使用dplyr的across+case_when重编码因子变量失败求助
解决dplyr across结合case_when重编码因子变量失效问题
你需要将多个以Q开头、cat5结尾的5级因子变量重编码为3级cat3变量,规则如下:
- 原变量取值为
"1_Disagree"或"2_SomeD"时,新变量为"1_Disagree" - 原变量取值为
"3_Neither"时,新变量为"2_Neither" - 原变量取值为
"4_SomeA"或"5_Agree"时,新变量为"3_Agree"
示例数据:
df <- tibble(Q1_cat5 = as.factor(c("1_Disagree","2_SomeD","2_SomeD","4_SomeA","5_Agree")), Q2_cat5 = as.factor(c("5_Agree","5_Agree","3_Neither","4_SomeA","5_Agree")), Q3_cat5 = as.factor(c("3_Neither","2_SomeD","2_SomeD","1_Disagree","5_Agree")))
你尝试用dplyr的across结合case_when编码,但新变量未按规则转换,仍保留原变量值。
错误原因
across参数用法错误:在.fns参数中直接传入case_when(),没有用波浪线~将其定义为匿名函数,导致across无法正确解析执行逻辑。- 因子类型匹配问题:原变量是因子类型,直接和字符串做
==比较可能因因子水平的隐藏索引出现匹配失效,最好先转换为字符型再判断。
修正后的代码
library(dplyr) library(stringr) df2 <- df %>% mutate(across( .cols = starts_with('Q') & ends_with('cat5'), .fns = ~ case_when( as.character(.) %in% c("1_Disagree", "2_SomeD") ~ "1_Disagree", as.character(.) == "3_Neither" ~ "2_Neither", as.character(.) %in% c("4_SomeA", "5_Agree") ~ "3_Agree", is.na(.) ~ NA_character_ ) %>% factor(levels = c("1_Disagree", "2_Neither", "3_Agree")), .names = '{str_sub(.col, 1, -5)}cat3' ))
修正说明
- 用
~把case_when包裹成匿名函数,符合across对.fns参数的要求 - 通过
as.character(.)将因子转换为字符型,避免类型匹配错误 - 用
%in%简化多值判断的写法,让代码更简洁 - 最后用
factor()将结果转换为指定水平的因子变量,保证新变量的类型符合需求
运行代码后,df2会保留原变量,同时生成符合规则的Q1_cat3、Q2_cat3、Q3_cat3变量。
内容的提问来源于stack exchange,提问作者Vetepi
相关产品推荐
相关产品推荐

