R中使用group_by、summarise遍历字符向量实现动态分组统计
R语言dplyr动态分组统计多变量的实现方案
推荐使用dplyr内置的across语法实现,无需写循环,代码更简洁易维护,也可以按需使用循环实现:
方法1:dplyr::across实现(推荐)
先封装单变量的统计逻辑,再批量作用到指定的所有变量上:
library(dplyr) # 自定义单变量统计函数,封装最大值、第二大值、求和逻辑 calc_stats <- function(x) { # 先去重再降序排序,避免组内有多个相同最大值时第二大值计算异常 sorted_unique <- sort(unique(x), decreasing = TRUE, na.last = NA) tibble( MaxVal = sorted_unique[1], MAXsecVal = sorted_unique[2], Sum = sum(x, na.rm = TRUE) ) } # 传入需要统计的变量向量 var <- c("hp", "drat", "wt") # 批量统计 df <- mtcars %>% group_by(cyl) %>% summarise( across(all_of(var), calc_stats, .names = "{.col}_{.fn}") ) %>% arrange(cyl)
运行后每个指定变量会生成对应的三列统计结果,例如hp_MaxVal、hp_MAXsecVal、hp_Sum,和你原有逻辑的计算结果完全一致。如果需要转为长表更方便查看,可以追加一步格式转换:
df_long <- df %>% tidyr::pivot_longer( cols = -cyl, names_to = c("variable", ".value"), names_sep = "_" )
方法2:循环实现
如果偏好循环写法,可以通过动态取列语法.data[[列名字符串]]实现:
library(dplyr) var <- c("hp", "drat", "wt") result_list <- list() for (v in var) { tmp <- mtcars %>% group_by(cyl) %>% summarise( variable = v, MaxVal = max(.data[[v]], na.rm = T), MAXsecVal = max(.data[[v]][.data[[v]] != max(.data[[v]], na.rm = T)], na.rm = F), Sum = sum(.data[[v]], na.rm = T) ) result_list[[v]] <- tmp } # 合并所有变量的统计结果 df <- bind_rows(result_list) %>% arrange(cyl, variable)
注意事项
- 用
all_of(var)包裹变量向量是dplyr官方推荐的写法,可以避免环境变量冲突的警告 .data[[变量名字符串]]是dplyr中动态取列的标准语法,适合在循环、自定义函数内调用- 第二大值的计算建议使用去重后排序的写法,替代原有
max(hp[hp != max(hp)])的逻辑,避免当组内存在多个相同最大值时,返回次高的重复值而非第二大的不同值
内容的提问来源于stack exchange,提问作者Hekmek
相关产品推荐
相关产品推荐

