基于值标签构建可在dplyr::mutate/across运行的二分转换函数
解决方案
针对你的需求,我们可以重构make_dicho()函数,使其适配dplyr的管道环境,无需手动传入数据框,同时完美支持across()批量处理变量。核心思路是利用rlang的tidy eval工具自动识别运行环境,同时兼容单独调用、mutate()调用和across()调用三种场景。
最终函数代码
library(dplyr) library(rlang) library(labelled) library(stringr) make_dicho <- function(var, df = NULL) { # 处理三种调用场景:单独传入df、mutate中调用、across中传入向量 if (!is.null(df)) { # 单独调用时,从指定数据框提取变量 var_name <- as_name(enexpr(var)) var_vec <- df[[var_name]] } else if (is_symbol(enexpr(var))) { # 在mutate管道中,自动获取当前数据框的变量 var_vec <- cur_data()[[as_name(enexpr(var))]] } else { # 在across中,直接处理传入的带标签向量 var_vec <- var } # 检查变量是否有值标签 val_labels <- val_labels(var_vec) if (is.null(val_labels)) { stop("目标变量没有值标签,请先使用labelled包添加标签后再处理。") } # 反转值标签映射,方便通过数值匹配对应的文本标签 label_map <- names(val_labels) names(label_map) <- val_labels # 将数值转换为文本标签,再进行二分判断 label_text <- label_map[as.character(var_vec)] case_when( str_detect(label_text, regex("agree", ignore_case = TRUE)) ~ "Agree", str_detect(label_text, regex("disagree", ignore_case = TRUE)) ~ "Disagree", TRUE ~ NA_character_ ) }
场景测试
1. 单独调用函数
make_dicho(x, df = data) # 输出:[1] "Disagree" "Disagree" "Agree" "Agree"
2. 在mutate()中调用(无需传入.)
data %>% mutate(new_x = make_dicho(x))
3. 在across()中批量处理变量
data %>% mutate( across(x:z, make_dicho, .names = "new_{col}") )
关键改进点
自动识别数据环境:
- 在
mutate()中调用时,通过cur_data()自动获取当前管道中的数据框,无需手动传入. - 兼容单独调用场景,通过可选的
df参数指定数据框
- 在
适配
across()运行逻辑:- 判断输入类型:如果是
across()传入的带标签向量,直接处理;如果是变量名,则从数据框提取变量 - 基于值标签文本进行二分,不受量表点数(4/6点)限制,只要标签包含"agree"/"disagree"即可正确分类
- 判断输入类型:如果是
鲁棒性增强:
- 添加值标签检查,避免无标签变量导致的错误
- 使用不区分大小写的正则匹配,兼容不同格式的标签文本(如"Strongly Agree"或"strongly agree")
内容的提问来源于stack exchange,提问作者jdenn0514
相关产品推荐
相关产品推荐

