使用dplyr::if_any()结合ifelse()时FALSE场景返回NA的问题求解
问题原因与解决方案
为什么会返回NA?
当数据行里没有值等于1,但存在NA时,x == 1对NA元素会返回NA。dplyr::if_any()的逻辑规则是:
- 只要有一个元素判断为
TRUE,返回TRUE - 所有元素判断为
FALSE,返回FALSE - 存在NA且没有
TRUE时,返回NA(因为NA代表逻辑不确定,无法确认是否存在符合条件的值)
这种情况下,后续的ifelse()遇到NA输入,直接返回NA,而非预期的0。比如示例第二行,x1:x4 == 1的结果是FALSE, FALSE, NA, NA,if_any()无法确定是否存在1,所以返回NA,最终ifelse(NA, 1, 0)输出NA。
可行解决方案
方案1:在if_any的判断中处理NA
将NA视为FALSE,确保判断结果只有TRUE或FALSE:
# 方法A:用coalesce把NA转为FALSE res <- df |> mutate(flag = ifelse(if_any(x1:x4, ~ coalesce(.x == 1, FALSE)), 1, 0)) # 方法B:先排除NA再判断 res <- df |> mutate(flag = ifelse(if_any(x1:x4, ~ !is.na(.x) & .x == 1), 1, 0))
方案2:用rowSums统计符合条件的元素数
通过rowSums忽略NA统计每行中等于1的元素数量,再判断是否大于0:
res <- df |> mutate(flag = as.integer(rowSums(across(x1:x4, ~ .x == 1), na.rm = TRUE) > 0))
这里rowSums会把TRUE转为1、FALSE转为0,na.rm=TRUE忽略NA,总和大于0则说明存在1,转成整数就是1,否则为0。
方案3:用purrr::pmap逐行判断
借助purrr工具逐行检查是否存在1(忽略NA):
library(purrr) res <- df |> mutate(flag = as.integer(pmap_lgl(across(x1:x4), ~ any(c(...) == 1, na.rm = TRUE))))
以上方案都能得到正确的标记列:c(1, 0, 1, 0, 1)
内容的提问来源于stack exchange,提问作者nightstand
相关产品推荐
相关产品推荐

