R语言dplyr中高效批量求和变量及按年份合并变量的方法
R语言高效实现多变量求和(无循环方案)
原始数据生成
先运行以下代码创建包含avar_YYYY、bvar_YYYY格式列的DataFrame:
library(dplyr) avar_2000 <- c(2,5,1) avar_2001 <- c(2,3,1) avar_2002 <- c(7,2,5) bvar_2000 <- c(9,1,1) bvar_2001 <- c(5,5,3) bvar_2002 <- c(3,8,NA) df <- data.frame(avar_2000,avar_2001,avar_2002,bvar_2000,bvar_2001,bvar_2002) print(df)
生成的DataFrame如下:
| avar_2000 | avar_2001 | avar_2002 | bvar_2000 | bvar_2001 | bvar_2002 |
|---|---|---|---|---|---|
| 2 | 2 | 7 | 9 | 5 | 3 |
| 5 | 3 | 2 | 1 | 5 | 8 |
| 1 | 1 | 5 | 1 | 3 | NA |
现有部分实现代码
目前已实现的求和代码如下:
bvars <- c("bvar_2000","bvar_2001","bvar_2002") df2 <- df %>% mutate(avar_sum = avar_2000 + avar_2001 + avar_2002) %>% rowwise() %>% mutate(bvar_sum = sum(across(all_of(bvars)))) print(df2)
得到结果:
| avar_2000 | avar_2001 | avar_2002 | bvar_2000 | bvar_2001 | bvar_2002 | avar_sum | bvar_sum |
|---|---|---|---|---|---|---|---|
| 2 | 2 | 7 | 9 | 5 | 3 | 11 | 17 |
| 5 | 3 | 2 | 1 | 5 | 8 | 10 | 14 |
| 1 | 1 | 5 | 1 | 3 | NA | 7 | NA |
问题1:批量按前缀生成求和列
需要简洁代码(无需逐个指定列),批量将所有avar_前缀的列求和生成avar_sum,所有bvar_前缀的列求和生成bvar_sum。
解决方案
利用dplyr的across结合rowSums实现,无需手动指定列名或使用rowwise(rowSums比rowwise+sum效率更高):
df2 <- df %>% mutate( # 按前缀匹配avar列,求和生成avar_sum,保留NA逻辑与原代码一致 avar_sum = rowSums(across(starts_with("avar_")), na.rm = FALSE), # 同理处理bvar列 bvar_sum = rowSums(across(starts_with("bvar_")), na.rm = FALSE) ) print(df2)
starts_with("avar_")会自动匹配所有以avar_开头的列,无需手动罗列na.rm = FALSE表示遇到NA时求和结果为NA,若需忽略NA求和,改为na.rm = TRUE即可
问题2:批量生成同年份的avar与bvar求和列
无需循环及手动逐行编写,将同一年份的avar_YYYY与bvar_YYYY列相加生成cvar_YYYY列。
解决方案1:利用列名匹配+cur_column()(简洁高效)
通过across遍历avar_前缀列,结合cur_column()动态匹配对应年份的bvar列,自动生成cvar_YYYY列:
df2 <- df %>% # 批量生成cvar列 mutate( across(starts_with("avar_"), ~ . + get(sub("avar", "bvar", cur_column())), .names = "cvar_{sub('avar_', '', .col)}") ) %>% # 加上问题1的求和列 mutate( avar_sum = rowSums(across(starts_with("avar_")), na.rm = FALSE), bvar_sum = rowSums(across(starts_with("bvar_")), na.rm = FALSE) ) print(df2)
sub("avar", "bvar", cur_column())将当前遍历的avar_YYYY列名替换为bvar_YYYY.names = "cvar_{sub('avar_', '', .col)}"自动生成cvar_YYYY格式的新列名
解决方案2:长格式重塑计算(逻辑直观,扩展性强)
通过tidyr的重塑函数将宽格式转长格式,计算后再转回宽格式,适合后续需要扩展更多变量的场景:
library(tidyr) df2 <- df %>% # 宽转长:拆分列名为变量类型和年份 pivot_longer(everything(), names_to = c("var", "year"), names_sep = "_", values_to = "value") %>% # 长转宽:将avar、bvar列为单独列 pivot_wider(names_from = var, values_from = value) %>% # 计算同年份的cvar mutate(cvar = avar + bvar) %>% # 长转长:合并变量列 pivot_longer(c(avar, bvar, cvar), names_to = "var", values_to = "value") %>% # 长转宽:转回原始宽格式,新增cvar列 pivot_wider(names_from = c(var, year), values_from = value) %>% # 加上求和列 mutate( avar_sum = rowSums(across(starts_with("avar_")), na.rm = FALSE), bvar_sum = rowSums(across(starts_with("bvar_")), na.rm = FALSE) ) print(df2)
内容的提问来源于stack exchange,提问作者Andre
相关产品推荐
相关产品推荐

