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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With