18  Conditional Statements

18.1 If-else statements

Conditional statements, or “If-else statements” are very useful and extremely common in programming. In an if-else statement, the code first checks a particular true/false condition. If the condition is true, it performs one action, and if the condition is false, it performs another action.

A simple example of this is the absolute value function we saw in Chapter 3. Let’s define precisely what that function does:

\left|x\right| = \begin{cases} -x & \text{ if } x<0 \\ x &\text{ otherwise} \end{cases} If x<0, it returns -x (so that the number becomes positive). Otherwise, it returns just x: if x was positive it stays positive, and if x is zero it stays zero.

Although there already is an absolute value function in R that we saw in Chapter 3 (the abs() function), we can easily create our own function to do the same thing.

Let’s call this function my_abs() (my absolute value function):

my_abs <- function(x) {
  if (x < 0) {
    return(-x)
  } else {
    return(x)
  }
}

After if, we need to write the condition to check in parentheses (here x < 0). Then we write between the curly brackets ({ and }) what we want R to do if the condition is TRUE (here return -x). Then we write else and write between the curly brackets what we want R to do if the condition is FALSE (here return x).

Let’s go through what R does here given an input x. First R checks the condition x < 0. If it is TRUE it returns -x and it’s done. If it is FALSE it goes to the else and returns x.

Let’s test it out:

my_abs(-2)
[1] 2
my_abs(3)
[1] 3
my_abs(0)
[1] 0

18.2 The ifelse() function

The my_abs() function we wrote above only works with scalar inputs (vectors of length one). If we try use it with a vector it will return an error. A useful function in R is the ifelse() function, which can do if-else statements on vectors. The function takes 3 arguments:

  1. A logical vector (such as a condition to check).
  2. What to do when TRUE.
  3. What to do when FALSE.

Let’s use the ifelse() function to get the absolute value of the sequence (-3, -2, -1, 0, 1, 2, 3):

x <- -3:3
ifelse(x < 0, -x, x)
[1] 3 2 1 0 1 2 3

The first argument checks the condition x < 0. This will be TRUE for the first 3 elements, and FALSE everywhere else. Let’s see this:

x < 0
[1]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE

The second argument is what to do when the condition is TRUE. This is to turn the x to -x, which makes the negative values positive. We can see that it did precisely this for the first 3 elements.

The third argument is what to do when the condition is FALSE. By writing just x, we are telling R to leave those elements unchanged.

We can also use the ifelse() statement to create other types of variables. For example, we can use it to make character variables:

x <- -3:3
ifelse(x < 0, "Negative", "Non-negative")
[1] "Negative"     "Negative"     "Negative"     "Non-negative" "Non-negative"
[6] "Non-negative" "Non-negative"

When x<0, the output element is "Negative" and when x\geq 0, the output element is "Non-negative".

18.3 “If else-if else” statements

Sometimes we want to do one thing if a certain condition holds, another thing if a different condition holds, and something else in the remaining cases. An example of this is the “sign” function, which tells you the sign in front of a value:

sgn(x) = \begin{cases} -1 & \text{ if } x < 0 \\ 0 & \text{ if } x = 0 \\ +1 & \text{ otherwise} \\ \end{cases} If the value is negative, we get -1. If it’s zero we get 0. If it’s positive (the remaining case), we get +1.

To do this in R, we can nest several if-else statements. We simply write else if for the intermediate case:

sgn <- function(x) {
  if (x < 0) {
    return(-1)
  } else if (x == 0) {
    return(0)
  } else {
    return(+1)
  }
}

Like above, after if we write the condition to check in parentheses and in curly brackets what to do if the condition is TRUE. We then write else if and write another condition to check, as well as what to do when that condition is TRUE in curly brackets. We then write after else what to do if neither of the above conditions are TRUE.

Let’s go through what R does here. Given an input x:

  1. R checks the condition x < 0. If it is TRUE it returns -1. If it is FALSE it goes to the next step.
  2. R checks the condition x == 0. If it is TRUE it returns 0. If it is FALSE it goes to the next step.
  3. R returns +1 (happens if neither of the above conditions are TRUE).

Let’s try it out:

sgn(-2)
[1] -1
sgn(3)
[1] 1
sgn(0)
[1] 0

“If else-if else” statements with vectors

The above approach only works for scalars. If we want to do this with vectors, we can nest the ifelse() function inside itself like this:

x <- -3:3
x
[1] -3 -2 -1  0  1  2  3
ifelse(x < 0, -1, ifelse(x == 0, 0, 1))
[1] -1 -1 -1  0  1  1  1

Let’s take apart what’s happening in ifelse(x < 0, -1, ifelse(x == 0, 0, 1)) for an element in x:

  • R first checks for each element in x if x<0. If it is TRUE, it returns -1; if it is FALSE, it goes to the next ifelse().
  • If we go to the next ifelse(), it checks if the element satisfies x=0. If this is TRUE it returns 0; if it is FALSE, it returns +1.