Advertisement
Advertisement

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

### Question

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'))
``````
2020/07/10
1
269
7/10/2020 11:06:54 AM

### Accepted Answer

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
 FALSE FALSE  TRUE
``````
2018/09/27
364
9/27/2018 10:04:16 PM

How about:

``````'%ni%' <- Negate('%in%')
c(1,3,11) %ni% 1:10
#  FALSE FALSE  TRUE
``````
2018/03/01

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
``````
2011/04/29

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'))
``````
2018/06/28

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")
``````
2018/05/22

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

```````%!in%` <- compose(`!`, `%in%`)
``````
2018/05/09

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]