Negating functions and function definitions: an 'opposite' function to the wonderful `%in%` operator


R has some neat functions, and even some weird quirks, that you aren’t likely to discover on your own but can either be immensely helpful or horribly confounding.

For example, the “+” operator (i.e. addition) is actually a function, and can even be called using the typical “bracket” notation:

1 + 2
## [1] 3

We can use backticks to evaluate the function as a “regular” function:

## function (e1, e2)  .Primitive("+")

And can therefore call it as a “regular” function, using brackets to pass the arguments:

`+`(1, 2)
## [1] 3

One consequence of this is that it is possible to redefine how “+” works:

`+` <- function(x1, x2) x1 - x2
1 + 2
## [1] -1

Ok … admittedly that’s confusing. Why would you want to redefine “+”? Well, one example is given by the syntax of the ggplot2 package, which defines it’s own version of “+” that lets you string plotting functions together to build up a plot (e.g. see my post about plotting here).

The %in% function

The %in% function is one of those functions that just clicked when I started using R. It’s an elegant way to write conditional statements – it checks whether the object to the left of the operator occurs anywhere in the object on the right of the operator. An example:

Does the number 5 occur in the vector of 1 through 10?

5 %in% 1:10
## [1] TRUE

Yes, it does (obviously).

One thing that I often find myself doing however, is wanting to know if something doesn’t occur in another object. To make that work, I usually wrap the whole statement in brackets and then precede with an ! operator (logical negation). Like this:

!(11 %in% 1:10)
## [1] TRUE

This evaluates to TRUE because 11 is not in the vector 1:10. While this works, it’s always bugged me because it just looks inelegant.

Well, while browsing Twitter recently, I came across this post from @groundwalkergmb:

First, note the (confusing) syntax that you don’t actually have to negate the entire expression. It is equivalent to write:

!11 %in% 1:10
## [1] TRUE

Ew. Gross! (@groundwalkergmb agrees with me about this)

But reading through the comments led me to this one:

Basically, you can use the Negate() function (never knew about this before) to create a new function which returns the logical negation of the output of the original.

`%nin%`<- Negate(`%in%`)
11 %nin% 1:10
## [1] TRUE