使用data.table选择最后一行替代第一行。

4

在一个具有键值的数据表上调用unique函数,你将会得到每个分组下唯一的行。在存在重复行时,将会选择第一行。在我需要选择最后一行时(通常是最后的时间交易),我使用.SD[.N]

library(data.table)
library(microbenchmark)

dt <- data.table(id=sample(letters, 10000, T), var=rnorm(10000), key="id")

microbenchmark(unique(dt), dt[, .SD[.N], by=id])
Unit: microseconds
                   expr      min        lq    median       uq        max neval
             unique(dt)  570.882  586.1155  595.8975  608.406   3209.122   100
 dt[, .SD[.N], by = id] 6532.739 6637.7745 6694.3820 6776.968 208264.433   100

你知道更快的方法来完成同样的事情吗?


我很惊讶unique.data.tableduplicated.data.table不支持fromLast参数,就像unique.data.frameduplicated.data.frame一样。 - GSee
3个回答

8
创建一个包含关键变量的唯一组合的数据表,然后使用“mult = 'last'”进行连接。
使用“.SD”很方便,但速度较慢。如果您愿意,可以使用“.I”代替。
dtu <- unique(dt)[,key(dt), with = FALSE]
dt[dtu, mult = 'last']

或者

 dt[ dt[,  .I[.N], by = key(dt)]$V1]

@Farrel 在 ?data.table(在 by 下)(`.I 是一个整数向量,长度为 .N,保存了该组在 x 中的行位置) - mnel
这非常聪明,我认为。这就是正在发生的事情吗?该代码创建了一个向量,其中包含dt中包含第N个组实例的行号,其中组是由键定义的唯一条目的集合。 - Farrel

4

data.table v1.9.4 版本开始,您可以使用 fromLast = TRUE 参数。

microbenchmark(unique(dt, by = "id"), 
               dt[, .SD[.N], by=id], 
               unique(dt, by = "id", fromLast = TRUE))

Unit: microseconds
                                   expr     min       lq     mean   median       uq      max neval cld
                  unique(dt, by = "id") 333.978 355.1900 406.1585 371.1360 393.4015 3203.769   100  a 
                 dt[, .SD[.N], by = id] 519.320 541.4345 580.2176 553.6200 563.5490 2690.167   100   b
 unique(dt, by = "id", fromLast = TRUE) 338.190 366.4725 430.1296 380.9145 400.7730 4774.663   100  a 

0

这里有另一个选项,尽管它看起来比 @mnel 的答案略慢,至少对于这个例子是这样。

dt[,list(var,RN=.N:1),by=id][RN==1L]

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