您对j
组件的处理方法不是data.table
母语
值得一读data.table wiki on do's and don't about data.table 语法(使用data.frame
是可怕的!,就性能而言)。
您也可以参考 这个问题,也许您会开始了解使用j
和list
工作原理。
- 您正在传递将在 data.table (或其分组子集)中评估的表达式列表
- 这些是未评估的表达式,并且(当前)该函数
[
依赖于观察list
在正确的环境中正确评估这些(data.table
或.SD
,组子集)
这个电话会起作用
dtb[,list(a = a+1, b = b + 1, c = c+1), by = id]
这也一样(传递一个未评估的表达式,它恰好是对list(...)
library(plyr) # for as.quoted
my_list <- as.quoted(paste('list(',paste(letters[1:3], '=', letters[1:3], '+1',collapse= ','),')'))[[1]]
my_list
## list(a = a + 1, b = b + 1, c = c + 1)
dtb[,eval(my_list), by = id]
还可以将调用 与lapply(.SD, a_function)
结合起来.SDcols
。该.SDcols
参数允许您传递希望对函数进行评估的列名字符串,因此这将起作用
dtb[, lapply(.SD,base::'+',1),by= id, .SDcols = c('a','b','c')]
或者
dtb[,lapply(.SD, .Primitive('+'),1), by= id, .SDcols = c('a','b','c')]
请注意,我调用了base::'+'
or.Primitive('+')
而不是'+'
,因为 data.table 无法'+'
作为函数找到
基准测试
对这些解决方案进行基准测试
benchmark(
lstdt=dtb[ , flst(.SD), by=id],
dfdt=dtb[ , fdf(.SD), by=id],
lapplySD = dtb[, lapply(.SD,base::'+',1),by= id, .SDcols = c('a','b','c')],
lapplySD2 = dtb[, lapply(.SD,.Primitive('+'),1),by= id, .SDcols = c('a','b','c')]
just_list = dtb[,list(a = a+1,b=b+1,c=c+1),b=id],
eval_mylist = dtb[,eval(my_list),b=id],
replications=10^2
## test replications elapsed relative user.self
## 2 dfdt 100 0.36 4.000000 0.34
## 6 eval_mylist 100 0.09 1.000000 0.10
## 5 just_list 100 0.11 1.222222 0.10
## 3 lapplySD 100 0.14 1.555556 0.14
## 4 lapplySD2 100 0.11 1.1 0.11
## 1 lstdt 100 0.18 2.000000 0.17