Course Notes Home

Making Choices

Our previous lessons have shown us how to manipulate data, and repeat things. However, the programs we have written so far always do the same things, regardless of what data they’re given.We want programs to make choices based on the values they are manipulating.

There are many instances where we need our code to do different things in different scenarioes. In other words, we need to write code that given some information automatically decides between multiple options. The tool R gives us for doing this is called a conditional statement, and looks like this:

num <- 37
if (num > 100) {
  print("greater")
} else {
  print("not greater")
}
print("done")
## [1] "not greater"
## [1] "done"

The second line of this code uses an if statement to tell R that we want to make a choice. If the following test is true, the body of the if (i.e., the lines in the curly braces underneath it) are executed. If the test is false, the body of the else is executed instead. Only one or the other is ever executed:

Executing a Conditional

In the example above, the test num > 100 returns the value FALSE, which is why the code inside the if block was skipped and the code inside the else statement was run instead.

num > 100
## [1] FALSE

And as you likely guessed, the opposite of FALSE is TRUE.

num < 100
## [1] TRUE

Conditional statements don’t have to include an else. If there isn’t one, R simply does nothing if the test is false:

num <- 53
if (num > 100) {
  print("num is greater than 100")
}

We can also chain several tests together when there are more than two options. For example if we wanted to write some code that returned the sign of a number:

num<- -3
if (num > 0) {
  print(1)
} else if (num == 0) {
  print(0)
} else {
  print(-1)
}
## [1] -1

Note that when combining else and if in an else if statement (similar to elif in Python), the if portion still requires a direct input condition. This is never the case for the else statement alone, which is only executed if all other conditions go unsatisfied. Note that the test for equality uses two equal signs, ==.

Other Comparisons

Other tests include greater than or equal to (>=), less than or equal to (<=), and not equal to (!=).

We can also combine tests. An ampersand, &, symbolizes “and”. A vertical bar, |, symbolizes “or”. & is only true if both parts are true:

if (1 > 0 & -1 > 0) {
    print("both parts are true")
} else {
  print("at least one part is not true")
}
## [1] "at least one part is not true"

while | is true if either part is true:

if (1 > 0 | -1 > 0) {
    print("at least one part is true")
} else {
  print("neither part is true")
}
## [1] "at least one part is true"

In this case, “either” means “either or both”, not “either one or the other but not both”.

We can also write a conditional to check if a character string in contained in a particular set. To this we use %in% which checks if the variable on the left is contained within the variable on the right.

pets<-c("cat", "dog", "horse") ## a vector of character strings
"cat" %in% pets
## [1] TRUE
"monkey" %in% pets
## [1] FALSE

As the outputs are TRUE or FALSE we can use this in an if else statement.

gw4<-c("Bath", "Bristol", "Cardiff", "Exeter")
location<-"Exeter"

if(location %in% gw4){
  print("Part of GW4")
} else {
  print("Outsider!")
}
## [1] "Part of GW4"
location<-"Newcastle"
if(location %in% gw4){
  print("Part of GW4")
} else {
  print("Outsider!")
}
## [1] "Outsider!"

If else statements can be used when you want to evaluate a conditional one by one. In other words it can only process one TRUE/FALSE statement at a time. Conditionals can also be used to subset vectors, matrices or data.frames.

numbers<-c(4,1,9,7,2,3)
numbers[numbers > 5]
## [1] 9 7
numbers[numbers < 0]
## numeric(0)

The %in% operator an also be used in a similar way.

pets<-c("cat", "dog", "horse") 
animals<-c("monkey", "cat", "dog", "cow", "cat")
animals[animals %in% pets]
## [1] "cat" "dog" "cat"

The presence of an ! at the beginning of the conditional inverts the meaning of the conditional statement. E.g to return all elements of animals that are not found in pets:

animals[!animals %in% pets]
## [1] "monkey" "cow"

There may be occasions where you need to know which elements satisfy a criteria, in this case which() can be used to identify which elements meet a conditional and returns a list of indexes that meet that condition.

numbers<-c(4,1,9,7,2,3)
which(numbers > 5)
## [1] 3 4
which(numbers < 0)
## integer(0)

If we want to count the number of elements that satisfy a criteria we can use sum(), as TRUE takes the value 1 and FALSE 0, summing across a logical vector of TRUE and FALSE effectively counts the number of TRUE. We can use ! in our criteria to instead count the number of FALSE (as they are converted to TRUE).

## count how many entries in numbers are greater than 5
sum(numbers > 5)
## [1] 2
## count how many entries in animals are not in pets
sum(!animals %in% pets)
## [1] 2

Next