有没有办法在 data.table 到 collapse/summarize 变量中使用对象,la .SDcols?

Is there a way in data.table to collapse/summarize variables using objects, a la .SDcols?

我有一个包含多个变量的数据集,我想 collapse/summarize(取决于你的背景是 Stata 还是 tidyverse)使用 data.table,而不必在代码中命名每个单独的变量这样做。

下面是一些示例数据:

library(data.table)

dt <- data.table(v1 = c(1,2,5,8,5,9, NA),
                 v2 = c(5,3,6,1, NA,7,8),
                 year = c(1,1,2,3,3,3,4))

dt
    v1 v2 year
1:  1  5    1
2:  2  3    1
3:  5  6    2
4:  8  1    3
5:  5 NA    3
6:  9  7    3
7: NA  8    4

这是我想要的最终数据集:

# this is the final data we want:
dt[, .(newv1 = sum(v1, na.rm = TRUE),
       newv2 = sum(v2, na.rm = TRUE)),
   by = 'year']

    year newv1 newv2
1:    1     3     8
2:    2     5     6
3:    3    22     8
4:    4     0     8

实际数据集有很多我想总结的变量,所以我想事先在折叠之外的列表中命名变量,然后以系统的方式命名它们,例如:

# but we want to do it with objects e.g.:
vars.to.collapse <- c('v1', 'v2')
new.v.names <- paste0('new', vars.to.collapse)

new.v.names
[1] "newv1" "newv2"

我知道你可以做这种事情——也就是说,使用对象创建多个变量——使用 .SD 当你是 adding/modifying 变量时使用 := 运算符, 但我一直没能找到一种方法来改变观察单位。在理想的世界中,我会使用如下代码:

# want something like this but it doesn't work:
newdt <- dt[, .( (new.v.names = sum(.SD, na.rm = TRUE))),
              .SDcols = vars.to.collapse,
              by = 'year']

# not what I want:
newdt
     year V1
1:    1 11
2:    2 11
3:    3 30
4:    4  8

但这不会生成我在上面向您展示的包含新变量名称和所有内容的数据集。我可以通过使用 := 运算符将这些统计信息添加到数据集中然后删除重复项或其他内容来解决这个问题,但如果可能的话我更愿意直接总结。

为了跟进您关于命名新变量的评论,我建议使用 data.table 库的两种解决方案。

所以,请在下面找到两个代表。

Reprex 1(作为@Roland 提出的解决方案的后续)

  • 代码
library(data.table)

vars.to.collapse <- c('v1', 'v2') # your code
new.v.names <- paste0('new', vars.to.collapse) # your code

dt <- dt[, lapply(.SD, sum, na.rm = TRUE), .SDcols = vars.to.collapse, by = 'year'] # Roland's code

setnames(dt, c("year", new.v.names))
  • 输出
dt
#>     year newv1 newv2
#> 1:     1     3     8
#> 2:     2     5     6
#> 3:     3    22     8
#> 4:     4     0     8

代表 2

  • 代码
library(data.table)

vars.to.collapse <- c('v1', 'v2')  # your code
new.v.names <- paste0('new', vars.to.collapse) # your code

dt[, lapply(.SD, sum, na.rm = TRUE), .SDcols = vars.to.collapse, by = 'year'
   ][, (new.v.names) := .SD, .SDcols = vars.to.collapse
     ][, .SD, .SDcols = !patterns("^v")][]
  • 输出
#>    year newv1 newv2
#> 1:    1     3     8
#> 2:    2     5     6
#> 3:    3    22     8
#> 4:    4     0     8

reprex package (v2.0.1)

于 2021-11-17 创建