如何修复自定义函数结合dplyr与purrr::pmap时的列未找到错误
问题修复方案
问题根源
你遇到的object 'vs' not found错误,是因为expr()生成的表达式仅包含符号本身,没有绑定对应的求值环境;当通过pmap传递时,fn_test中的准引用({{}})无法在正确的上下文中找到目标列。
修复方案(保留expr/准引用逻辑)
如果要继续使用表达式传递列参数,只需将expr()替换为quo()来捕获环境,同时保持原有fn_test逻辑不变:
library(tidyverse) library(purrr) # 原始自定义函数无需修改 fn_test <- function(dta, col) { dta %>% select({{col}}) %>% mutate(!!paste0(quo_name(col), "_txt") := case_when( {{col}} == 0 ~ "No", {{col}} == 1 ~ "Yes" )) } # 准备参数列表:用quo()捕获列的环境 param_list <- list( dta = list(mtcars, mtcars), col = list(quo(vs), quo(am)) ) # 封装pmap调用的函数 fn_test_purrr <- function(param_list) { pmap(param_list, fn_test) } # 生成目标列表 df_test_purrr <- fn_test_purrr(param_list) # 验证结果 str(df_test_purrr)
替代方案(改用字符串列名,更稳定)
如果实际场景中参数较多,使用字符串传递列名会更直观且不易出作用域问题,只需修改fn_test将字符串转为符号处理:
library(tidyverse) library(purrr) # 修改后的fn_test:接受字符串列名 fn_test <- function(dta, col) { col_sym <- sym(col) dta %>% select({{col_sym}}) %>% mutate(!!paste0(col, "_txt") := case_when( {{col_sym}} == 0 ~ "No", {{col_sym}} == 1 ~ "Yes" )) } # 参数列表改用字符串传递列名 param_list <- list( dta = list(mtcars, mtcars), col = list("vs", "am") ) fn_test_purrr <- function(param_list) { pmap(param_list, fn_test) } # 调用生成结果 df_test_purrr <- fn_test_purrr(param_list)
方案说明
- 第一种方案中,
quo()会捕获符号所在的环境,确保{{col}}在fn_test中能正确关联到数据框中的列; - 第二种方案直接用字符串传递列名,通过
sym()转为符号后再用准引用处理,避开了作用域绑定的问题,更适合参数较多的场景。
内容的提问来源于stack exchange,提问作者MatSchu
相关产品推荐
相关产品推荐

