微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

data.table分别对数字和文本变量进行分组

我正在尝试简化这个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开始.最近在当前开发版本中修复了该错误.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