在dplyr的mutate_函数中使用paste生成动态变量名报错求助
解决dplyr中动态生成变量名并计算均值的问题
你的问题核心在于直接把字符串传给mean()函数,而没有告诉dplyr这个字符串对应数据框中的列变量。paste0()生成的是字符串(比如"SumA2"),但mean()需要的是数值向量,所以会出现"argument is not numeric or logical"的警告,返回NA。
下面给你两种可行的解决方案,分别适配你当前用的mutate_()语法,以及更现代的dplyr tidyeval语法(推荐后者,因为mutate_()已被软弃用):
方案1:适配mutate_()的写法
需要将生成的字符串转换为dplyr能识别的表达式,这里可以用rlang::parse_expr()把字符串转成表达式对象,再传给.dots参数:
library(dplyr) library(rlang) # 确保nameVarPeriod1是字符串类型(如果是函数参数,注意传参时加引号) nameVarPeriod1 <- "A2" df <- df %>% group_by(segment) %>% mutate_(.dots = setNames( # 把"mean(SumA2)"字符串转成表达式 list(parse_expr(paste0("mean(Sum", nameVarPeriod1, ")"))), # 动态设置新列名 paste0("MeanSum", nameVarPeriod1) ))
方案2:推荐的tidyeval语法(现代dplyr风格)
用sym()将字符串转为符号,再用!!(解引用运算符)告诉dplyr这是一个变量名;用:=实现动态列名赋值:
library(dplyr) library(rlang) nameVarPeriod1 <- "A2" # 1. 动态生成要计算的列名和新列名 sum_col <- sym(paste0("Sum", nameVarPeriod1)) mean_col <- paste0("MeanSum", nameVarPeriod1) # 2. 分组计算均值并添加新列 df <- df %>% group_by(segment) %>% mutate(!!mean_col := mean(!!sum_col, na.rm = TRUE)) # na.rm可选,处理缺失值
如果你的nameVarPeriod1是函数参数,且希望调用时不用加引号(比如my_func(df, A2)),可以用enquo()捕获参数并转为字符串:
my_calculate_mean <- function(data, nameVarPeriod1) { # 捕获参数并转为字符串 var_str <- quo_name(enquo(nameVarPeriod1)) sum_col <- sym(paste0("Sum", var_str)) mean_col <- paste0("MeanSum", var_str) data %>% group_by(segment) %>% mutate(!!mean_col := mean(!!sum_col, na.rm = TRUE)) } # 调用示例(不用给A2加引号) df <- my_calculate_mean(df, A2)
测试结果验证
用你提供的测试数据运行后,会新增MeanSumA2列,比如Seg1组的均值为(127343.87 + 36815.82)/2 = 82079.845,和预期一致。
内容的提问来源于stack exchange,提问作者Cox Tox
相关产品推荐
相关产品推荐

