## 2.7 Logical Operators

In last section, you learned how to do vector subsetting, which yields a subvector of the original vector. Let’s take a numeric vector `x <- 1:5`

for example. In order to get a subvector of `x`

with values bigger than 3, you can first create a **logical vector** `xb3 <- x > 3`

, then use the `xb3`

as the index to do vector subsetting.

```
<- 1:5
x <- x > 3
xb3 <- x[xb3]
set1
set1#> [1] 4 5
```

Here, the numeric vector `set1`

has values `4 5`

. You can get another subvector of `x`

by running the following codes.

```
<- x <= 4
xs4 <- x[xs4] set2
```

Sometimes, you may want to get a subvector with more than one conditions. For example, how can we find the subvector of `x`

with values larger than 3 and less than or equal to 4? In this section, we will introduce several **logical operators** and use them to get subvectors. Here, we only introduce how to apply these operators on logical vectors.

Before we get started, let’s create another numeric vector `y`

and compare it to `8`

and `9`

separately, then you will get two logical vectors with same values as `xb3`

and `xs4`

.

```
<- 6:10
y <- y > 8 #xb3 is the same as yb8
yb8 <- y <= 9 #xs4 is the same as ys9 ys9
```

### 2.7.1 NOT operator by `!`

The first operator we want to introduce is `!`

, often called the **NOT operator**. The NOT operator returns the opposite logical value of the input logical values. It is intuitive to understand since if something is NOT FALSE, then it is TRUE; and if it is NOT TRUE, then it has to be FALSE.
It is summarized in the following table.

Operation | Result |
---|---|

!TRUE | FALSE |

!FALSE | TRUE |

Let’s see what happens if you apply the NOT operator on a logical vector.

```
!c(FALSE, FALSE, FALSE, TRUE, TRUE) #the opposite of a logical vector
#> [1] TRUE TRUE TRUE FALSE FALSE
```

From the result, you get another logical vector with the same length as the original one. The value of each element in the new vector is the **opposite** of the corresponding value in the original vector.

Since `xb3`

is also a logical vector, you can try to apply `!`

on `xb3`

, and use `!xb3`

(which is also a logical vector) to do vector subsetting. Guess what will you get?

```
!xb3
#> [1] TRUE TRUE TRUE FALSE FALSE
<- x[!xb3]
set3
set3#> [1] 1 2 3
```

Of course the resulting numeric vector `set3`

will have `1 2 3`

as values! As a result, `set1`

and `set3`

are complement of each other from the whole vector `x`

.

From Section 2.6, you have learned that if the logical vectors you use are identical, you will get the same result after doing vector subsetting. So if you use `!yb8`

to do vector subsetting, you will get a vector with the same result as that when you use `set3`

.

```
!yb8]
x[#> [1] 1 2 3
```

### 2.7.2 AND operator by `&`

Secondly, we will introduce the AND operator `&`

. Similar to making comparisons between two logical vectors, `&`

performs comparisons elementwisely, which generates a vector with the same length if the input logical vectors are of the same length or with the same length as that of the longer vector. For each location of the resulting vector, the value will be `TRUE`

if both values in the same location of the input two vectors are **both TRUE**, and will be

`FALSE`

otherwise. In particular, for each element, we have the following summary.Operation | Result |
---|---|

TRUE & TRUE | TRUE |

TRUE & FALSE | FALSE |

FALSE & TRUE | FALSE |

FALSE & FALSE | FALSE |

Let’s see an example of the AND operation between two logical vectors of the same length.

```
c(FALSE, FALSE, FALSE, TRUE, TRUE) & c(TRUE, TRUE, FALSE, TRUE, FALSE)
#> [1] FALSE FALSE FALSE TRUE FALSE
```

As explained before, the AND operator works elementwisely and the intermediate step is as below.

```
c(FALSE & TRUE, FALSE & TRUE, FALSE & FALSE, TRUE & TRUE, TRUE & FALSE)
#> [1] FALSE FALSE FALSE TRUE FALSE
```

As you can see from the result, only the fourth element is `TRUE`

since the fourth element of both input logical vectors is `TRUE`

.

Since the AND operator makes comparisons elementwisely, the *recycling rule* also works here. But normally we want one vector with length > 1 and another one with length 1.

```
c(FALSE, FALSE, FALSE, TRUE, TRUE) & FALSE
#> [1] FALSE FALSE FALSE FALSE FALSE
```

After learning about the AND operator, you can now get a subvector of `x`

with value(s) > 3 and <= 4 easily. At the beginning of this section, you have created two logical vectors `xb3`

and `xs4`

by making comparisons, then let’s apply `&`

