R语言中按组对多列进行汇总统计的高效实现方法
高效实现多分组列的汇总统计
问题描述
我有一个包含学生基础信息的dataframe,想要获取Age、Sex以及GroupMath、GroupEng、GroupScie、GroupChine各分组的汇总统计信息。目前我通过重复代码分别处理每个分组列,效率很低,想知道更高效的实现方式。
测试数据
set.seed(500) testdf <- data.frame(ID = paste0("Stu", c(1:10)), Age = sample(18:25, 10, replace = T), Sex = sample(c("Boy", "Girl", "NA"), 10, replace = T), Name = c("Pwyll","Flavian","Leehi","Zuzana","Aniya","Bogomil" ,"Lameez","Prudencia","Ikuo","Grayson"), GroupMath = sample(LETTERS[1:2], 10, replace = T), GroupEng = sample(LETTERS[1:2], 10, replace = T), GroupScie = sample(LETTERS[1:2], 10, replace = T), GroupChine = sample(LETTERS[1:2], 10, replace = T))
现有单分组处理代码
# 统计GroupMath分组的样本量 N.math <- testdf %>% group_by(GroupMath) %>% count(GroupMath) # 统计GroupMath分组下Age的均值、最大/最小值、标准差 Age.math <- testdf %>% group_by(GroupMath) %>% summarize( Mean = mean(Age), Max = max(Age), Min = min(Age), sd = sd(Age)) # 统计GroupMath分组下Sex的分布 Sex.math <- testdf %>% group_by(GroupMath) %>% count(Sex)
高效实现方式
利用tidyverse的长格式转换+批量分组统计,可以避免重复编写代码,一次处理所有分组列。
方案1:整合所有统计结果到单一数据框
library(tidyverse) # 将所有分组列转为长格式,统一处理 testdf_long <- testdf %>% pivot_longer( cols = starts_with("Group"), names_to = "Subject", values_to = "Group" ) # 计算核心统计量(样本量、Age指标) base_stats <- testdf_long %>% group_by(Subject, Group) %>% summarize( N = n(), Age_Mean = mean(Age), Age_Max = max(Age), Age_Min = min(Age), Age_SD = sd(Age), .groups = "drop" ) # 计算Sex分布并合并到结果中 final_stats <- base_stats %>% left_join( testdf_long %>% group_by(Subject, Group, Sex) %>% count(name = "Count") %>% pivot_wider(names_from = Sex, values_from = Count, values_fill = 0), by = c("Subject", "Group") ) # 查看最终结果 print(final_stats)
方案2:按科目拆分输出独立统计结果
如果需要保留原代码中按单个分组列输出的结构,可以用map批量处理:
# 按科目拆分数据 subject_groups <- testdf_long %>% group_by(Subject) %>% group_split() # 批量生成每个科目的三类统计结果 output_list <- map(subject_groups, function(subj_df) { subj_name <- unique(subj_df$Subject) list( N = subj_df %>% count(Group), Age_stats = subj_df %>% group_by(Group) %>% summarize(Mean = mean(Age), Max = max(Age), Min = min(Age), sd = sd(Age)), Sex_dist = subj_df %>% group_by(Group) %>% count(Sex) ) %>% set_names(paste0(subj_name, "_", names(.))) }) %>% flatten() # 调用示例:查看数学分组的Age统计结果 output_list$GroupMath_Age_stats
说明
- 两种方案都通过
starts_with("Group")自动匹配所有分组列,后续新增分组列无需修改代码; - 方案1适合将所有统计结果整合到一个数据框,方便后续分析或导出;
- 方案2保留了与原代码类似的拆分结构,同时实现了批量处理。
内容的提问来源于stack exchange,提问作者mashimena
相关产品推荐
相关产品推荐

