Lesson 6 of 17 · Week 03 · Thu Oct 8

Control Flow

Questions

Objectives

Making decisions: if / else

x <- 12
if (x > 10) {
  print("big")
} else if (x > 5) {
  print("medium")
} else {
  print("small")
}

The condition inside if ( ) must be a single TRUE or FALSE. When you have a whole vector of comparisons, squash it into one answer with any() (is at least one TRUE?) or all() (are they all TRUE?). Combine conditions with && (and) and || (or).

any(gm$year == 1987)                 # TRUE: at least one row is from 1987
if (any(gm$lifeExp > 80)) print("Someone lives past 80 on average")

if can also return a value, which is handy for labels:

label <- if (x %% 2 == 0) "even" else "odd"

Adapted from Software Carpentry's “Control Flow” episode (CC BY 4.0, The Carpentries). Text, examples and exercises have been rewritten for this course.

Repeating steps: for loops

for (yr in c(1967, 2007)) {
  print(paste("The year is", yr))
}

The loop variable (yr) takes each value of the vector in turn. To loop over positions instead, use seq_along(v), which is safer than 1:length(v) when v might be empty.

Saving results from a loop. You can grow a vector with out <- c(out, new_value), but that gets slow for long loops. It's better to make the output first and fill it by position:

squares <- numeric(5)            # five zeros, ready to be filled
for (i in 1:5) {
  squares[i] <- i ^ 2
}

With a nested loop you have to work out each result's position yourself, e.g. (i - 1) * n_inner + j.

A preview: picking values with a condition

Loops over groups need one trick that the next lesson covers fully: v[condition] keeps only the elements of v where the condition is TRUE.

gm$lifeExp[gm$continent == "Europe"]          # Europe's life expectancies
for (cont in levels(gm$continent)) {
  m <- mean(gm$lifeExp[gm$continent == cont])
  print(paste(cont, round(m, 1)))
}

To store one result per group, use a named vector: res <- character(0) before the loop and res[cont] <- "something" inside it. startsWith(as.character(gm$country), "B") tests whether names start with a letter.

while loops

balance <- 1000
years <- 0
while (balance < 2000) {
  balance <- balance * 1.07
  years <- years + 1
}
years

A while loop runs as long as its condition stays TRUE. Make sure something inside it eventually makes the condition FALSE, or it runs forever (press Esc in Positron's console to stop it).

Loops are fine, but in R many loops can be replaced by one vectorized operation. That's the subject of Week 04.

Exercises

Each exercise gives you up to 10 checked attempts. Use Run as many times as you like to experiment first, then click Check answer when you're ready. Your exercises use numbers/subsets unique to you, so answers won't match a classmate's exactly.

Exercise 1 — Is that year in the data?

0 / 10 attempts used

Click Run to see two years, y1 and y2. For each one, write an if/else that sets a variable (report1 for y1, report2 for y2) to "found" if gm has any rows from that year and to "missing" otherwise. Use any(), and use the variables, not typed-in years.

Pasting isn't accepted here — please type your answer so it reflects your own work.

      

Exercise 2 — Grow vs. fill

0 / 10 attempts used

Click Run to see how grown was built by a nested loop that grows a vector (your loop sizes n_outer and n_inner differ from your classmates'). Build the same values in filled: create it at full length first with numeric(), then fill it by position inside the same nested loop.

Pasting isn't accepted here — please type your answer so it reflects your own work.

      

Exercise 3 — Continents above or below

0 / 10 attempts used

Click Run to see your cutoff. Write a for loop over the continents (levels(gm$continent)) that computes each continent's mean lifeExp (all years together) and stores "above" or "below" the cutoff in a named character vector verdict, e.g. verdict["Asia"].

Pasting isn't accepted here — please type your answer so it reflects your own work.

      

Exercise 4 — Three bands per country

0 / 10 attempts used

Loop over every country in gm and classify its 2007 life expectancy as "low" (under lo), "mid" (from lo up to, but not including, hi) or "high" (hi or more). Store the results in a named character vector band, one element per country. Click Run for your lo and hi.

Pasting isn't accepted here — please type your answer so it reflects your own work.

      

Exercise 5 — Advanced: flag some countries

0 / 10 attempts used

Loop over the countries whose names start with letter (click Run to see it; use startsWith()). Collect in a character vector flagged the names of those whose mean life expectancy over all four years is below limit.

Extra, on your computer: for each flagged country, draw life expectancy against year with plot(..., type = "l").

Pasting isn't accepted here — please type your answer so it reflects your own work.

      

Key Points

Proof of completion

Once you've attempted every exercise above, download a PDF summary of your work on this lesson — your name, the exercises you passed, attempt counts, timing, and your final code for each.