Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant version of %in% in R that returns NA?

Tags:

r

So, I was surprised by the behavior of the third line of this R code:

x <- c(1, 2, 3, 4, NA, 5, 6, 7, 8)
ifelse(x < 4, 1, 0)
ifelse(x %in% 1:3, 1, 0)

It returns 1,1,1,0,0,0,0,0,0 not the 1,1,1,0,NA,0,0,0,0 that I assumed I would get, ie the same as the second line. Closer inspection of the helpfile for %in% and match shows this is documented behavior, returning:

"A logical vector, indicating if a match was located for each element of x: thus the values are TRUE or FALSE and never NA."

Is there a general function that is similar to %in% except that it would give an NA in this circumstance? For instance, this returns the desired result:

`%inna%` <- function(x, table){
  y <- match(x, table, nomatch = 0) > 0
  y[is.na(x)] <- NA
  return(y)
}

ifelse(x %inna% 1:3, 1, 0)

But is there a common way of doing this?

like image 281
Peter Ellis Avatar asked Jun 08 '18 05:06

Peter Ellis


Video Answer


1 Answers

We can replace with NA by either multiplying NA generated using is.na(x)

(x %in% 1:3) * NA^(is.na(x))
#[1]  1  1  1  0 NA  0  0  0  0

Or use replace

replace(+(x %in% 1:3), is.na(x), NA)
#[1]  1  1  1  0 NA  0  0  0  0

It can be converted to a function

`%inna%` <- function(x, table) {
      replace(as.integer(x %in% table), is.na(x), NA)
 }

x %inna% 1:3
#[1]  1  1  1  0 NA  0  0  0  0
like image 147
akrun Avatar answered Nov 07 '22 23:11

akrun