59

Is there a short negation of %in% in R like !%in% or %!in%?


Of course I can negate c("A", "B") %in% c("B", "C") by !(c("A", "B") %in% c("B", "C")) (cf. this question) but I would prefere a more straight forward approach and save a pair of brackets (alike presumably most people would prefer c("A", "B") != c("B", "C") over !(c("A", "B") == c("B", "C"))).

Qaswed
  • 3,649
  • 7
  • 27
  • 47
  • @SpencerCastro I included a link to the question you mentioned. My question is different: I'm aware of the technical possibilities on how to negate %in%. My question is about whether there is a strait forward approach or not. And the answer given by user "catastrophic-failure" saying "No, [...] but ..." was what I wanted to know. – Qaswed Feb 26 '18 at 19:53
  • Great, I think linking these questions is helpful, because both provide a full explanation of solutions. – Spencer Castro Feb 26 '18 at 20:37

4 Answers4

96

No, there isn't a built in function to do that, but you could easily code it yourself with

`%nin%` = Negate(`%in%`)

Or

`%!in%` = Negate(`%in%`)

See this thread and followup discussion: %in% operator - NOT IN (alternatively here)


Also, it was pointed out the package Hmisc includes the operator %nin%, so if you're using it for your applications it's already there.

library(Hmisc)
"A" %nin% "B"
#[1] TRUE
"A" %nin% "A"
#FALSE
catastrophic-failure
  • 3,759
  • 1
  • 24
  • 43
11

You can always create one:

> `%out%` <- function(a,b) ! a %in% b

> 1:10 %out% 5:15
[1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

Otherwise there is a somewhat similar function with setdiff, which returns the unique elements of a that are not in b:

> setdiff(1:10,5:15)
[1] 1 2 3 4
> setdiff(5:15,1:10)
[1] 11 12 13 14 15
plannapus
  • 18,529
  • 4
  • 72
  • 94
  • 4
    You (or rather, the OP) should be careful with using `setdiff` instead of a negated `%in%` since, as the name indicates, it's a _set_ operation and hence, only returns _unique_ elements of `a` that are not in `b`. That may be a very different result from a negated `%in%`. – talat Jul 13 '16 at 12:50
  • True, i'll edit to make that point clearer. Thanks! – plannapus Jul 13 '16 at 12:52
8

Actually you don't need the extra parentheses, !c("A", "B") %in% c("B", "C") works.

If you prefer something that reads easier, just define it yourself:

"%nin%" <- function(x, table) match(x, table, nomatch = 0L) == 0L

This has the advantage of not wasting effort -- we don't get a result and then negate it, we just get the result directly. (the difference should generally be trivial)

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
4

The %!in% function is now available in the library(operators)

  • 2
    I just tried using this from the operators package. The packages seemed to be causing issues with dplyr::group_by() I didn't debug it, but the issue went away once I removed the library call. – BBlank Apr 04 '20 at 05:01