R语言如何循环多列数据实现多条件判断赋值
问题原因
你的嵌套ifelse()逻辑失效,核心是R的逻辑运算规则导致的:任何值和NA做==比较时,返回结果都是NA,而非FALSE。比如NA == TRUE的输出是NA,既不满足第一层判断的TRUE条件,也不会正常进入第二层判断,最终Test1为NA的行会直接返回NA,和你预期的「Test1不为T(含NA、FALSE两种情况)就判断Test2」的逻辑不符。
可用实现方案
1. 等价于Python zip+列表推导的原生写法
R原生支持多向量同步遍历的写法,和Python中zip()打包两个列表再做列表推导的逻辑完全对应,用mapply()就能实现,逐行传入两个列的对应值做判断即可:
test_data$test <- mapply(function(t1, t2) { if (isTRUE(t1)) return("A") if (isTRUE(t2)) return("B") return("C") }, test_data$Test1, test_data$Test2)
这里用isTRUE()做判断的好处是,只有传入值明确为TRUE时才会返回TRUE,传入值为FALSE、NA时都会返回FALSE,完全匹配你的判断规则,不会被NA干扰。
2. 修正后的向量化ifelse写法
如果想保留向量化运算的效率,不需要写逐行判断逻辑,只要把原来的== TRUE替换成%in% TRUE即可避开NA的坑:
test_data$test <- ifelse( test_data$Test1 %in% TRUE, "A", ifelse(test_data$Test2 %in% TRUE, "B", "C") )
%in%运算符做匹配时,只有左侧值明确存在于右侧向量中才会返回TRUE,因此x %in% TRUE的效果和isTRUE()的向量化版本完全一致:x为TRUE返回T,x为FALSE、NA都返回F。运行后执行table(test_data$test)可以得到正确计数:A共3个,B共3个,C共4个。
3. 可读性更高的分支判断写法
日常数据处理中更常用dplyr::case_when()写多分支判断,规则和需求一一对应,不容易写错:
library(dplyr) test_data <- test_data |> mutate( test = case_when( Test1 %in% TRUE ~ "A", Test2 %in% TRUE ~ "B", .default = "C" ) )
补充:R本身的向量化运算效率远高于逐行循环,绝大多数场景不需要特意写类Python的显式循环。如果偏好函数式写法,也可以用
purrr::map2_chr(test_data$Test1, test_data$Test2, ~if(isTRUE(.x)){"A"}else if(isTRUE(.y)){"B"}else{"C"})实现和mapply()完全一致的效果。
内容的提问来源于stack exchange,提问作者Data-7scientist

