Logical operators

1 The functions

Here, we have to use logical operators to combine different filter conditions:

  • X & Y: this means X and Y are both true
  • X && Y: this means X and Y are both true, but if X is FALSE, then R won’t evaluate Y; this is called short-circuited evaluation, and it can be very useful
  • X | Y: this means either X or Y or both are true
  • X || Y: this means either X or Y or both are true, but if X is TRUE, then R won’t evaluate Y; as you might guess, this is also called short-circuit evaluation
  • any(aVector): this means if any term in aVector is TRUE, then this is TRUE
  • all(aVector): this means for this to be true, then all terms in aVector must be true
  • aValue %in% aVector: this returns TRUE if aValue is one of the terms within aVector

2 Examples

Now, let’s take a look at some examples of how we might use these logical operators in conjunction with the comparison operators above. We continue to use the variables that we defined above.

First, let’s look at these most basic logical operators:

> 3 & 0
[1] FALSE

Okay, that was simple: “are both 3 and 0 true? And then answer is no since 0 is false. The only way for x & y to be true is for every single argument to be true.

Here are a couple more examples:

> 3 | 0
[1] TRUE
> 3 || 0
[1] TRUE

Recall, from our previous definitions, that 0 is equivalent to FALSE and all other numerical values are equivalent to TRUE. Thus, these examples (both of which can be translated as is 3 or 0 true?) must be TRUE (since 3 is true). The difference between the two is that the second one is more computationally efficient since it stops evaluating after it sees that the first argument, 3, is true.

The any() function is equivalent to the or operator. This checks if any of the arguments to the function are true; if so, then it returns TRUE:

> any(3, 0)
[1] TRUE
Warning message:
In any(3, 0) : coercing argument of type 'double' to logical

Notice this warning message. The function is still returning a value but R is telling you that it has had to coerce an argument from type double to type logical. That’s fine, and what we expected. It also does so if the argument to any() is either a vector or a list:

> any(c(3, 0))
[1] TRUE
Warning message:
In any(c(3, 0)) : coercing argument of type 'double' to logical
> any(list(3, 0))
[1] TRUE
Warning message:
In any(list(3, 0)) : coercing argument of type 'list' to logical

However, what if we don’t want it to print out this warning message? Well, you can get rid of this message by surrounding the function with the suppressWarnings() function, as this shows:

> suppressWarnings(any(3, 0))
[1] TRUE

It returns the value from any() as before, but now it does not print out the warning.

Now, let’s look at the all() function. This reports on whether or not all of its arguments are true:

> all(3, 2, 5, 3, 1, 0)
[1] FALSE
Warning messages:
1: In all(3, 2, 5, 3, 1, 0) :
  coercing argument of type 'double' to logical
2: In all(3, 2, 5, 3, 1, 0) :
  coercing argument of type 'double' to logical
3: In all(3, 2, 5, 3, 1, 0) :
  coercing argument of type 'double' to logical
4: In all(3, 2, 5, 3, 1, 0) :
  coercing argument of type 'double' to logical
5: In all(3, 2, 5, 3, 1, 0) :
  coercing argument of type 'double' to logical
6: In all(3, 2, 5, 3, 1, 0) :
  coercing argument of type 'double' to logical

Note a couple of things:

  • It returns FALSE because the last argument, 0, is false. The function all(), again, only returns TRUE if every argument is true.
  • Six separate warnings are returned because all six arguments are of type double, and each of them has to be coerced to type logical.

As before, we can use the suppressWarnings() function to stop R from showing the warning messages:

> suppressWarnings(all(3, 2, 5, 3, 1, 0))
[1] FALSE

The following are examples of how to use the %in% operator that tests if a value can be found in a vector or list:

> "Dave" %in% names
[1] TRUE
> "Melinda" %in% names
[1] FALSE

One nice feature of R is that you can also test if a vector or list of values can be found in a vector or list. For example:

> c("Scott", "Melinda") %in% names
[1]  TRUE FALSE

The following is a nice example of the power of the composition of functions in R. Here we count (using sum()) the number of values in the list() are found in names:

> sum(list("Dave", "Scott", "Melinda") %in% names)
[1] 2

We can see that two of the items in the list() that are found in names.

You can also use either any() or all() on an existing variable (in this case vals):

> any(vals)
[1] TRUE
Warning message:
In any(vals) : coercing argument of type 'double' to logical
> all(vals)
[1] FALSE
Warning message:
In all(vals) : coercing argument of type 'double' to logical

As before, you can use suppressWarnings() to stop R from displaying warning messages:

> suppressWarnings(any(vals))
[1] TRUE

Finally, here are a few examples that demonstrate the or operators. Recall that 900 >= min_score is FALSE while "Lindsey" %in% names is TRUE. Thus, in the first statement, R determines that it is equivalent to FALSE | TRUE which is TRUE. In the second statement, R determines that the first clause is FALSE, and then it evaluates the second clause to be TRUE, and thus it returns TRUE; this is the short-circuit form of or so it will stop evaluating the statement as soon as it determines the answer.

> 900 >= min_score | "Lindsey" %in% names
[1] TRUE
> 900 >= min_score || "Lindsey" %in% names
[1] TRUE

In this statement, once it evaluates the first clause to be TRUE, it stops evaluating and returns TRUE:

> "Lindsey" %in% names || 900 >= min_score
[1] TRUE

Clearly, the computational savings of this is quite minimal, but the benefit would accrue over multiple terms and millions of repetitions.