Opposite of %in%: exclude rows with values specified in a vector

A categorical variable V1 in a data frame D1 can have values represented by the letters from A to Z. I want to create a subset D2, which excludes some values, say, B, N and T. Basically, I want a command which is the opposite of %in%

D2 = subset(D1, V1 %in% c("B", "N", "T")) 
2

13 Answers

You can use the ! operator to basically make any TRUE FALSE and every FALSE TRUE. so:

D2 = subset(D1, !(V1 %in% c('B','N','T'))) 

EDIT: You can also make an operator yourself:

'%!in%' <- function(x,y)!('%in%'(x,y)) c(1,3,11)%!in%1:10 [1] FALSE FALSE TRUE 
7

How about:

`%ni%` <- Negate(`%in%`) c(1,3,11) %ni% 1:10 # [1] FALSE FALSE TRUE 
4

Here is a version using filter in dplyr that applies the same technique as the accepted answer by negating the logical with !:

D2 <- D1 %>% dplyr::filter(!V1 %in% c('B','N','T')) 
0

If you look at the code of %in%

 function (x, table) match(x, table, nomatch = 0L) > 0L 

then you should be able to write your version of opposite. I use

`%not in%` <- function (x, table) is.na(match(x, table, nomatch=NA_integer_)) 

Another way is:

function (x, table) match(x, table, nomatch = 0L) == 0L 
0

Using negate from purrr also does the trick quickly and neatly:

`%not_in%` <- purrr::negate(`%in%`) 

Then usage is, for example,

c("cat", "dog") %not_in% c("dog", "mouse") 
1

purrr::compose() is another quick way to define this for later use, as in:

`%!in%` <- compose(`!`, `%in%`) 

Another solution could be using setdiff

D1 = c("A",..., "Z") ; D0 = c("B","N","T") D2 = setdiff(D1, D0) 

D2 is your desired subset.

1

Hmisc has %nin% function, which should do this.

library(roperators) 1 %ni% 2:10 

If you frequently need to use custom infix operators, it is easier to just have them in a package rather than declaring the same exact functions over and over in each script or project.

1

The package has it built in: %!in%.

The help for %in%, help("%in%"), includes, in the Examples section, this definition of not in,

"%w/o%" <- function(x, y) x[!x %in% y] #-- x without y

Lets try it:

c(2,3,4) %w/o% c(2,8,9) [1] 3 4 

Alternatively

"%w/o%" <- function(x, y) !x %in% y #-- x without y c(2,3,4) %w/o% c(2,8,9) # [1] FALSE TRUE TRUE 
require(TSDT) c(1,3,11) %nin% 1:10 # [1] FALSE FALSE TRUE 

For more information, you can refer to:

In Frank Harrell's package of R utility functions, he has a %nin% (not in) which does exactly what the original question asked. No need for wheel reinvention.

You Might Also Like