Dealing with TRUE, FALSE, NA and NaN

50,274

Solution 1

To answer your questions in order:

1) The == operator does indeed not treat NA's as you would expect it to. A very useful function is this compareNA function from r-cookbook.com:

  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 stands for "Not available", and is not the same as the general NaN ("not a number"). NA is generally used for a default value for a number to stand in for missing data; NaN's are normally generated because a numerical issue (taking log of -1 or similar).

3) I'm not really sure what you mean by "logical things"--many different data types, including numeric vectors, can be used as input to logical operators. You might want to try reading the R logical operators page: http://stat.ethz.ch/R-manual/R-patched/library/base/html/Logic.html.

Hope this helps!

Solution 2

You don't need to wrap anything in a function - the following works

a = c(T,F,NA)

a %in% TRUE

[1]  TRUE FALSE FALSE

Solution 3

So you want TRUE to remain TRUE and FALSE to remain FALSE, the only real change is that NA needs to become FALSE, so just do this change like:

a[ is.na(a) ] <- FALSE

Or you could rephrase to say it is only TRUE if it is TRUE and not missing:

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

Solution 4

I like the is.element-function:

is.element(a, T)

Solution 5

Taking Ben Bolker's suggestion above you could set your own function following the is.na() syntax

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

This also works for subsetting data.

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

And helps avoid accidentally incorporating empty rows where NA do exist in the data.

df[df$a == TRUE,]

      a  b
1     1  1
NA   NA NA
6     1  6
NA.1 NA NA
9     1  9
Share:
50,274
Remi.b
Author by

Remi.b

Updated on March 05, 2020

Comments

  • Remi.b
    Remi.b about 4 years

    Here is a vector

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

    I'd like a simple function that returns TRUE everytime there is a TRUE in "a", and FALSE everytime there is a FALSE or a NA in "a".

    The three following things do not work

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

    Here is a solution

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

    but it doesn't seem to be a straightforward and easy solution

    Is there another solution ?

    Here are some functions (and operators) I know:

    identical()
    isTRUE()
    is.na()
    na.rm()
    &
    |
    !
    
    • What are the other functions (operators, tips, whatever,...) that are useful to deal with TRUE, FALSE, NA, NaN?

    • What are the differences between NA and NaN?

    • Are there other "logical things" than TRUE, FALSE, NA and NaN?

    Thanks a lot !

  • Matthew Plourde
    Matthew Plourde almost 11 years
    Division by 0 is Inf, but Inf - Inf gives you NaN. A lot of times R functions will raise an exception if NaNs are generated, e.g., log(-1).
  • Ben Bolker
    Ben Bolker over 9 years
    you really don't need the ifelse() here -- as @GregSnow's answer points out, !is.na(x) & x is equivalent
  • Ari B. Friedman
    Ari B. Friedman about 9 years
    Nice solution. You can use it in functional form: '%in%'(aamc$forgive, FALSE) which is useful for apply and its ilk.
  • Jim Maas
    Jim Maas almost 4 years
    Very nice and useful solution when trying to build functions that will not throw errors etc. when using logical tests involving ">=", "<=", "==", etc. when it might be evaluated against a NA.
  • Jim Maas
    Jim Maas almost 4 years
    Ben, I really agree with this, and it works but it is not straight forward to follow the logic because you get into double and triple negatives paradigm .... which many of us find hard to follow. Is there not a better, more direct way that does not depend on double negatives ?
  • JRC
    JRC about 2 years
    eq = function(x,y) is.element(x == y, TRUE) | is.na(x) & is.na(y)