如何用dplyr的across替代循环批量生成年度求和列?
问题:用dplyr高效生成年度行和汇总列
我需要用R的dplyr包,为数据集中的每个年度生成新列,新列的值是对应年度下季度末(Mar、Jun、Sep、Dec)各列的行求和结果。目前通过for循环可以实现需求,但希望找到更简洁高效的方案,比如使用across语句或map函数。
可复现示例代码
library(tidyverse) library(glue) # 创建示例数据集 set.seed(100) # 设置随机种子保证结果可复现 vars <- c("AgeGroup", paste0(month.abb[seq(3, 12, 3)], "_", rep(15:17, each = 4))) (df <- cbind(LETTERS[1:5], matrix(rpois(n = (length(vars) - 1) * 5, 30), nrow = 5)) %>% data.frame() %>% setNames(vars) %>% tibble() %>% mutate(across(-1, as.integer)) )
生成的数据集如下:
# A tibble: 5 × 13 AgeGroup Mar_15 Jun_15 Sep_15 Dec_15 Mar_16 Jun_16 Sep_16 Dec_16 Mar_17 Jun_17 Sep_17 Dec_17 <chr> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> 1 A 27 26 33 36 34 25 27 37 37 32 37 30 2 B 21 32 24 31 25 39 32 20 30 32 25 26 3 C 34 28 30 23 25 29 35 26 19 30 28 29 4 D 30 32 29 34 31 29 35 37 28 34 31 50 5 E 31 33 27 31 23 26 29 28 28 26 19 37
当前实现方式(for循环)
以下代码可以实现需求,但希望避免使用循环:
# 循环生成年度汇总列 for (i in 15:17) { df <- df %>% mutate("sum_{i}" := rowSums(across(ends_with(glue("_{i}"))))) } # 查看结果 df %>% select(AgeGroup, starts_with("sum"))
优化方案
方案1:使用map_dfc生成汇总列后合并
利用purrr::map_dfc批量生成各年度的行和列,再与原数据集绑定,代码更简洁:
years <- 15:17 # 批量生成年度汇总列 sum_columns <- map_dfc(years, function(year) { df %>% transmute(!!paste0("sum_", year) := rowSums(across(ends_with(paste0("_", year))))) }) # 合并到原数据集 df_final <- bind_cols(df, sum_columns)
方案2:长格式转换后计算再转宽
通过pivot_longer将数据转为长格式,按分组计算行和后再转回宽格式,最后与原数据合并,逻辑更清晰:
df_final <- df %>% # 转长格式,拆分月份和年份 pivot_longer(-AgeGroup, names_to = c("month", "year"), names_sep = "_") %>% # 按AgeGroup和年份分组求和 group_by(AgeGroup, year) %>% summarise(sum_val = sum(value), .groups = "drop") %>% # 转回宽格式,添加sum_前缀 pivot_wider(names_from = year, values_from = sum_val, names_prefix = "sum_") %>% # 合并到原数据集 left_join(df, .)
方案3:使用dplyr的across结合动态列名
利用across的动态选择和cur_column()提取年份,一次性生成所有汇总列:
df_final <- df %>% mutate( across( # 提取所有年度列的年份唯一值 unique(str_extract(names(.)[-1], "_\\d+$")), ~ rowSums(across(ends_with(.x))), .names = "sum{str_remove(.col, '_')}" ) )
以上三种方案都能替代for循环,实现高效生成年度行和汇总列的需求。
内容的提问来源于stack exchange,提问作者StatsStudent
相关产品推荐
相关产品推荐

