【问题标题】:Is there a way in data.table to collapse/summarize variables using objects, a la .SDcols?data.table 中是否有一种方法可以使用对象(例如 .SDcols)折叠/汇总变量?
【发布时间】:2021-12-28 13:01:06
【问题描述】:

我有一个包含多个变量的数据集,我想使用 data.table 折叠/汇总(取决于您的背景是更多的 Stata 还是 tidyverse),而不必在执行此操作的代码中命名每个单独的变量。

以下是一些示例数据:

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,但我无法做到在改变观察单位的同时找到一种方法来做到这一点。在理想的世界中,我会使用如下代码:

# 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

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

【问题讨论】:

  • dt[, lapply(.SD, sum, na.rm = TRUE), .SDcols = vars.to.collapse, by = 'year'] 甚至dt[, lapply(.SD, sum, na.rm = TRUE), .SDcols = 1:2, by = 'year']。学习help("data.table").
  • 这不允许命名新变量,对吧?
  • 嗨@dmcd,请找到您评论的完整答案。如果它满足您的需求,请考虑将此响应标记为“已接受”和/或“赞成”。如果没有,请告诉我出了什么问题。干杯。

标签: r data.table summarize


【解决方案1】:

为了跟进您关于命名新变量的评论,我建议使用 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

Reprex 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 创建于 2021-11-17 (v2.0.1)

【讨论】:

  • 啊,所以没有直接的方法可以做到这一点,基本上只有解决方法。谢谢
  • 嗨@dmcd。很高兴我能帮助你。只是一个小附录。我只是对使用bench 库的两个解决方案进行了一个小比较:解决方案 1 的运行速度比解决方案 2 快(大约快 1.8 倍)。我祝你工作顺利。干杯。
猜你喜欢
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
  • 2014-08-28
  • 2021-05-09
  • 2012-08-21
相关资源
最近更新 更多