处理TRUE、FALSE、NA和NaN

39

这里是一个向量

a <- c(TRUE, FALSE, FALSE, NA, FALSE, TRUE, NA, FALSE, TRUE)

我希望有一个简单的函数,每当在“a”中出现TRUE时,它返回TRUE,每当在“a”中出现FALSENA时,它返回FALSE

以下三个方法都无法实现此功能。

a == TRUE
identical(TRUE, a)
isTRUE(a)

这是一个解决方案

a[-which(is.na(a))]

但似乎并没有一个直接简单的解决方案。

还有其他解决方案吗?

以下是我所知道的一些函数(和运算符):

identical()
isTRUE()
is.na()
na.rm()
&
|
!
  • 还有哪些其他函数(操作符、技巧等等)对于处理TRUEFALSENANaN很有用?

  • NANaN之间有什么区别?

  • 除了TRUEFALSENANaN,还有其他的“逻辑事物”吗?

非常感谢!


6
回答你的第一个问题,以下是一种方法:Vectorize(isTRUE)(a)。该代码将向量a中的每个元素应用函数isTRUE,并返回一个逻辑型向量,表示每个元素是否为TRUE。 - Matthew Plourde
1
更具体地说,我认为 !is.na(x) & x 应该可以工作,只要你期望的值确实包含在 {TRUE, FALSE, NA, NaN} 中... - Ben Bolker
我觉得这些区别(NA vs NaNisTRUE vs is.na等)可能已经在其他地方/以前讨论过,甚至可能在StackOverflow上。通过谷歌搜索“na nan is.finite is.nan is.na”可以找到http://stat.ethz.ch/R-manual/R-devel/library/base/html/is.finite.html,但奇怪的是它没有与http://stat.ethz.ch/R-manual/R-devel/library/base/html/NA.html相关的“参见”。 - Ben Bolker
为了完整性,我建议在您上面的列表中添加“all.equal”,“is.finite”和“is.nan”。 - Ben Bolker
4
NaN是数值型的,因此您在逻辑向量中不可能遇到它。建议的解决方案a[-which(is.na(a))]只有7个元素,而a有9个元素。您确定这就是您想要的吗?也许sapply(a, isTRUE)才是您想要的? - G. Grothendieck
关于问题的最后一部分“是否存在除T、F、NA和NaN之外的其他“逻辑事物”?”只是一个快速的旁观评论——通常情况下,TF并不等同于TRUEFALSE;也就是说,它们不是保留字,可以随时被用户重新定义。这意味着你需要小心对待它们;例如,T <- FALSE可能会让你的一天变得糟糕。 - Jason Morgan
5个回答

70
您不需要将任何内容包装在函数中——以下内容可以正常工作。
a = c(T,F,NA)

a %in% TRUE

[1]  TRUE FALSE FALSE

11
不错的解决方案。你可以使用函数形式:'%in%'(aamc$forgive, FALSE),这对于 apply 及其类似函数非常有用。 - Ari B. Friedman
当尝试构建函数并涉及">="、"<="、"=="等逻辑测试时,如果可能会针对NA进行评估,则非常好且有用的解决方案是不会抛出错误等。 - Jim Maas

17

按顺序回答你的问题:

1)==操作符实际上并不像你期望的那样处理NA值。一个非常有用的函数是来自r-cookbook.comcompareNA函数:

  compareNA <- function(v1,v2) {
    # This function returns TRUE wherever elements are the same, including NA's,
    # and false everywhere else.
    same <- (v1 == v2)  |  (is.na(v1) & is.na(v2))
    same[is.na(same)] <- FALSE
    return(same)
   }

2)NA代表“不可用”,并不同于一般的NaN(“不是数字”)。 NA通常用作数字的默认值,以代替缺失数据;NaN通常是由于数值问题(例如取log(-1))等而产生的。

3)我不太确定您所说的“逻辑事物”是什么意思--许多不同的数据类型,包括数字向量,都可以用作逻辑运算符的输入。您可能想尝试阅读R逻辑运算符页面:http://stat.ethz.ch/R-manual/R-patched/library/base/html/Logic.html

希望这能有所帮助!


除以0的结果是“Inf”,但是“Inf-Inf”会得到“NaN”。很多时候,如果产生了“NaN”,R函数会引发异常,例如“log(-1)”。 - Matthew Plourde
eq = function(x,y) is.element(x == y, TRUE) | is.na(x) & is.na(y) - JRC

10

所以您希望TRUE保持为TRUE,FALSE保持为FALSE,唯一的改变是NA需要变成FALSE,那么只需进行以下更改:


所以你想要TRUE保持不变,FALSE也保持不变,唯一需要更改的是将NA变为FALSE,可以按照以下方式进行更改:
a[ is.na(a) ] <- FALSE

或者您可以重新表述,说只有在其为 TRUE 且不缺失时才为 TRUE:

a <- a & !is.na(a)

7
采用Ben Bolker上面提出的建议,您可以按照is.na()语法设置自己的函数。
is.true <- function(x) {
  !is.na(x) & x
}

a = c(T,F,F,NA,F,T,NA,F,T)

is.true(a)
[1]  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE

这同样适用于数据子集。
b = c(1:9)
df <- as.data.frame(cbind(a,b))

df[is.true(df$a),]

  a b
1 1 1
6 1 6
9 1 9

并且有助于避免在数据中存在NA时意外地将空行合并。

df[df$a == TRUE,]

      a  b
1     1  1
NA   NA NA
6     1  6
NA.1 NA NA
9     1  9

你真的不需要在这里使用 ifelse() -- 正如 @GregSnow 的回答所指出的那样,!is.na(x) & x 是等价的。 - Ben Bolker
Ben,我非常同意这一点,它确实有效,但是遵循逻辑并不直观,因为你会陷入双重和三重否定的范式……这让我们许多人难以理解。难道没有更好、更直接的方法,不依赖于双重否定吗? - Jim Maas

7

我喜欢is.element函数:

is.element(a, T)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接