The Ultimate Guide to Logical Operators in R

A deep dive into logical operators in R. Learn how to change or compare results of comparisons made using relational operators with NOT, OR and AND in R.

Written by Linda Ngo
A collage of shapes and logical operators.
Image: Shutterstock / Built In
Brand Studio Logo
UPDATED BY
Brennan Whitfield | Jan 28, 2025

Suppose we want to change or compare the results of the comparisons made using relational operators. How would we go about doing that?

 R does this using the AND, OR and NOT operators.

Logical Operators in R

  • AND Operator: Represented using an ampersand, this operator takes two logical values and returns TRUE only if both values are TRUE themselves.
  • OR Operator: Denoted using the pike symbol, this operator takes two logical values and returns TRUE if just one value is TRUE.
  • NOT Operator: Represented using an exclamation mark, this operator negates the logical value it’s used on.

 

A tutorial on logical operators in R. | Video: DataCamp

AND Operator “&”

The AND operator takes two logical values and returns TRUE only if both values are TRUE themselves. This means that TRUE & TRUE evaluates to TRUE, but that FALSE & TRUE, TRUE & FALSE and FALSE & FALSE evaluates to FALSE.

Only TRUE and TRUE will give us TRUE.
Only TRUE and TRUE will give us TRUE. | Screenshot: Linda Ngo

Instead of using logical values, we can use the results of comparisons. Suppose we have a variable x that is equal to 12. To check if this variable is greater than 5 but less than 15, we can use x greater than 5 and x less than 15.

x <- 12
x > 5 & x < 15

The first part, x > 5, will evaluate to TRUE because 12 is greater than 5. The second part, x < 15, will also evaluate to TRUE because 12 is also less than 15. So, the result of this expression is TRUE since TRUE & TRUE is TRUE. This makes sense, because 12 lies between 5 and 15.

However, if x were 17, the expression x > 5 & x < 15 would simplify to TRUE & FALSE, which would result in the expression being FALSE.

AND Operator Example Problem 1

Consider the following vector and variable:

linkedin <- c(16, 9, 13, 5, 2, 17, 14)
last <- tail(linkedin, 1)

The linkedin vector represents the number of LinkedIn views your profile has gotten in the last seven days. The last variable represents the last value of the linkedin vector.

Determine whether the last variable is between 15 and 20, excluding 15 but including 20.

Example 1 Solution

# We are looking for the R equivalent of 15 < last <= 20
last > 15 & last <= 20
The last variable of LinkedIn is 14, which is not between 15 and 20.
The last variable of LinkedIn is 14, which is not between 15 and 20. | Screenshot: Linda Ngo

AND Operator Example Problem 2

Consider the following vectors:

linkedin <- c(16, 9, 13, 5, 2, 17, 14)
facebook <- c(17, 7, 5, 16, 8, 13, 14)

The linkedin vector represents the views on your LinkedIn profile from the past seven days, and the facebook vector represents the views on your Facebook profile from the past seven days.

Determine when LinkedIn views exceeded 10 and Facebook views failed to reach 10 for a particular day. Use the linkedin and facebook vectors. 

Example 2 Solution

# linkedin exceeds 10 but facebook below 10
linkedin > 10 & facebook < 10
Only on the third day were the LinkedIn views greater than 10 but the Facebook views less than 10.
Only on the third day were the LinkedIn views greater than 10 but the Facebook views less than 10. | Screenshot: Linda Ngo

AND Operator Example Problem 3

Consider the following matrix:

views <- matrix(c(linkedin, facebook), nrow = 2, byrow = TRUE)

The linkedin and facebook variable corresponds to the same vectors in the previous example.

The first and second rows in the matrix views corresponds to the linkedin and facebook vectors, respectively.

Determine when the views matrix equals a number between 11 and 14, excluding 11 and including 14.

Example 3 Solution

# When is views between 11 (exclusive) and 14 (inclusive)?
views > 11 & views <= 14
On the third and last day, the LinkedIn views were between 11 (exclusive) and 14 (inclusive). On the sixth and last day, the Facebook views were between 11 (exclusive) and 14 (inclusive).
On the third and last day, the LinkedIn views were between 11 (exclusive) and 14 (inclusive). On the sixth and last day, the Facebook views were between 11 (exclusive) and 14 (inclusive). | Screenshot: Linda Ngo

RelatedPipe in R: A Guide

 

OR Operator “|”

The OR operator | works similarly to the AND operator &, but the difference is that only one of the logical values needs to be equal to TRUE for the entire OR operation to evaluate to TRUE.

