在 R 中按元素比较时如何将 NA 视为值
How to treat NAs like values when comparing elementwise in R
我想按元素比较两个向量,以检查第一个向量中某个位置的元素是否与第二个向量中相同位置的元素不同。
关键是我在向量中有 NA
值,当对这些值进行比较时,我得到 NA
而不是 TRUE
或 FALSE
.
可重现示例:
这是我得到的:
a<-c(1, NA, 2, 2, NA)
b<-c(1, 1, 1, NA, NA)
a!=b
[1] FALSE TRUE NA NA NA
下面是我希望 !=
运算符的工作方式(将 NA
值视为变量的另一个 "level"):
a!=b
[1] FALSE TRUE TRUE TRUE FALSE
this link 中有一个可能的解决方案,但此人正在创建一个函数来执行该任务。我想知道是否有更优雅的方法来做到这一点。
我们可以用两个向量中都不存在的值 v1
执行 NA 值的即时替换,然后执行 !=
f1 <- function(x, y) {
v1 <- setdiff(1:1000, na.omit(unique(c(x,y))))[1]
replace(x, is.na(x), v1) != replace(y, is.na(y), v1)
}
f1(a,b)
#[1] FALSE TRUE TRUE TRUE FALSE
f1(a1,b1)
#[1] TRUE TRUE TRUE
f1(a2,b2)
#[1] FALSE TRUE TRUE FALSE
数据
a <- c(1, NA, 2, 2, NA)
b<-c(1, 1, 1, NA, NA)
a1 <- c(NA, 1, NA)
b1 <- c(2, NA, 3)
a2<-c(1,NA,2,NA)
b2<-c(1,1,3,NA)
利用以下事实:
T & NA = NA
但
F & NA = F
和
F | NA = NA
但
T | NA = T
以下解决方案有效,并小心放置了括号:
(a != b | (is.na(a) & !is.na(b)) | (is.na(b) & !is.na(a))) & !(is.na(a) & is.na(b))
您可以定义:
`%!=na%` <- function(e1, e2) (e1 != e2 | (is.na(e1) & !is.na(e2)) | (is.na(e2) & !is.na(e1))) & !(is.na(e1) & is.na(e2))
然后使用:
a %!=na% b
这是另一种解决方案。它可能比我的其他答案慢,因为它没有矢量化,但它肯定更优雅。前几天我注意到 %in%
比较 NA
就像其他值一样。因此 c(1L, NA) %in% 1:4
给出 TRUE FALSE
而不是 TRUE NA
,例如。
所以你可以拥有:
!mapply(`%in%`, a, b)
我喜欢这个,因为它非常简单,而且很容易看出它有效 (source):
# This function returns TRUE wherever elements are the same, including NA's,
# and FALSE everywhere else.
compareNA <- function(v1, v2)
{
same <- (v1 == v2) | (is.na(v1) & is.na(v2))
same[is.na(same)] <- FALSE
return(same)
}
我想按元素比较两个向量,以检查第一个向量中某个位置的元素是否与第二个向量中相同位置的元素不同。
关键是我在向量中有 NA
值,当对这些值进行比较时,我得到 NA
而不是 TRUE
或 FALSE
.
可重现示例:
这是我得到的:
a<-c(1, NA, 2, 2, NA)
b<-c(1, 1, 1, NA, NA)
a!=b
[1] FALSE TRUE NA NA NA
下面是我希望 !=
运算符的工作方式(将 NA
值视为变量的另一个 "level"):
a!=b
[1] FALSE TRUE TRUE TRUE FALSE
this link 中有一个可能的解决方案,但此人正在创建一个函数来执行该任务。我想知道是否有更优雅的方法来做到这一点。
我们可以用两个向量中都不存在的值 v1
执行 NA 值的即时替换,然后执行 !=
f1 <- function(x, y) {
v1 <- setdiff(1:1000, na.omit(unique(c(x,y))))[1]
replace(x, is.na(x), v1) != replace(y, is.na(y), v1)
}
f1(a,b)
#[1] FALSE TRUE TRUE TRUE FALSE
f1(a1,b1)
#[1] TRUE TRUE TRUE
f1(a2,b2)
#[1] FALSE TRUE TRUE FALSE
数据
a <- c(1, NA, 2, 2, NA)
b<-c(1, 1, 1, NA, NA)
a1 <- c(NA, 1, NA)
b1 <- c(2, NA, 3)
a2<-c(1,NA,2,NA)
b2<-c(1,1,3,NA)
利用以下事实:
T & NA = NA
但
F & NA = F
和
F | NA = NA
但
T | NA = T
以下解决方案有效,并小心放置了括号:
(a != b | (is.na(a) & !is.na(b)) | (is.na(b) & !is.na(a))) & !(is.na(a) & is.na(b))
您可以定义:
`%!=na%` <- function(e1, e2) (e1 != e2 | (is.na(e1) & !is.na(e2)) | (is.na(e2) & !is.na(e1))) & !(is.na(e1) & is.na(e2))
然后使用:
a %!=na% b
这是另一种解决方案。它可能比我的其他答案慢,因为它没有矢量化,但它肯定更优雅。前几天我注意到 %in%
比较 NA
就像其他值一样。因此 c(1L, NA) %in% 1:4
给出 TRUE FALSE
而不是 TRUE NA
,例如。
所以你可以拥有:
!mapply(`%in%`, a, b)
我喜欢这个,因为它非常简单,而且很容易看出它有效 (source):
# This function returns TRUE wherever elements are the same, including NA's,
# and FALSE everywhere else.
compareNA <- function(v1, v2)
{
same <- (v1 == v2) | (is.na(v1) & is.na(v2))
same[is.na(same)] <- FALSE
return(same)
}