R code

library("tidyverse")
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.4.0      ✔ purrr   0.3.5 
## ✔ tibble  3.1.8      ✔ dplyr   1.0.10
## ✔ tidyr   1.2.1      ✔ stringr 1.4.1 
## ✔ readr   2.1.3      ✔ forcats 0.5.2 
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()

TRUE/FALSE

Always use TRUE/FALSE and not T/F!

T
## [1] TRUE
F
## [1] FALSE
TRUE
## [1] TRUE
FALSE
## [1] FALSE

T and TRUE appear the same.

isTRUE(T)
## [1] TRUE
isTRUE(TRUE)
## [1] TRUE

But T can be reassigned.

T <- FALSE

isTRUE(T)
## [1] FALSE

TRUE cannot be reassigned.

TRUE <- FALSE
## Error in TRUE <- FALSE: invalid (do_set) left-hand side to assignment

The reason is because R has a short list of reserved words

?Reserved

NOT (!)

!TRUE
## [1] FALSE
!FALSE
## [1] TRUE

OR (|)

TRUE | TRUE
## [1] TRUE
TRUE | FALSE
## [1] TRUE
FALSE | TRUE
## [1] TRUE
FALSE | FALSE
## [1] FALSE

AND (&)

TRUE & TRUE
## [1] TRUE
TRUE & FALSE
## [1] FALSE
FALSE & TRUE
## [1] FALSE
FALSE & FALSE
## [1] FALSE

XOR (xor)

xor(TRUE, TRUE)
## [1] FALSE
xor(TRUE, FALSE)
## [1] TRUE
xor(FALSE, TRUE)
## [1] TRUE
xor(FALSE, FALSE)
## [1] FALSE

Multiple comparisons

Elementwise comparisons

The operations above perofrm elementwise comparisons.

b <- c(TRUE,FALSE)
x <- rep(b, times = 2)
y <- rep(b, each = 2)
x
## [1]  TRUE FALSE  TRUE FALSE
y
## [1]  TRUE  TRUE FALSE FALSE
x | y
## [1]  TRUE  TRUE  TRUE FALSE
x & y
## [1]  TRUE FALSE FALSE FALSE
xor(x,y)
## [1] FALSE  TRUE  TRUE FALSE
!x
## [1] FALSE  TRUE FALSE  TRUE

Left-to-right comparison

If you want left-to-right comparisons, you can use && and ||.

TRUE && TRUE && TRUE
## [1] TRUE
TRUE && TRUE && FALSE
## [1] FALSE
TRUE && FALSE && TRUE
## [1] FALSE
FALSE && FALSE && FALSE
## [1] FALSE
TRUE || TRUE || TRUE
## [1] TRUE
FALSE || FALSE || TRUE
## [1] TRUE
FALSE || FALSE || FALSE
## [1] FALSE

You will get a warning if you try to pass a vector to these left-to-right comparisons.

c(TRUE,FALSE) && c(TRUE,TRUE)
## Warning in c(TRUE, FALSE) && c(TRUE, TRUE): 'length(x) = 2 > 1' in coercion to
## 'logical(1)'

## Warning in c(TRUE, FALSE) && c(TRUE, TRUE): 'length(x) = 2 > 1' in coercion to
## 'logical(1)'
## [1] TRUE

any()

any(c(TRUE,   TRUE,  TRUE,  TRUE))
## [1] TRUE
any(c(TRUE,  FALSE, FALSE, FALSE))
## [1] TRUE
any(c(FALSE, FALSE, FALSE, FALSE))
## [1] FALSE

all()

all(c(TRUE,   TRUE,  TRUE,  TRUE))
## [1] TRUE
all(c(TRUE,  FALSE, FALSE, FALSE))
## [1] FALSE
all(c(FALSE, FALSE, FALSE, FALSE))
## [1] FALSE

Comparisons

Character

"a" == "a"
## [1] TRUE
"a" != "a"
## [1] FALSE
"a" == ""
## [1] FALSE
"a" != "b"
## [1] TRUE

Partial matching

grepl("a", "abcd")
## [1] TRUE
grepl("a", letters)
##  [1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [25] FALSE FALSE
grepl("a", LETTERS, ignore.case = TRUE)
##  [1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [25] FALSE FALSE

Numeric

a <- 1
b <- 2

a < b
## [1] TRUE
a > b
## [1] FALSE
a <= b
## [1] TRUE
a >= b
## [1] FALSE

Equality

a == 1
## [1] TRUE
a == 2
## [1] FALSE
a != 1
## [1] FALSE
a != 2
## [1] TRUE
a == b
## [1] FALSE
a != b
## [1] TRUE

Be careful with double precision

sin(0)    == 0
## [1] TRUE
sin(2*pi) == 0
## [1] FALSE
abs(sin(2*pi) - 0) < .Machine$double.eps^0.5
## [1] TRUE
near(sin(2*pi), 0)
## [1] TRUE

Force TRUE/FALSE

Not all seemingly logical functions return TRUE/FALSE.

all.equal(1,1)
## [1] TRUE
all.equal(1,2)
## [1] "Mean relative difference: 1"
all(c(TRUE, FALSE))
## [1] FALSE
all(c(TRUE, FALSE, NA))
## [1] FALSE
all(c(TRUE, TRUE,  NA))
## [1] NA

This can cause issues in flow control

if (all(c(TRUE, TRUE,  NA))) {
  # Do something
}
## Error in if (all(c(TRUE, TRUE, NA))) {: missing value where TRUE/FALSE needed

isTRUE()

The isTRUE() and isFALSE() functions ALWAYS resolve to TRUE/FALSE.

isTRUE(TRUE)
## [1] TRUE
isTRUE(NA)
## [1] FALSE
isTRUE(1)
## [1] FALSE
isTRUE(as.logical(NA))
## [1] FALSE
isTRUE(as.logical(1))  # all non-zero numeric values are coerced to TRUE
## [1] TRUE
isTRUE(as.logical(2))  
## [1] TRUE
isTRUE(as.logical(1e-16))  
## [1] TRUE
isFALSE(FALSE)
## [1] TRUE
isFALSE(NA)
## [1] FALSE
isFALSE(1)
## [1] FALSE
isFALSE(as.logical(NA))
## [1] FALSE
isFALSE(as.logical(0))  # only 0 is coerced to FALSE
## [1] TRUE
isFALSE(as.logical(2)) 
## [1] FALSE
isTRUE(all.equal(1,2))
## [1] FALSE
isFALSE(all.equal(1,2))
## [1] FALSE
isFALSE(!all.equal(1,1))
## [1] TRUE
isTRUE(NA)
## [1] FALSE
isFALSE(NA)
## [1] FALSE