on these vectors,

```
& xs4
xb3 #> [1] FALSE FALSE FALSE TRUE FALSE
```

From the result, you know that both `xb3`

and `xs4`

have value `TRUE`

for the fourth element, which means the statement that *the value is > 3 and <= 4* is TRUE for the fourth element in `x`

. Then you can use `xb3 & xs4`

(a logical vector) to do vector subsetting.

```
& xs4]
x[xb3 #> [1] 4
```

Here, you get a subvector of `x`

with value `4`

.

Since `xs4`

and `ys9`

have same values, you will get the same result if you include `ys9`

to get a subvector. You can try the following codes by yourself.

```
& ys9]
x[xb3 & ys9] x[yb8
```

Note that the logical vector used to do vector subsetting needs to be of the **same length** as the original vector. Since `x`

and `y`

have the same length, the logical vectors from above can be used to get subvectors of `y`

as well. You will get the same result from the following four codes.

```
& xs4]
y[xb3 & ys9]
y[yb8 & ys9]
y[xb3 & xs4] y[yb8
```

### 2.7.3 OR operator by `|`

The OR operator `|`

works similarly to the AND operator `&`

, but the difference is that `|`

returns `TRUE`

if there is **at least one** `TRUE`

among the two elements at the same location in two vectors. Let’s go through some examples together.

Operation | Result |
---|---|

TRUE | TRUE | TRUE |

TRUE | FALSE | TRUE |

FALSE | TRUE | TRUE |

FALSE | FALSE | FALSE |

Let’s try another example on length > 1 vectors and compare the result with that when we use the AND operator `&`

.

```
c(FALSE, FALSE, FALSE, TRUE, TRUE) | c(TRUE, TRUE, FALSE, TRUE, FALSE)
#> [1] TRUE TRUE FALSE TRUE TRUE
c(FALSE, FALSE, FALSE, TRUE, TRUE) & c(TRUE, TRUE, FALSE, TRUE, FALSE)
#> [1] FALSE FALSE FALSE TRUE FALSE
```

You also get a length-5 logical vector with an elementwise OR operation `|`

, which is very different from the result with AND operation `&`

.

Of course you can also use `xb3 | xs4`

to do vector subsetting, with it being another length-5 logical vector.

```
| xs4]
x[xb3 #> [1] 1 2 3 4 5
```

Wow! You get all five elements of `x`

! That’s because the statement “the value is either > 3 or <= 4” is TRUE for all elements in `x`

.

### 2.7.4 Exclusive OR by `xor`

Last but not least, we introduce the **exclusive OR** operator `xor`

. From the name, it’s easy to know that `xor`

is an extended form of `|`

. Here are some examples,

Operation | Result |
---|---|

xor(TRUE, TRUE) | FALSE |

xor(TRUE, FALSE) | TRUE |

xor(FALSE, TRUE) | TRUE |

xor(FALSE, FALSE) | FALSE |

Different from the OR operator, `xor()`

returns `TRUE`

when there is **one and only one** `TRUE`

among values of these two logical vectors. If these two vectors have the same value, both `TRUE`

or both `FALSE`

, you will get the value `FALSE`

.

For two length > 1 vectors, `xor()`

again performs comparisons elementwisely. You can check the result by yourself!

```
xor(c(FALSE, FALSE, FALSE, TRUE, TRUE), c(TRUE, TRUE, TRUE, TRUE, FALSE))
#> [1] TRUE TRUE TRUE FALSE TRUE
```

Since you also get a logical vector after applying `xor()`

, you can use it to do vector subsetting. Using different combinations to do vector subsetting is interesting. Try them!

```
xor(xb3, xs4)]
x[xor(!xb3, ys9)]
y[xor(yb8, !ys9)] y[
```

### 2.7.5 Summary of Logical Operators

Let’s summarize the logical operators between two vectors.

- The NOT operator
`!`

gives the opposite of each value. - The AND operator
`&`

returns`TRUE`

if both are`TRUE`

. - The OR operator
`|`

returns`TRUE`

if at least one is`TRUE`

. - The exclusive OR operator
`xor()`

returns`TRUE`

if one and only one is`TRUE`

.

### 2.7.6 Exercises

Consider the vector `v1 <- seq(from = 1, to = 100, by = 3)`

, and `v2 <- sqrt(v1)`

.

Find the subvector of

`v1`

with values bigger or equal to 30 and less than 60. And assign the subvector to name v1s.Find the subvector of

`v2`

such that the corresponding value of`v1`

is less than 20 or larger than 50.Use an example to verify \(xor(a, b) = (!a & b) | (a & !b)\)