或者更为一般,它是DT[,.SD[...],by=...]对抗merge(aggregate(...)).
不用多说了,这里有数据和示例:
set.seed(5141)
size = 1e6
df <- data.table(a = rnorm(size),
b = paste0(sample(letters, size, T),
sample(letters, size, T),
sample(letters, size, T)),
c = sample(1:(size/10), size, T),
d = sample(seq.Date(as.Date("2015-01-01"),
as.Date("2015-05-31"), by="day"), size, T))
system.time(df[,.SD[d == max(d)], by = c])
# user system elapsed
# 50.89 0.00 51.00
system.time(merge(aggregate(d ~ c, data = df, max), df))
# user system elapsed
# 18.24 0.20 18.45
Run Code Online (Sandbox Code Playgroud)
通常对data.table性能没有任何问题,我对这个特殊的例子感到惊讶.我不得不通过仅采用某些事件类型的最新(可以同时)出现来对一个相当大的数据帧进行子集(聚合).并保留这些特定事件的其余相关数据.但是,似乎.SD在这个特定应用中不能很好地扩展.
是否有更好的"数据表方式"来处理这类任务?
我们可以.I用来获取行索引并根据它来对行进行子集化.它应该更快.
system.time(df[df[,.I[d == max(d)], by = c]$V1])
# user system elapsed
# 5.00 0.09 5.30
Run Code Online (Sandbox Code Playgroud)
@Heroka的解决方案
system.time(df[,is_max:=d==max(d), by = c][is_max==T,])
# user system elapsed
# 5.06 0.00 5.12
Run Code Online (Sandbox Code Playgroud)
aggregate我机器上的方法给出了
system.time(merge(aggregate(d ~ c, data = df, max), df))
# user system elapsed
# 48.62 1.00 50.76
Run Code Online (Sandbox Code Playgroud)
有.SD选项
system.time(df[,.SD[d == max(d)], by = c])
# user system elapsed
# 151.13 0.40 156.57
Run Code Online (Sandbox Code Playgroud)
使用data.table连接
system.time(df[df[, list(d=max(d)) , c], on=c('c', 'd')])
# user system elapsed
# 0.58 0.01 0.60
Run Code Online (Sandbox Code Playgroud)
如果我们看一下merge/aggregate和之间的比较==,它们就是不同的功能.通常,aggregate/merge与相应的连接相比,该方法会更慢data.table.但是,我们正在使用==它来比较每一行(需要一些时间)以及.SD子集化(与.I行索引相比,它的效率也相对较低).该.SD还的开销[.data.table.