我正在尝试简化这个data.table两阶段过程,它同时作用于数字和字符变量.例如. – 获取textvar的第一个元素并对每个数字变量求和.考虑这个小例子:
library(data.table) dt <- data.table(grpvar=letters[c(1,1,2)],textvar=c("one","two","one"),numvar=1:3,othernum=2:4) dt # grpvar textvar numvar othernum #1: a one 1 2 #2: a two 2 3 #3: b one 3 4
现在我的第一个想法是嵌套.SD将一个变量从lapply调用中删除,但我认为这有点复杂:
dt[,c(textvar=textvar[1],.SD[,lapply(.SD,sum),.SDcols=-c("textvar")]),by=grpvar] # grpvar textvar numvar othernum #1: a one 3 5 #2: b one 3 4
然后我想也许我可以单独分组并加入它们,但这似乎更糟糕:
dt[,.(textvar=textvar[1]),by=grpvar][ dt[,by=grpvar,.SDcols=-c("textvar")],on="grpvar" ] # grpvar textvar numvar othernum #1: a one 3 5 #2: b one 3 4
是否有更简单的结构可以绕过.SD或加入的嵌套?我觉得我忽略了一些基本的东西.
解决方法
data.table中的j参数(故意)非常灵活.我们需要记住的是:
As long as
j
returns a list,each element of the list will become a column in the resulting data.table.
使用c(list,list)是一个列表的事实,我们可以构造如下表达式:
dt[,c(textvar = textvar[1L],sum)),# select/compute all cols necessary .SDcols = numvar:othernum,# provide .SD's columns by = grpvar] # group by 'grpvar' # grpvar textvar numvar othernum # 1: a one 3 5 # 2: b one 3 4
这里,我没有用list()包装第一个表达式,因为textvar [1L]返回一个length = 1的向量..即,相同(c(1,list(2,3)),c(list(1),3)))为TRUE.
请注意,这只能从v1.9.7开始.最近在当前开发版本中修复了该错误.