data.table中如何借助对象类似.SDcols指定变量实现分组汇总?
data.table批量分组汇总(无需逐个写变量名)的实现方法
需求说明
需要对包含多变量的数据集进行分组汇总(对应Stata的collapse、tidyverse的summarize功能),提前定义要汇总的变量列表和生成的新变量名,无需在代码中逐个手动写明变量。
示例数据
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
预期结果
按year分组,对指定变量求和(忽略NA),生成规则命名的新变量:
# 手动写变量名的实现代码(目标效果) 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
预定义变量
提前定义要汇总的变量和新变量名:
vars.to.collapse <- c('v1', 'v2') new.v.names <- paste0('new', vars.to.collapse) new.v.names # [1] "newv1" "newv2"
错误写法说明
之前的写法直接对整个.SD求和,会将所有要汇总的列的数值整体相加得到单个值,因此只能得到一列结果:
# 错误写法 newdt <- dt[, .( (new.v.names = sum(.SD, na.rm = TRUE))), .SDcols = vars.to.collapse, by = 'year'] # 错误结果 # year V1 # 1: 1 11 # 2: 2 11 # 3: 3 30 # 4: 4 8
正确实现方法
使用lapply遍历.SD的每一列单独计算统计量,再用setNames为结果匹配预定义的新变量名即可:
newdt <- dt[, setNames(lapply(.SD, sum, na.rm = TRUE), new.v.names), by = year, .SDcols = vars.to.collapse] newdt # year newv1 newv2 # 1: 1 3 8 # 2: 2 5 6 # 3: 3 22 8 # 4: 4 0 8
扩展:多统计量批量汇总
如果需要同时计算多类统计量(如总和、均值、中位数等),可按如下方式扩展:
# 定义要计算的统计量函数列表 stats_funs <- list( sum = \(x) sum(x, na.rm = TRUE), mean = \(x) round(mean(x, na.rm = TRUE), 2) ) # 生成新变量名 new_v_names <- expand.grid(names(stats_funs), vars.to.collapse) |> apply(1, paste, collapse = "_") # 批量汇总 newdt_multi <- dt[, setNames( unlist(lapply(.SD, \(x) lapply(stats_funs, \(f) f(x))), recursive = FALSE), new_v_names ), by = year, .SDcols = vars.to.collapse] newdt_multi # year sum_v1 mean_v1 sum_v2 mean_v2 # 1: 1 3 1.50 8 4.00 # 2: 2 5 5.00 6 6.00 # 3: 3 22 7.33 8 4.00 # 4: 4 0 0.00 8 8.00
内容的提问来源于stack exchange,提问作者dmcd
相关产品推荐
相关产品推荐