This means that TRUE | TRUE equals TRUE, but also, TRUE | FALSE and FALSE | TRUE evaluates to TRUE. When both logicals are FALSE in an OR operation, FALSE | FALSE, the result is FALSE. Remember, the OR operation is not an exclusive OR operation, so TRUE | TRUE equals TRUE as well.

Only FALSE and FALSE will give us FALSE.
Only FALSE and FALSE will give us FALSE. | Screenshot: Linda Ngo

With the AND operator, only TRUE & TRUE makes a TRUE, anything else is FALSE. With the OR operator, only FALSE | FALSE makes a FALSE, anything else is TRUE.

Just as in AND operations, we can use comparisons together with the OR operator. Suppose we have a variable y that equals 4. To see if this variable is less than 5 or greater than 15, we can use the following expression:

y <- 4
y < 5 | y > 15

R will first carry out the comparisons, resulting in TRUE | FALSE, which in turn, results in TRUE.

Now, suppose y is 14. The expression y < 5 | y > 15 now evaluates to FALSE | FALSE. Neither one of the comparisons are TRUE, so the result is FALSE.

OR Operator Example Problem 1

Using the same variables from the “AND operator example problem 3,” determine if last is under 5 or above 10.

linkedin <- c(16, 9, 13, 5, 2, 17, 14)
last <- tail(linkedin, 1)

Example 1 Solution

# Is last under 5 or above 10?
last < 5 | last > 10
The last element of LinkedIn is 14, and while it is under five, it is above 10, making the expression evaluate to true.
The last element of LinkedIn is 14, and while it is under 5, it is above 10, making the expression evaluate to true. | Screenshot: Linda Ngo

OR Operator Example Problem 2

Consider the same linkedin and facebook vectors from the previous example.

linkedin <- c(16, 9, 13, 5, 2, 17, 14)
facebook <- c(17, 7, 5, 16, 8, 13, 14)

Determine when one or both social profiles were visited at least 12 times.

Example 2 Solution

# When were one or both visited at least 12 times?
linkedin >= 12 | facebook >= 12
On days 1, 3, 4, 6 and 7, one or both social profiles were visited at least 12 times.
On days 1, 3, 4, 6 and 7, one or both social profiles were visited at least 12 times. | Screenshot: Linda Ngo

RelatedGrouping Data With R: A Guide

 

NOT Operator “!”

The NOT operator, represented by an exclamation mark !, simply negates the logical value it’s used on. That is, !TRUE evaluates to FALSE, while !FALSE evaluates to TRUE.

!TRUE evaluates to FALSE, while !FALSE evaluates to TRUE.
!TRUE evaluates to FALSE, while !FALSE evaluates to TRUE. | Screenshot: Linda Ngo

Just like the OR and AND operators, we can use the NOT operator in combination with logical operators. This is not always necessary. For example, !(x < 5) is the same as x >= 5.

However, there are cases in R where the NOT operator is especially handy. For example, the built-in R function is.numeric() checks if an R object is a numeric. There is no respective built-in function that checks if it isn’t a numeric. To check, we would have to negate the result (!is.numeric()). So, is.numeric(5) evaluates to TRUE, as 5 is a numeric. If we negate this result using the NOT operator (!is.numeric(5)), we get FALSE. If, however, we use is.numeric("hello") we get FALSE. Negating this result (!is.numeric("hello")) gives us TRUE.

RelatedA Guide to C++ Or, And and Not Logical Operators

 

Logical Operators and Vectors

Now, how do logical operators work with vectors and matrices? Just as relational operators, they perform the operations element-wise. Consider these two vectors:

c(TRUE, TRUE, FALSE) & c(TRUE, FALSE, FALSE)

The AND operation on these two vectors, results in a vector with the elements TRUE, FALSE and FALSE.

TRUE FALSE FALSE

The first elements in both vectors are TRUE, so the first element of the resulting vector contains TRUE. The same holds true for the second elements, where TRUE & FALSE result in FALSE, and in the third elements, where FALSE & FALSE give FALSE.

A similar thing happens with the OR operator:

c(TRUE, TRUE, FALSE) | c(TRUE, FALSE, FALSE)

TRUE | TRUE gives TRUE, TRUE | FALSE also gives TRUE, and FALSE | FALSE gives FALSE. So, we would get the result:

TRUE TRUE FALSE

The NOT operator also works on every element on the vector:

!c(TRUE, TRUE, FALSE)

TRUE are converted to FALSE, and FALSE are converted to TRUE. So, we would get the result:

FALSE FALSE TRUE
Using logical operators for true-false statements.
Using logical operators for true-false statements. | Screenshot: Linda Ngo

Logical Operators and Vectors Example Problem

What would the following set of R expressions return:

x <- 5
y <- 7
!(!(x < 4) & !!!(y > 12))

