In R, the operators “|” and “&” indicate the logical operations OR and AND. For example, to test if `x`

equals 1 **and** `y`

equals 2 we do the following:

` > x = 1; y = 2`

> (x == 1) & (y == 2)

[1] TRUE

However, if you are used to programming in C you may be tempted to write

#Gives the same answer as above (in this example...)

> (x == 1) && (y == 2)

[1] TRUE

At this point you could be lulled into a false sense of security and believe that they could be used interchangeably. **Big mistake.**

Let’s consider another example, this time a vector comparison:

> z = 1:6

> (z > 2) & (z < 5)

[1] FALSE FALSE TRUE TRUE FALSE FALSE

> z[(z>2) & (z<5)]

[1] 3 4

but the double “&&” gives

> (z > 2) && (z < 5)

[1] FALSE

> z[(z > 2) && (z < 5)]

integer(0)#Probably not what you want

It’s all gone a bit pear shaped! In fact it could have been worse:

> (z > 2) && (z < 5)

[1] TRUE

> z[(z > 0) && (z < 5)]

[1] 1 2 3 4 5 6

Now you’ve the wrong answer and something that would be very tricky to spot. This is because R recylces the `TRUE`

variable.

## What’s the difference?

Well from the R help page:

“The longer form evaluates left to right examining only the first element of each vector”

where the longer form refers to “&&”. So

> (z > 2) && (z < 5)

[1] FALSE

is equivalent to:

> (z[1] > 2) & (z[1] < 5)

[1] FALSE

The same concept applies to the OR operator, “|”.

As the commentators point out below, another key difference is for the longer form

“Evaluation proceeds only until the result is determined”

This concept is highlighted in the following example:

> f = function(){cat("My name is f\n");return(TRUE)}

> g = function(){cat("My name is g\n");return(FALSE)}

> f() | g()

My name is f

My name is g

[1] TRUE

> f() || g()

My name is f

[1] TRUE

This has two benefits:

- Evaluation will be faster. In the above example, the function
`g`

isn’t evaluated (thanks to Andrew Robson and NotMe) - Also, you can use the double variety to check a property of a data structure before carrying on with your analysis, i.e.
`all(!is.na(x)) && mean(x) > 0`

(thanks to Pat Burns for this tip)

Hi Colin,

X || Y performs sequential evaluation of X and Y.

From p. 22 of our lovely book[1] … X || Y is useful when Y is not always well-defined. Also, if Y takes a while to evaluate.

There are reasonably easy work-arounds for both conditions, but || and && provide a compact representation.

Best wishes

Andrew

[1] “Introduction to Scientific Programming and Simulation using R“, 2009, Chapman & Hall.

Comment by Andrew Robinson — December 15, 2010 @ 3:20 am

As is mentioned on ?”&&” you mainly use && in if-clauses. So something like if ((a==3) && (b==4) && (d==7)). So if (a==3) is NOT true, then R doesn’t need to look whether b==4 or d==7. Should be faster.

Comment by NotMe — December 15, 2010 @ 8:06 am

As an example of what the previous comments are talking about, you might have something like:

if(all(!is.na(x)) && mean(x) > 0) { …

The first part about missing values makes sure that you don’t run into trouble with the test on the mean (which is what you really care about).

Comment by Pat Burns — December 15, 2010 @ 9:44 am

Many thanks for your helpful comment. I’ve updated the post accordingly.

Comment by csgillespie — December 15, 2010 @ 5:03 pm

I think && and || have been badly implemented. In other languages they the conditional AND and OR operators, they perform a logical AND or OR boolean operations , but only evaluate its second operand if necessary.

Comment by joe — November 28, 2016 @ 6:50 pm

Say b1, b2, b3, … are boolean vectors.

Am I correct that the expression,

(b1 && b2 && b3 && …)

is always equivalent to this expression?

(b1[1] & b2[1] & b3[1] & …)

I think that’s consistent with the R documentation, “The longer form evaluates left to right examining only the first element of each vector.”

Same would then be true for | and ||, correct?

Comment by vknowles — September 6, 2019 @ 7:02 pm

They’re not quite the same. For example compare FALSE & stop() with FALSE && stop()

Comment by csgillespie — September 7, 2019 @ 10:10 am

They are slightly different. Compare FALSE & stop() with FALSE && stop()

Comment by csgillespie — September 7, 2019 @ 10:11 am

Yes, I see. They differ in whether the evaluation stops after the first FALSE result.

Thanks!

Comment by vknowles — September 8, 2019 @ 3:03 am