Skip to course content
Free R data course

R Foundations for Data Analysis

Unit 04.03: case_when() stops at the first TRUE

case_when() stops at the first condition that is TRUE. That single fact is the whole lesson.

Order is meaning, not style

case_when() turns a set of conditions into a category column. It is evaluated top to bottom and takes the first match, so a broad condition placed above a narrow one makes the narrow one unreachable.

This is not an error. R cannot know which order you intended, so it produces a column that is entirely plausible and quietly wrong.

Two habits prevent it. Test missingness first, since NA fails ordinary comparisons and would otherwise fall through to whatever catch-all you wrote. And always supply .default so no row can come out as NA by accident.

This block bands a rate column, then deliberately reverses two conditions.


suppressPackageStartupMessages(library(dplyr))

rates <- data.frame(ward = c("North", "South", "East", "West", "Central"),
                    per_1000 = c(33.2, 39.6, 33.0, NA, 41.1))

banded <- rates |>
  mutate(band = case_when(
    is.na(per_1000)   ~ "not recorded",   # test missingness FIRST
    per_1000 >= 40    ~ "high",
    per_1000 >= 35    ~ "medium",
    .default          = "low"             # everything left over
  ))

print(banded)

# case_when stops at the first TRUE, so order is meaning, not style.
wrong <- rates |>
  mutate(band = case_when(per_1000 >= 35 ~ "medium",
                          per_1000 >= 40 ~ "high",
                          .default = "low"))
cat("\nWith the tests reversed, Central (41.1) is labelled:",
    wrong$band[wrong$ward == "Central"], "\n")
cat("No error, no warning. The 'high' band is simply never reached.\n")

In the correct version Central at 41.1 is high, South at 39.6 is medium, North and East are low, and West — which is NA — is labelled not recorded because the missingness test came first. In the reversed version Central is labelled medium: the >= 35 test matched first and the high band is unreachable. No error, no warning, and the mistake is invisible unless you check a value you already know the answer for.

The mistake this prevents

The mistake is writing bands in the order they appear in the report — low to high — while the conditions need the opposite order to work. It reads correctly and is wrong.

Takeaway

Put the missingness test first and .default last. Order the remaining conditions from narrowest to broadest, then verify one row per band by hand — the reversed version above cannot be caught any other way.