【问题标题】:R: data.table vs merge(aggregate()) performanceR:data.table 与合并(聚合())性能
【发布时间】:2016-02-05 20:26:38
【问题描述】:

或者更笼统地说,是 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 在这个特定的应用程序中似乎不能很好地扩展。

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

【问题讨论】:

  • 有趣的是,df[,is_max:=d==max(d), by = c][is_max==T,] 在我的机器上运行得非常快。
  • 这似乎是迄今为止最快的解决方案。是否可以在不创建额外列的情况下做同样的事情?
  • 我不知道,你可以随时删除它df[,is_max:=d==max(d), by = c][is_max==T,][, is_max:=NULL,]。 @Akrun 提供的 join-solution 是迄今为止最快的。

标签: r data.table


【解决方案1】:

我们可以使用.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 进行子集设置(与.I 进行行索引相比效率相对较低)。 .SD 也有[.data.table 的开销。

【讨论】:

  • 我认为加入解决方案缺少一些东西。和可疑的好结果。同时,我将研究.I 解决方案。感谢您提供整个阵列来尝试。
  • @A.Val。如果您查看语法,我使用的是on。您可以在较小的数据集上测试解决方案
  • &gt; nrow(df[df[, list(d=max(d)) , c], on='c']) [1] 1000000
  • @A.Val。谢谢你的信息,我会调查的,
  • @A.Val。尝试使用 on= c('c', 'd') 它给出与其他结果相同的 nrow。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-29
  • 2015-02-17
  • 2016-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多