为何在R语言中仅dplyr::case_when会产生不同结果?
问题:
case_when 与 if/ifelse 处理空字符向量的行为差异 当用 dplyr::case_when 替代 if 语句时,发现一个特殊行为:当第二个分支返回显式字符串时结果符合预期,但返回空字符向量 x 本身时,结果变成了空向量。对比 if、ifelse 和 case_when 的执行结果,只有 case_when 出现这种差异,原因是什么?
x <- character(0) dplyr::case_when(rlang::is_empty(x) ~ "Empty", !rlang::is_empty(x) ~ "Not empty") #> [1] "Empty" dplyr::case_when(rlang::is_empty(x) ~ "Empty", !rlang::is_empty(x) ~ x) #> character(0) if (rlang::is_empty(x)) "Empty" else if (!rlang::is_empty(x)) "Not empty" #> [1] "Empty" if (rlang::is_empty(x)) "Empty" else if (!rlang::is_empty(x)) x #> [1] "Empty" ifelse(rlang::is_empty(x), "Empty", "Not empty") #> [1] "Empty" ifelse(rlang::is_empty(x), "Empty", x) #> [1] "Empty"
Created on 2022-08-16 by the reprex package (v2.0.1)
核心原因:case_when 的向量化逻辑与类型对齐规则
case_when的向量化特性:它是为处理长度大于1的向量场景设计的,会对所有分支的结果向量做长度对齐。哪怕某个分支的条件为FALSE,其结果向量的长度仍会参与最终结果的长度计算——这里第二个分支的x是空向量(长度0),最终结果被强制对齐为长度0,所以输出character(0)。if的标量判断逻辑:if仅接受标量逻辑值(此处rlang::is_empty(x)返回标量TRUE),一旦第一个条件满足,直接返回对应结果,后续分支的代码完全不会执行,自然不受x是空向量的影响。ifelse的特殊处理逻辑:ifelse虽为向量化函数,但会根据条件的长度决定结果长度。当条件是标量TRUE时,它只会取第一个分支的结果,完全忽略第二个分支的空向量,因此输出正常。
解决方法
要让case_when输出符合预期,可通过以下方式调整:
- 用
TRUE ~ ...设置兜底分支,避免空向量分支影响:dplyr::case_when(rlang::is_empty(x) ~ "Empty", TRUE ~ x) #> [1] "Empty" - 对返回
x的分支做长度对齐处理:dplyr::case_when(rlang::is_empty(x) ~ "Empty", !rlang::is_empty(x) ~ dplyr::if_else(!rlang::is_empty(x), x, "Empty")) #> [1] "Empty"
内容的提问来源于Stack Exchange,提问作者ryoto
相关产品推荐
相关产品推荐

