在 data.table 中按 n 个不同的组创建 n 个新列

Create n new columns by n distinct groups in data.table

我有以下数据 table,我想对 y 求和两次,将 first 时间按 g1 和 second[=33 分组=] 时间按 g2.

通常我只是将计算链接在一起,但我希望能够通过 n[=33= 进行不同时间的分组总和 n ]组。

library(data.table)
  DT <- data.table(
    g1 = c("a", "b"),
    g2 = c("a", "a"),
    y = c(3,5)
  )

new_cols <- paste0("sum_by_", c("g1", "g2"))
group_cols <- c("g1", "g2")

# Supplying cols to by like this groups by g1 AND g2, when in reality I want it to 
# take g1 the first time and g2 the second time. 
DT[, paste(new_cols) := lapply(rep(y, length(new_cols)), sum),
   by = .(group_cols)][]

这给了我:

#    g1 g2 y sum_by_g1 sum_by_g2
# 1:  a  a 3         3         3
# 2:  b  a 5         5         5

当我真正想要的时候:

#    g1 g2 y sum_by_g1 sum_by_g2
# 1:  a  a 3         3         8
# 2:  b  a 5         5         8

有没有巧妙的 data.table 方法来做到这一点? 提供 .SD 的东西(这本身似乎不起作用)?

编辑:将 y 从 c(1,1) 更改为 c(3,5)

编辑理由:y = c(1,1) 时的实际输出和期望输出给人的印象是我想计算每个组中的观察值,而实际上我想对每个组求和 (y)。

分组应分开,因为 a aa b 被视为唯一元素,因此每组只有一个观察值

for(i in seq_along(group_cols)) DT[, (new_cols[i]) := sum(y), by = c(group_cols[i])]

-输出

DT
   g1 g2 y sum_by_g1 sum_by_g2
1:  a  a 3         3         8
2:  b  a 5         5         8

您可以像下面那样尝试Reduce

> Reduce(function(dt, g) dt[, paste0("sum_by_", g) := .N, g], list(DT, "g1", "g2"))[]
   g1 g2 y sum_by_g1 sum_by_g2
1:  a  a 1         1         2
2:  b  a 1         1         2

> Reduce(function(dt, g) dt[, paste0("sum_by_", g) := .N, g], c("g1", "g2"),init = DT)[]
   g1 g2 y sum_by_g1 sum_by_g2
1:  a  a 1         1         2
2:  b  a 1         1         2