If else and case when

Conditional column values

SAS: IF-THEN-ELSE, IFN / IFC, SELECT

Use if_else() for one condition and two results. Use case_when() for several branches.

Quick reference

library(dplyr)

df |>
  mutate(
    AGEGR1 = if_else(AGE < 65L, "<65", ">=65")
  )

df |>
  mutate(
    AESEVN = case_when(
      AESEV == "MILD" ~ 1L,
      AESEV == "MODERATE" ~ 2L,
      AESEV == "SEVERE" ~ 3L,
      TRUE ~ NA_integer_
    )
  )
R SAS
if_else(cond, true, false) IFN / IFC, or if then ... else
case_when(cond ~ val, ...) SELECT / nested IF-THEN-ELSE
case_when(..., TRUE ~ other) OTHERWISE / final else

Trap: dplyr::if_else() is stricter on types than base ifelse(). Prefer if_else() in dplyr pipelines. case_when() stops at the first true condition.

Worked examples below.

Two-way: if_else()

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
dm <- data.frame(
  USUBJID = c("STD-001-0001", "STD-001-0002", "STD-001-0003"),
  AGE = c(54L, 70L, NA_integer_)
)

dm |>
  mutate(AGEGR1 = if_else(AGE < 65L, "<65", ">=65"))
       USUBJID AGE AGEGR1
1 STD-001-0001  54    <65
2 STD-001-0002  70   >=65
3 STD-001-0003  NA   <NA>

When AGE is NA, if_else() returns NA for that row (unless you set missing=).

SAS ifc(age < 65, "<65", ">=65") is the same idea for character results.

Multi-way: case_when()

ae <- data.frame(
  USUBJID = c("STD-001-0001", "STD-001-0002", "STD-001-0003", "STD-001-0004"),
  AESEV = c("MILD", "MODERATE", "SEVERE", NA_character_)
)

ae |>
  mutate(
    AESEVN = case_when(
      AESEV == "MILD" ~ 1L,
      AESEV == "MODERATE" ~ 2L,
      AESEV == "SEVERE" ~ 3L,
      TRUE ~ NA_integer_
    )
  )
       USUBJID    AESEV AESEVN
1 STD-001-0001     MILD      1
2 STD-001-0002 MODERATE      2
3 STD-001-0003   SEVERE      3
4 STD-001-0004     <NA>     NA

The first matching condition wins. End with TRUE ~ ... as the catch-all (SAS OTHERWISE).

ImportantPrefer if_else() over base ifelse() in dplyr

if_else() checks that true and false values share a type. Base ifelse() is looser and often surprises with factors and dates.

For "first non-missing of several columns," use coalesce() (see Coalesce), not case_when().