8

我很惊讶地做了以下事情:

R) system.time(lastOrder <- order[,lapply(.SD,tail,1),by="TRADER_ID,EXEC_IDATE"]);
utilisateur     système      écoulé 
       1.45        0.00        1.53 
R) nrow(order)
[1] 75301
R) ncol(order)
[1] 23

以为很长,然后我做了

R) system.time(lastOrder <- order[,list(test=tail(EXEC_IDATE,1)),by="TRADER_ID,EXEC_IDATE"]);
utilisateur     système      écoulé 
       0.14        0.00        0.14 

据我了解,如果您知道要选择的所有行并完成大部分工作,那么我不明白为什么将其应用于所有列应该长 10 倍。我在第一段代码上做错了吗,这是我知道按组选择最后一行的唯一方法

4

2 回答 2

10

按组的最后一行:

DT[, .SD[.N], by="TRADER_ID,EXEC_IDATE"]            # (1)

或者,更快(尽可能避免使用.SD,以提高速度):

w = DT[, .I[.N], by="TRADER_ID,EXEC_IDATE"][[3]]    # (2)
DT[w]

请注意,以下功能请求将使方法 (1) 与方法 (2) 一样快:

FR#2330 优化 .SD[i] 查询以保持优雅但使其更快不变。

于 2013-01-04T10:56:41.627 回答
3

这样的事情怎么样?(合成数据旨在模仿我可以从问题中推断出的关于您的信息)

tmp <- data.table(id = sample(1:20, 1e6, replace=TRUE),
                  date = as.Date(as.integer(runif(n=1e6, min = 1e4, max = 1.1e4)),
                                 origin = as.Date("1970-01-01")),
                  data1 = rnorm(1e6),
                  data2 = rnorm(1e6),
                  data3 = rnorm(1e6))

> system.time(X <- tmp[, lapply(.SD, tail, 1), by = list(id, date)])
  user  system elapsed 
  1.95    0.00    1.95

> system.time(Y <- tmp[, list(tail(data1, 1)), by = list(id, date)])
  user  system elapsed 
  1.24    0.01    1.26 

> system.time({
    setkey(tmp, id, date)
    Z <- tmp[unique(tmp)[, key(tmp), with=FALSE], mult="last"]
})
  user  system elapsed 
  0.90    0.02    0.92 

保证相同顺序后 X 和 Z 相同:

> identical(setkey(X, id, date), setkey(Z, id, date))
[1] TRUE

lapply tailmy和 1-column之间的差异tail没有你的那么大,但是没有你的数据结构,很难说更多。

另外,请注意,此方法中的大部分时间都是设置密钥。如果表已经按分组列排序,它会非常快:

> system.time(Z <- tmp[unique(tmp)[, key(tmp), with=FALSE], mult="last"])
  user  system elapsed 
  0.03    0.00    0.03 

或者,您可以使用临时列将多列问题转换为 1 列问题:

> system.time({
  tmp[, row.num := seq_len(nrow(tmp))]
  W <- tmp[tmp[, max(row.num), by = list(id, date)]$V1][, row.num := NULL]
  tmp[, row.num := NULL]
})
user  system elapsed 
0.92    0.00    1.09 

> identical(setkey(X, id, date), setkey(W, id, date))
[1] TRUE
于 2013-01-03T17:38:43.603 回答