为所有列的数据表按组选择最后一行

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倍的时间。在第一段代码中我做错了什么吗?这是我所知道的按组选择最后一行的唯一方法。
2个回答

11

1
也许这样更好 w = DT[, list(IDX=.I[.N]), by="TRADER_ID,EXEC_IDATE"]$IDXDT[w] - statquant
1
看起来功能请求现在已经在这里(https://github.com/Rdatatable/data.table/issues/613),并计划用于data.table v. 2.0。 - C8H10N4O2

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 和 1 列的 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

除了 @user1935457 外, Z1 <- tmp[, lapply(.SD, last), by = .(id, date)]) 执行相同的操作,并且与 X <- tmp[, lapply(.SD, tail, 1), by = list(id, date)] 的速度一样快。 - nachti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接