在lapply函数中使用dplyr的rename重命名变量失败求助
问题:lapply调用函数时dplyr::rename无法正确使用派生变量名
在使用lapply调用自定义函数时,dplyr的rename函数无法使用从输入变量派生的名称,总是显示占位符X[[i]];但直接调用函数时,变量名派生和重命名都能正常工作。尝试过quote(var)、as.character(var)等方式获取变量名,均未解决问题。
示例代码
library(dplyr) fc <- c(1:10) sc <- c(20:29) df1 <- cbind.data.frame(fc, sc) # 用于lapply调用的数据集 df2 <- cbind.data.frame(fc, sc) # 用于直接调用函数的数据集 addfunc <- function(var, df) { attach(df) dfname = deparse(substitute(df)) # 获取数据集名称 new_var_name = deparse(substitute(var)) # 获取变量名转为字符串 new_var_name <- paste(new_var_name, "_new", sep = "") # 拼接新变量名 df <- df %>% mutate(new_var = var + 100) # 生成新变量占位符 df <- df %>% rename(!!new_var_name := new_var) # 重命名占位符 assign(dfname, df, envir=globalenv()) # 将修改后的数据集推至全局环境 detach(df) } var <- list(sc, fc) # 待处理的变量列表 # 直接调用函数可得到预期结果 addfunc(fc, df2) addfunc(sc, df2) # lapply调用时无法正确生成新变量名 lapply(var, FUN = addfunc, df=df1)
解决方案
问题核心是lapply传递的是变量的值而非变量名的符号引用:deparse(substitute(var))在lapply迭代时,只能拿到X[[i]]这类占位符,因为lapply遍历的是列表元素的值,而非原始变量的符号信息。
方法1:传递变量名字符串(最简洁)
将待处理变量名以字符串形式存入列表,修改函数通过.data代词引用变量,避免非标准求值问题:
library(dplyr) fc <- c(1:10) sc <- c(20:29) df1 <- cbind.data.frame(fc, sc) addfunc <- function(var_name, df) { dfname <- deparse(substitute(df)) new_var_name <- paste(var_name, "_new", sep = "") # 使用.data[[var_name]]安全引用变量 df <- df %>% mutate(new_var = .data[[var_name]] + 100) df <- df %>% rename(!!new_var_name := new_var) assign(dfname, df, envir = globalenv()) } # 传递变量名字符串列表 var_names <- c("sc", "fc") lapply(var_names, FUN = addfunc, df = df1)
方法2:传递变量符号(保留非标准求值风格)
如果偏好使用符号传递变量,可借助purrr::imap同时获取符号和名称:
library(dplyr) library(purrr) fc <- c(1:10) sc <- c(20:29) df1 <- cbind.data.frame(fc, sc) addfunc <- function(var_sym, var_name, df) { dfname <- deparse(substitute(df)) new_var_name <- paste(var_name, "_new", sep = "") df <- df %>% mutate(new_var = !!var_sym + 100) df <- df %>% rename(!!new_var_name := new_var) assign(dfname, df, envir = globalenv()) } # 构建符号与对应名称的列表 var_list <- list(sc = rlang::sym("sc"), fc = rlang::sym("fc")) imap(var_list, ~addfunc(.x, .y, df = df1))
额外优化建议
- 避免使用
attach()/detach():这类操作容易引发环境变量冲突,用.data代词或符号引用变量更安全。 - 尽量不用
assign()修改全局环境:推荐函数直接返回修改后的数据集,再手动赋值,代码逻辑更清晰可控:
addfunc <- function(var_name, df) { new_var_name <- paste(var_name, "_new", sep = "") df %>% mutate(new_var = .data[[var_name]] + 100) %>% rename(!!new_var_name := new_var) } # 直接接收函数返回值并合并 df1 <- lapply(c("sc", "fc"), addfunc, df = df1) %>% purrr::reduce(full_join, by = c("fc", "sc"))
内容的提问来源于stack exchange,提问作者Kilsen
相关产品推荐
相关产品推荐