Solution

FALSE

To find the answer, it’s helpful to break the query down to smaller expressions.

We first have the left expression !(x < 4) of the inner expression (!(x < 4) & !!!(y > 12)).

  1. x < 4: Since x is 5, and 5 < 4 is not true, this statement evaluates to FALSE.
  2. !(x < 4): From the step above, we determined that x < 4 evaluates to FALSE. Negating this result gives us !FALSE, which is TRUE.

Next, we have the right expression !!!(y > 12) of the inner expression (!(x < 4) & !!!(y > 12)).

  1. y > 12: Since y is 7, and 7 > 12 is not true, this expression evaluates to FALSE.
  2. !(y > 12): Negating the result from step one, we get !FALSE, or TRUE.
  3. !!(y > 12): Negating the result from step two, we get !TRUE, or FALSE.
  4. !!!(y > 12): Negating the result from step three, we get !FALSE, or TRUE.

So, for the inner expression (!(x < 4) & !!!(y > 12)), it evaluates to TRUE & TRUE, which equals TRUE.

The outer NOT operator ! negates this TRUE making !(!(x < 4) & !!!(y > 12)) equal to !TRUE or FALSE.

RelatedHow to Show All Columns and Rows in a Pandas DataFrame

 

Single vs. Double Operators in R

What is the difference between a single and a double ampersand or vertical bar? In R, you can use both the single sign version or the double sign version, but the result of the logical operation you’re carrying out can be different. The biggest difference occurs when you use the two types of operations on vectors.

“&” vs. “&&” in R

c(TRUE, TRUE, FALSE) & c(TRUE, FALSE, FALSE)

As we’ve seen before, the above expression evaluates to a vector:

TRUE FALSE FALSE

However, if we use &&, we simply get TRUE.

c(TRUE, TRUE, FALSE) && c(TRUE, FALSE, FALSE)

This is because the double AND operation only examines the first element of each vector. In this case, the first elements are TRUE and TRUE, so the expression returns TRUE.

Using the && operator R.
Using the && operator R. | Screenshot: Linda Ngo

“|” vs. “||” in R

You can see similar things happening with the OR operator. The single sign version | returns an entire vector. The double sign version || returns the result of the OR operator on the first element of each vector.

Using the || operator in R.
Using the || operator in R. | Screenshot Linda Ngo

So pay attention when doing logical operations on vectors. You will likely want to use the single sign version for most actions.

 

Tips For Using Logical Operators in R

When using logical operators in R, it’s important to remember a few key points about them to ensure code runs smoothly.

Remember Operator Precedence

In R, all operators, including logical operators, follow a specific order of precedence. This means certain operators will execute before others, regardless of where they are written in a line of code. Understanding the precedence of logical operators — both in relation to each other and other types of operators in R — is crucial for writing accurate and predictable code. 

For logical operators in R, the operator precedence is as follows:

  1. NOT operator (!)
  2. AND operator (& and &&)
  3. OR operator (| and ||)

Use the Correct AND and OR Operators

In R, both the AND operator and OR operator come with two variations each — & and && for AND, as well as | and || for OR. Though these variations use the same symbols, they perform different operations, so it’s important to understand the differences between them and use them appropriately based on the context. 

Here’s when to use each variation of the AND and OR logical operators in R:

  • When to use &: For comparing every element between vectors (element-wise), where both corresponding elements of a pair must be TRUE to return TRUE.
  • When to use &&: For comparing only the first element between vectors, where both elements must be TRUE to return TRUE.
  • When to use |: For comparing every element between vectors (element-wise), where at least one of the corresponding elements of a pair must be TRUE to return TRUE.
  • When to use ||: For comparing only the first element between vectors, where at least one of the corresponding elements must be TRUE to return TRUE.

Frequently Asked Questions

In R, && is a form of the logical AND operator used to evaluate only the first element of each given vector. When using && to compare two vectors, both of the first elements of each vector must be equal to TRUE to get a return of TRUE.

In R, & and && are both forms of the logical AND operator (which takes two logical values and returns TRUE only if both values are TRUE), though they have different uses. The & operator is element-wise, meaning it goes over all elements between given vectors and only returns TRUE if both corresponding elements in a pair are TRUE. The && operator only applies to the first element of a vector, and returns TRUE if both of the first elements of given vectors are TRUE.

%>%, known as the pipe operator in R, forwards (“pipes”) a value or the output of an expression into the next function in a code sequence. In other words, %>% takes the output of the expression on its left and passes it as the first argument to the function on its right. It tends to be used to chain R functions together and achieve a similar goal as nesting. %>% is included in the magrittr package in R.

Explore Job Matches.