使用purrr::map时,如何避免Tidyevaluation列选择的字符串转换?
解决方案
可以通过一次性将选中列转换为符号列表,避免字符串与符号的来回转换,同时保持函数输入的未引用形式:
library(magrittr) library(rlang) library(tidyselect) library(purrr) library(dplyr) library(tibble) outer_func <- function(dat, col_rfs, dflt_flag){ # 直接将选中列转换为符号列表,无需中间字符串转换 col_rfs_syms <- tidyselect::eval_select(rlang::enquo(col_rfs), dat) %>% names() %>% rlang::syms() # 遍历符号列表,直接传入get_freq freqs <- purrr::map(col_rfs_syms, \(rf) get_freq(dat, !!rf, {{dflt_flag}})) return(freqs) } get_freq <- function(dat, rf, dflt_flag){ freq <- dat %>% dplyr::group_by({{rf}}) %>% dplyr::summarise(count = dplyr::n(), dr = mean({{dflt_flag}}), .groups = "drop") return(freq) } # 测试代码(设置随机种子保证结果可复现) set.seed(123) dat <- tibble::tibble( dflt = sample(c(0,1), size = 1000, replace = TRUE), rf_1 = sample(c("a","b"), size = 1000, replace = TRUE), rf_2 = sample(c(1,2), size = 1000, replace = TRUE) ) outer_func(dat, dplyr::starts_with("rf"), dflt)
核心优化点
- 一次性将选中列名转换为符号列表(
rlang::syms()),避免循环中反复执行rlang::sym(x)的冗余操作 - 直接遍历符号列表,通过
!!rf将未引用的列传入get_freq,完全符合未引用参数的要求 - 保留了原函数对
dplyr列选择器(如starts_with)的支持
内容的提问来源于stack exchange,提问作者PalimPalim
相关产品推荐
相关产品推荐

