2.13 Logical Vectors: Logical Operators
In Section 2.5, you learned how to do vector subsetting, which yields a subvector of the original vector. Let’s take a numeric vector x <- 1:5
as an example. To get a subvector of x
with values greater than 3, you can create a logical vector, and then use it as the index to do vector subsetting.
Here, the numeric vector set1
has values 4 5
. You can get another subvector of x
by running the following codes.
Sometimes, you may want to get a subvector containing elements that satisfy 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 will focusing on applying logical operators on logical vectors, but keep in mind that many of the example here could be used to express complex arguments in R.
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 the same values as xb3
and xs4
.
2.13.1 NOT operator by !
The first operator we want to introduce is !
, often called the NOT operator. The NOT operator returns the opposite 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. The effect of !
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 with more than one element.
!c(FALSE, FALSE, FALSE, TRUE, TRUE) #the opposite of a logical vector
#> [1] TRUE TRUE TRUE FALSE FALSE
Here, you get another logical vector with the same length as the original one. The value of each element in the output is the opposite of the corresponding value in the original vector.
Since xb3
is also a logical vector, you can apply !
on xb3
and use !xb3
(which is also a logical vector) to do vector subsetting. Guess what you will get?
Of course, the resulting numeric vector set3
will have 1 2 3
as values! As a result, set1
and set3
are complements of each other from the whole vector x
. We can actually get back x
with xb3
alone, with some help of vector subsetting and vector concatenation introduced in previous sections.
2.13.2 AND operator by &
Now, we will introduce the AND operator &
. For two logical vectors of the same length, &
performs comparisons elementwisely. For each location of the resulting vector, the value will be TRUE
if the 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. As in the arithmetic operations, normally, we mix one vector with length > 1 and another one with length 1.
Using the AND operator, you can now easily get a subvector of x
with value(s) > 3 and <= 4. Recall that at the beginning of this section, you have created two logical vectors xb3
and xs4
, then let’s apply &
on them,
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.
Here, you get a subvector of x
with the value 4
.
Since xs4
and ys9
have the same values, you will get the same result if you include ys9
to get a subvector. Therefore, you can try the following codes by yourself.
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 also be used to get subvectors of y
. For example, you will get the same result from the following four codes.
2.13.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 the two vectors. The working mechanism of |
is summarized below.
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 &
.
Naturally, you can also use xb3 | xs4
to do vector subsetting, leading to another length-5 logical vector.
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.13.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 |
Unlike 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!
2.13.5 Summary of Logical Operators
Let’s summarize the logical operators between two vectors.
- The NOT operator
!
returns the opposite of each value. - The AND operator
&
returnsTRUE
if both areTRUE
. - The OR operator
|
returnsTRUE
if at least one isTRUE
. - The exclusive OR operator
xor()
returnsTRUE
if one and only one isTRUE
.
2.13.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 than 30 and less than 60. And assign the subvector to name v1s.Find the subvector of
v2
such that the corresponding value ofv1
is less than 20 or larger than 50.Use an example to verify \[xor(a, b) = (!a & b) | (a & !b)\]