使用data.table聚合或聚合并与一对多变量合并是否更快?

时间:2018-03-26 18:06:42

标签: r data.table

我有data.table,如下所示:

dt <- data.table(data.frame(
  id = rep(1:3, each=5),
  age = rep(10*(2:4), each=5),
  var = rnorm(15)
))

我希望使用总和超过var,但是我必须在输出中将“年龄”保持为一对多变量。

一种方法是:

dt <- merge(dt[, .(vsum=sum(var)), by=id], unique(dt[, c('id', 'age']), by='id')

另一种方式是

dt <- dt[, .(vsum=sum(var)), by=c('id', 'age')]

我的直觉说第二种情况会失去时间,因为by=age内查找ids的不同值,如果age是20个或更多变量,这可能会有问题。我的直觉说merge是有问题的,因为总体上更多的操作,而by=个实例中只有一部分是[.data.table

我可以探索这样的愚蠢案例,但是没有一般操作特性的意义1.当有许多多对一变量(如年龄),以及数据密集时观察(许多行和几个ID)或密集的个人(相同的N行但很多ID)

是否有任何通用,有效的方法来执行此类型的摘要数据集?

1 个答案:

答案 0 :(得分:2)

这完全取决于实施。但是,为什么不这样做呢?

dt[, .(vsum=sum(var), age=age[1]), by="id"]

编辑:下面的基准测试。

dt <- data.table(data.frame(
  id = rep(1:10000, each=5),
  age = rep(10*(1:10000), each=5),
  var = rnorm(150000)
))

res1 <- function() {merge(dt[, .(vsum=sum(var)), by="id"], unique(dt[, c('id', 'age')]), by='id')}
res2 <- function() {dt[, .(vsum=sum(var)), by=c('id', 'age')]}
res3 <- function() {dt[, .(vsum=sum(var), age=unique(age)), by="id"]}
res4 <- function() {dt[, .(vsum=sum(var), age=age[1]), by="id"]}

library(microbenchmark)
microbenchmark(res1(),res2(), res3(), res4(), times=10)

Unit: milliseconds
   expr       min        lq      mean    median        uq       max neval cld
 res1()  6.940417  7.949203  9.250408  8.791923  9.695110 13.448288    10  b 
 res2()  3.796992  3.898165  4.889812  4.507141  4.790384  9.477044    10 a  
 res3() 48.259783 52.026664 55.401017 54.986112 59.375380 60.804102    10   c
 res4()  2.646796  2.853593  3.709116  3.252362  3.391909  6.321708    10 a 

事实证明,与直觉相反,第二种方法相当快,最快的是第四种方法。