如何在dplyr::summarise中用向量元素生成分组均值变量?
问题:在dplyr::summarise中通过向量动态生成汇总变量
数据集与需求
给定数据集:
df_x <- data.frame(year = c(2000, 2000, 2000, 2001, 2001, 2001, 2002, 2002, 2002), a = c(7, 3, 5), b = c(5, 8, 1), c = c(8, 4, 3))
以及变量名向量:
v <- c("a", "b", "c")
需求是按year分组,生成y_a、y_b、y_c三个新变量,分别对应a、b、c的均值。直接写固定变量的代码可实现需求:
y <- df_x %>% group_by(year) %>% dplyr::summarise(y_a = mean(a, na.rm = TRUE), y_b = mean(b, na.rm = TRUE), y_c = mean(c, na.rm = TRUE))
但尝试通过向量v动态生成变量时出现错误:
y <- df_x %>% group_by(year) %>% dplyr::summarise(as.name(paste0("y_", v[1])) = mean(as.name(v[1]), na.rm = TRUE), as.name(paste0("y_", v[2])) = mean(as.name(v[1]), na.rm = TRUE), as.name(paste0("y_", v[3])) = mean(as.name(v[1]), na.rm = TRUE))
错误信息:
Error: unexpected '=' in "y <- df_x %>% group_by(year) %>% dplyr::summarise(as.name(paste0("y_", v[1])) ="
正确解法
方法1:使用dplyr::across(推荐,dplyr 1.0.0+)
across是dplyr专门用于批量处理变量的函数,配合all_of选择向量中的变量,再通过.names参数自动生成新变量名:
library(dplyr) y <- df_x %>% group_by(year) %>% summarise(across(all_of(v), ~mean(.x, na.rm = TRUE), .names = "y_{.col}"))
其中.names = "y_{.col}"会将原变量名(.col)自动拼接到y_后,直接生成y_a、y_b、y_c。
方法2:使用rlang准引用语法(适合复杂动态场景)
如果需要更灵活的动态逻辑,可以结合rlang的符号转换与动态赋值语法:
library(dplyr) library(rlang) # 生成包含动态命名与计算逻辑的表达式列表 summarise_exprs <- set_names( map(v, ~expr(mean(!!sym(.x), na.rm = TRUE))), paste0("y_", v) ) # 将表达式列表展开传入summarise y <- df_x %>% group_by(year) %>% summarise(!!!summarise_exprs)
sym(.x)将字符串变量名转为dplyr可识别的符号!!用于解引用符号,让dplyr识别为数据集中的变量set_names为表达式列表绑定新变量名!!!将表达式列表展开,作为summarise的参数
方法3:使用dplyr::summarise_at(旧版本兼容)
若使用较旧版本的dplyr,可通过summarise_at实现,后续再调整变量名:
y <- df_x %>% group_by(year) %>% summarise_at(v, list(y = ~mean(., na.rm = TRUE))) %>% rename_with(~paste0("y_", v), ends_with("_y"))
该方法已被across替代,优先推荐方法1。
内容的提问来源于stack exchange,提问作者feder80
相关产品推荐
相关产品推荐

