使用dplyr的case_when创建新列时的NA特殊处理问题
解决多列条件计分并处理NA的问题
样本数据框
x <- data.frame(x1 = c(NA, 1, 1, 0, 0 , NA), x2 = c(1, NA, 0, 0, NA, 0), x3 = c(0, NA, NA, 1, 0, 1), x4 = c(NA, 1, 1, NA, 0, 0))
需求说明
需要创建score列,规则如下:
- 第一组(x1、x2):
- 若x1或x2为1,加1分
- 若x1和x2均为0,加0分
- 其他情况记为NA
- 第二组(x3、x4):
- 若x3或x4为1,加1分
- 若x3和x4均为0,加0分
- 其他情况记为NA
- 最终score为两组得分之和,且需忽略NA(即NA按0处理),期望结果为
1, 2, 2, 1, 0, 1
问题分析
- 直接相加两组
case_when结果时,只要其中一组为NA,整体结果就会变成NA(R中NA与任何值运算结果都是NA) - 使用全局
sum(..., na.rm=T)会对整个向量求和,得到单一值,无法实现逐行计算
解决方案
方法1:分步计算(清晰直观)
先分别计算两组得分,再逐行求和并忽略NA:
library(dplyr) x <- x %>% mutate( # 计算第一组得分 part1 = case_when( x1 == 0 & x2 == 0 ~ 0L, x1 == 1 | x2 == 1 ~ 1L, TRUE ~ NA_integer_ ), # 计算第二组得分 part2 = case_when( x3 == 0 & x4 == 0 ~ 0L, x3 == 1 | x4 == 1 ~ 1L, TRUE ~ NA_integer_ ), # 逐行求和,自动忽略NA score = rowSums(cbind(part1, part2), na.rm = TRUE) )
方法2:简洁写法(无需中间列)
直接在rowSums中嵌套两组case_when逻辑:
library(dplyr) x <- x %>% mutate( score = rowSums( cbind( case_when(x1 == 0 & x2 == 0 ~ 0L, x1 == 1 | x2 == 1 ~ 1L, TRUE ~ NA_integer_), case_when(x3 == 0 & x4 == 0 ~ 0L, x3 == 1 | x4 == 1 ~ 1L, TRUE ~ NA_integer_) ), na.rm = TRUE ) )
运行后score列将得到期望的1, 2, 2, 1, 0, 1。
内容的提问来源于stack exchange,提问作者rez
相关产品推荐
相关产品推荐

