You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在dplyr::case_when()中引用多列向量判断NA值?

基于多列NA判断创建新列的dplyr解决方案

问题背景

需要通过dplyr::case_when()生成新列:当指定子集的所有列均为NA时,新列值设为1,否则为0。但直接使用all(is.na(c(x,y)))的写法无法得到预期结果,示例代码及问题如下:

示例代码

test <- data.frame(x=c(1,2,3,NA,NA),
                   y=c(1,NA,2,3,NA))
test %>%
  mutate(z = case_when(
    all(is.na(c(x,y))) ~ 1,
    .default = 0
  ))

问题表现

预期第5行(x和y均为NA)的z值为1,其余行z值为0,但实际所有行的z值都为0。is.na(x) & is.na(y) ~ 1的写法虽可行,但不适用于列数较多的场景。

可行解决方案

针对多列场景,推荐两种高效写法:

方法1:结合rowwise()与c_across()

c_across()可选中指定范围的列,配合rowwise()实现逐行判断目标列是否全为NA:

test %>%
  rowwise() %>%
  mutate(z = case_when(
    all(is.na(c_across(c(x, y)))) ~ 1,
    .default = 0
  )) %>%
  ungroup() # 完成操作后取消行分组,避免影响后续计算

支持tidyselect语法:选中连续列可写c_across(x:y),按列名模式匹配可写c_across(starts_with("col_"))。

方法2:使用if_all()

if_all()是dplyr 1.0.0+版本新增函数,可直接在case_when()中逐行判断指定列是否全部满足条件,无需手动分组:

test %>%
  mutate(z = case_when(
    if_all(c(x, y), is.na) ~ 1,
    .default = 0
  ))

同样支持tidyselect语法,例如if_all(starts_with("x"), is.na)可选中所有以x开头的列。

原代码失效原因

原代码中all(is.na(c(x,y)))会将x、y整合成一个整体向量,判断整个向量是否全为NA,而非逐行判断每行的x和y是否都为NA,最终得到单一逻辑值FALSE,导致所有行的z值都为0。上述两种方法均针对每行的指定列做判断,符合需求。

内容的提问来源于stack exchange,提问作者JLinsta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 09:12:32