我有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)
是否有任何通用,有效的方法来执行此类型的摘要数据集?
答案 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
事实证明,与直觉相反,第二种方法相当快,最快的是第四种方法。