R:data.table与merge(aggregate())性能

时间:2016-02-05 11:40:42

标签: r data.table

或者更为一般,它是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 

通常对data.table性能没有任何问题,我对这个特定的例子感到惊讶。我不得不通过仅采用某些事件类型的最新(可以同时)出现来对一个相当大的数据帧进行子集(聚合)。并保留这些特定事件的其余相关数据。但是,似乎.SD在这个特定的应用程序中不能很好地扩展。

是否有更好的“数据表方式”来处理这类任务?

1 个答案:

答案 0 :(得分:8)

我们可以使用.I获取行索引并根据该行对其进行子集化。它应该更快。

system.time(df[df[,.I[d == max(d)], by = c]$V1])
#    user  system elapsed 
#   5.00    0.09    5.30 

@Heroka的解决方案

system.time(df[,is_max:=d==max(d), by = c][is_max==T,])
#   user  system elapsed 
#  5.06    0.00    5.12 

我机器上的aggregate方法提供了

system.time(merge(aggregate(d ~ c, data = df, max), df))
#   user  system elapsed 
#  48.62    1.00   50.76 

使用.SD选项

system.time(df[,.SD[d == max(d)], by = c])
#   user  system elapsed 
# 151.13    0.40  156.57 

使用data.table加入

system.time(df[df[, list(d=max(d)) , c], on=c('c', 'd')])
#   user  system elapsed 
#   0.58    0.01    0.60 

如果我们查看merge/aggregate==之间的比较,它们就是不同的功能。通常,与aggregate/merge的相应联接相比,data.table方法会更慢。但是,我们正在使用==来比较每一行(需要一些时间)和.SD进行子集化(与行{1}}进行比较时,对于行索引也相对效率相对较低)。 .I也有.SD的开销。