为何R语言中ifelse条件重编码未返回预期值?
问题:基于含NA的多变量创建新变量时ifelse返回错误NA值
需要基于年度调查中更名的同一项问题(变量A和B,某一变量有值时对应其他年份的变量为NA)创建新变量C,规则如下:
- 若A=1或B=1,则C=1
- 若A=2或B=2,则C=2
- 若A和B均非1/2,则C=NA
数据示例
A B [1,] 1 NA [2,] 2 NA [3,] NA NA [4,] NA 1 [5,] NA 2
错误现象
运行下方代码后,第2行(A=2)和第5行(B=2)的C值为NA,不符合预期。
可复现代码
require(tidyverse) require(dplyr) require(data.table) # 创建数据 A <- as.numeric(c(1,2,NA,NA,NA)) B <- as.numeric(c(NA,NA,NA,1,2)) df_ <- cbind(A,B) # dplyr 条件编码(错误版本) df2 <- df_ %>% data.frame() %>% mutate(C = ifelse(A == 1 | B == 1, 1, ifelse(A == 2 | B == 2, 2, NA))) # data.table 条件编码(错误版本) df2 <- df_ %>% data.table() %>% .[ , C := ifelse(A == 1 | B == 1, 1, ifelse(A == 2 | B == 2, 2, NA))]
问题原因
确实和R处理NA的逻辑有关:在R中,任何与NA的比较运算(如A == 1当A为NA时)都会返回NA;而ifelse遇到NA的条件时,会直接返回NA,不会进入后续的判断分支。
以第2行为例:A=2,B=NA,第一个ifelse的条件是2 ==1 | NA ==1,结果为FALSE | NA即NA,因此ifelse直接返回NA,不会执行第二个ifelse的判断。
解决方案
方法1:利用%in%处理NA
%in%会自动忽略NA(NA %in% x返回FALSE),避免条件判断出现NA,从而让逻辑进入正确分支:
dplyr版本
df2 <- df_ %>% data.frame() %>% mutate(C = ifelse(A %in% 1 | B %in% 1, 1, ifelse(A %in% 2 | B %in% 2, 2, NA)))
data.table版本
df2 <- df_ %>% data.table() %>% .[ , C := ifelse(A %in% 1 | B %in% 1, 1, ifelse(A %in% 2 | B %in% 2, 2, NA))]
方法2:先合并A和B(更简洁)
由于题目中A和B不会同时有值(某一变量有值时另一变量为NA),可以用coalesce(dplyr)或fcoalesce(data.table)先合并成一个变量,再进行判断:
dplyr版本
df2 <- df_ %>% data.frame() %>% mutate(C = case_when( coalesce(A, B) == 1 ~ 1, coalesce(A, B) == 2 ~ 2, TRUE ~ NA_real_ ))
data.table版本
df2 <- df_ %>% data.table() %>% .[ , C := fcase( fcoalesce(A, B) == 1, 1, fcoalesce(A, B) == 2, 2, default = NA_real_ )]
内容的提问来源于stack exchange,提问作者David Crow
相关产品推荐
相关产品推荐

