按列名称的data.table操作

sds*_*sds 12 r data.table

假设我有一个 data.table

a <- data.table(id=c(1,1,2,2,3),a=21:25,b=11:15,key="id")
Run Code Online (Sandbox Code Playgroud)

我可以像这样添加新列:

a[, sa := sum(a), by="id"]
a[, sb := sum(b), by="id"]
> a
   id  a  b sa sb
1:  1 21 11 43 23
2:  1 22 12 43 23
3:  2 23 13 47 27
4:  2 24 14 47 27
5:  3 25 15 25 15
Run Code Online (Sandbox Code Playgroud)

但是,假设我有列名:

for (n in c("a","b")) {
  s <- paste0("s",n)
  a[, s := sum(n), by="id", with=FALSE] # ERROR: invalid 'type' (character) of argument
}
Run Code Online (Sandbox Code Playgroud)

我该怎么办?

edd*_*ddi 11

你也可以这样做:

a <- data.table(id=c(1,1,2,2,3),a=21:25,b=11:15,key="id")

a[, c("sa", "sb") := lapply(.SD, sum), by = id]
Run Code Online (Sandbox Code Playgroud)

或稍微更一般:

cols.to.sum = c("a", "b")
a[, paste0("s", cols.to.sum) := lapply(.SD, sum), by = id, .SDcols = cols.to.sum]
Run Code Online (Sandbox Code Playgroud)


Mat*_*wle 8

这类似于:

如何在循环调用中使用data.table生成变量的线性组合和更新表?

但是你也希望将它结合起来by=,所以set()不够灵活.这是一个刻意的设计设计,set()在这方面不太可能改变.

我有时会EVAL在答案的最后使用帮助器.
/sf/answers/1456600141/
在这种方法上有些畏缩,但我只是把它想象成构建一个动态SQL语句,这是很常见的做法.该EVAL方法提供了不挠头约最大的灵活性eval()quote().要查看已构造的动态查询(检查它),您可以printEVAL辅助函数中添加一个内部.

但是,在这个简单的例子中,您可以:=用括号包装LHS 来告诉data.table查找值(更清晰with=FALSE),并且RHS需要a get().

for (n in c("a","b")) {
  s <- paste0("s",n)
  a[, (s) := sum(get(n)), by="id"]
}
Run Code Online (Sandbox Code Playgroud)