R语言:如何对多变量应用自定义函数并正确传递字符型变量名
我来帮你解决这个问题!你的核心问题在于函数里用了enquo()来处理变量,但lapply传递的是字符型的列名,enquo()是用来捕获裸变量名(比如直接写actor1而不是"actor1")的,所以才会返回变量名而不是预期的演员列表。下面给你几种可行的解决方案:
方案1:用.data pronoun直接引用字符列名(最简洁推荐)
这种方法不需要用到tidyeval的复杂语法,直接通过.data[[col]]来引用数据框中对应名称的列,完美适配字符型输入:
# 先把s类演员单独定义成向量,方便后续修改 s_actors <- c("A", "B", "C") nons_function <- function(col) { df %>% filter(!is.na(.data[[col]]), !.data[[col]] %in% s_actors) %>% distinct(.data[[col]]) %>% pull() } # 运行测试 actorlist <- c("actor1", "actor2") lapply(actorlist, nons_function)
运行结果完全符合你的预期:
[[1]] [1] "D" "E" "F" "G" "H" [[2]] [1] "E" "I" "D" "G"
方案2:将字符转成符号适配tidyeval语法
如果你更习惯用tidyeval的写法,可以用rlang::sym()把字符型列名转换成变量符号,再用!!注入到dplyr函数中:
library(rlang) s_actors <- c("A", "B", "C") nons_function <- function(col) { col_sym <- sym(col) df %>% filter(!is.na(!!col_sym), !!!col_sym %in% s_actors) %>% distinct(!!col_sym) %>% pull() } lapply(actorlist, nons_function)
方案3:无需单独写函数,直接用purrr简化代码
如果不想单独定义函数,也可以用purrr::map()直接完成遍历,代码更紧凑:
library(purrr) s_actors <- c("A", "B", "C") actorlist <- c("actor1", "actor2") map(actorlist, ~ df %>% filter(!is.na(.data[[.x]]), !.data[[.x]] %in% s_actors) %>% distinct(.data[[.x]]) %>% pull())
额外优化建议
把s_actors单独定义成向量是关键——以后如果s类演员有变动,你只需要修改这个向量,不用改动函数或遍历逻辑,完全符合你想要的自动化、少调整的需求。
内容的提问来源于stack exchange,提问作者MarkusG
相关产品推荐
相关产品推荐

