Conditional if

Conditional if statements allow programs to make decisions and execute different code based on whether certain conditions are TRUE or FALSE. For instance, we may want to perform a different action when a study participant is an adult or not:

IF (participant_age >= 18)
    DO SOMETHING
OTHERWISE
    DO SOMETHING ELSE

The basic syntax for conditional statements is if (condition) {}, where condition is an expression that evaluates to either TRUE or FALSE, i.e. a boolean. If it’s TRUE, the indented code block under the if statement will run. If FALSE, it will be skipped. For example, the below code will print “You are an adult” if age is 18 or higher.

age <- 18
if (age >= 18) {
    cat("You are an adult")
}
You are an adult

You can also add an else clause to specify code to run if the condition is FALSE:

age <- 17
if (age >= 18) {
    cat("You are an adult")
} else {
    cat("You are not an adult")
}
You are not an adult

For multiple conditions, you can use else if clauses to execute the first matching block.

age <- 14
if (age < 13) {
    cat("You are a child") 
} else if (age < 18) {
    cat("You are a teenager")
} else {
    cat("You are an adult")
}
You are a teenager
if statement syntax

An if statement has scaffolding as well as user-supplied parts. The scafolding is the word if, the parentheses () and the curly braces {} as shown below.

if  (my_number > 100)  {
    cat(my_number, "is large")
}

The user-supplied part is the conditional:

if (my_number > 100) {
    cat(my_number, "is large")
}

For readability, it is recommended to ident the body.

You can chain multiple conditions with else if using the same syntax. On the contrary, else provides a default case if no conditions are TRUE and do not requiere a condition.

Exercise

To explore the behaviour of the if statement, we could edit the below if.R to use some different logical statements. Make sure you remember to save the file after each change.

if.R
my_number <- 99

if (my_number > 100) {
    cat(my_number, "is large")
}

Less than:

my_number <- 74

if (my_number < 100) {
    cat(my_number, "is less than 100")
}
74 is less than 100


Equal to:

my_number <- 74

if (my_number == 100) {
    cat(my_number, "== 100") }
if (my_number == 74) {
    cat(my_number, "== 74") }
74 == 74


Not equal to:

my_number <- 74

if (my_number != 100) {
    cat(my_number, "!= 100")
}
74 != 100
if (my_number != 74) {
    cat(my_number, "!= 74")
}

Ordering your options

When working out which lines of code will be run, R will work down the list of if, else if and else and will run the first one that matches. Once it’s matched one, it will not bother checking to see if any of those later on would have matched. This means that you should order your questions from most-specific to least-specific.

For example, if you want to do one thing for positive numbers, but something special instead for numbers greater than 100, then you should put the more specific check first:

my_number <- 73

if (my_number > 100) {
    cat(my_number, "is large")
} else if ( my_number > 1) {
    cat(my_number, "is positive")
} else {
    cat(my_number, "negative")
}
73 is positive
Exercise

Create a file leap_year.R which calculates, for a given year, whether it is a leap year and prints out the answer. You might want to read the year in using input, or you could hard-code it in the program.

The rules to follow are:

  1. if the year is divisible by 400 then it’s a leap year,
  2. otherwise, if the year is divisible by 100 then it’s not,
  3. otherwise, if the year is divisible by 4 then it’s a leap year,
  4. otherwise, it’s not.

To simplify the writing of the program, you might find it easier to start with the divisible-by-4 condition, then add in the divisible-by-100 check and then add in the divisible-by-400 calculation.

For reference, here are some years for you to check against:

  • 2023 - not a leap year as it’s not divisible by 4
  • 2024 - a leap year as it’s divisible by 4 (and not by 100)
  • 1900 - not a leap year as it’s divisible by 100 (and not by 400)
  • 2000 - a leap year as it’s divisible by 400

Whenever solving a problem like this, it’s always good to build it up one step at a time. You could be tempted to jump right to the solution but it is easier to take small steps and check your results along the way than debugging a long piece of code.

Divisible by 4

The first step is to implement the simplest of the logical checks: is the year divisible by 4? If it is, print out an appropriate message checking that it works for a know leap year.

leap_year.r
year <- 2024

if (year %% 4 == 0) {
    cat(year, "is a leap year")
}
2024 is a leap year

For a year that we know is not a leap year, what do we get:

leap_year.r
year <- 2023

if (year %% 4 == 0) {
    cat(year, "is a leap year")
}

We get no output, so let’s fix that next, by adding an else:

leap_year.r
year <- 2024

if (year %% 4 == 0) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2024 is a leap year
leap_year.r
year <- 2023

if (year %% 4 == 0) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2023 is not a leap year

So far it’s looking like it’s doing the right thing. We have a working leap year calculator which covers most cases correctly.

Divisible by 100

Let’s check the next corner case: what happens if the year is divisible by 100. The rules say that this should not be a leap year:

leap_year.r
year <- 1900

if (year %% 4 == 0) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
1900 is a leap year

So it’s currently getting this wrong. We need to add in a check to see if the year is divisible by 100 and set it to be labelled as not a leap year.

Here we need to be careful as any number which is divisible by 100 is also divisible by 4 but we want a special thing to happen in the former case. The divisible-by-100 check is more specific than the divisible-by\(4\) check, so it must come first in the if-else if-else chain:

leap_year.r
year <- 2024

if (year %% 100 == 0) {
    cat(year, "is not a leap year")
} else if (year %% 4 == 0) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2024 is a leap year

(omitting repeated code)

2023 is not a leap year
1900 is not a leap year

Divisible by 400

The code is working for all those cases correctly, however, the last condition to think about is what happens for the year 2000:

leap_year.r
year <- 2000

if (year %% 100 == 0) {
    cat(year, "is not a leap year")
} else if (year %% 4 == 0) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2000 is not a leap year

This year should be a leap year as it is divisible by 400. Again this is more specific than the previous two so must be added before them in the chain:

leap_year.r
year <- 2024

if (year %% 400 == 0) {
    cat(year, "is a leap year")
} else if (year %% 100 == 0) {
    cat(year, "is not a leap year")
} else if (year %% 4 == 0) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2024 is a leap year

(omitting repeated code)

2023 is not a leap year
1900 is not a leap year
2000 is a leap year

Combining questions

It is possible to ask two or more questions in one go by combining them with and and or. So, if you want to check is a number is smaller than ten (my_number < 10) and is not equal to zero (my_number != 0), you can use:

if ( my_number<10 & my_number!=0 ) :
    ...

These combined checks can be used is both if and else if statements.

Exercise

Could you figure out how to rewrite leap_year.R with a single if-else statement?

year <- 2024

if ( (!(year %% 100 == 0) & (year %% 4 == 0)) | (year %% 400 == 0) ) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2024 is a leap year
leap_year.R
year <- 2023

if ( (!(year %% 100 == 0) & (year %% 4 == 0)) | (year %% 400 == 0) ) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2023 is not a leap year
leap_year.R
year <- 1900

if ( (!(year %% 100 == 0) & (year %% 4 == 0)) | (year %% 400 == 0) ) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
1900 is not a leap year
leap_year.R
year <- 2000

if ( (!(year %% 100 == 0) & (year %% 4 == 0)) | (year %% 400 == 0) ) {
    cat(year, "is a leap year")
} else {
    cat(year, "is not a leap year")
}
2000 is a leap year