Introduction to Conditionals in R
Conditional statements let an R program choose which block of code to execute based on whether a logical expression evaluates to TRUE or FALSE. Every conditional in R ultimately reduces to a single logical value — TRUE, FALSE, or NA — that determines the path execution takes, whether that decision is made once for a whole program's flow or repeated across thousands of rows in a data set.
Cricket analogy: A captain deciding whether to review an lbw call works like an if statement: if the on-field decision looks marginal and wickets remain, review it; otherwise, accept the umpire's call and move on.
The if, else if, and else Statements
R's if statement evaluates a single logical condition inside parentheses and executes the following block only when that condition is TRUE; chaining else if clauses lets you test additional mutually exclusive conditions in order, and a final else catches everything that didn't match. Since R 4.2.0, passing a condition of length greater than one to if() throws an error rather than a warning, so conditions must resolve to exactly one TRUE or FALSE value.
Cricket analogy: Selecting a bowler works like if/else if/else: if the pitch is dry and cracked, bring on the spinner; else if the ball is still new and seaming, use the fast bowler; else rotate the part-timers — mutually exclusive, ordered checks.
classify_score <- function(score) {
if (score >= 90) {
"A"
} else if (score >= 80) {
"B"
} else if (score >= 70) {
"C"
} else {
"F"
}
}
classify_score(85) # "B"Vectorized Conditionals with ifelse()
The vectorized ifelse(test, yes, no) function evaluates a logical vector element by element and returns a same-length vector picking from yes or no at each position, making it the natural tool for recoding an entire column in a data frame without writing an explicit loop. Unlike if, which requires a single logical value, ifelse() is designed specifically to operate across whole vectors at once, though it evaluates both the yes and no arguments fully before selecting, so both branches must be valid expressions.
Cricket analogy: Scoring an entire innings' worth of deliveries at once, ifelse(runs >= 4, 'boundary', 'running shot') labels every ball in the over as a boundary or a running shot in one vectorized pass, rather than checking each delivery in a loop.
scores <- c(95, 82, 67, 74, 59)
grades <- ifelse(scores >= 90, "A",
ifelse(scores >= 80, "B",
ifelse(scores >= 70, "C", "F")))
grades
# [1] "A" "B" "F" "C" "F"switch() for Multi-Branch Logic
The switch() function selects one branch based on matching a character string (or an integer position) against a set of named alternatives, offering a cleaner alternative to a long else-if chain when you're testing one variable against several discrete values. Leaving a case's right-hand side empty makes it fall through to the next non-empty case, and including an unnamed final argument provides a default result when none of the named cases match.
Cricket analogy: A commentator's phrase generator uses switch(dismissal_type, 'bowled' = 'clean bowled!', 'caught' = 'well taken!', 'lbw' = 'trapped in front!', 'dismissed'), picking the right call from a fixed set of dismissal categories instead of chained if checks.
R evaluates if() and while() conditions lazily but expects a single logical value; using && and || (not & and |) inside if() conditions ensures only one comparison is made, which also short-circuits and avoids unnecessary evaluation of the second operand.
As of R 4.2.0, calling if() or while() with a condition vector of length greater than one throws a hard error instead of the older warning-then-first-element behavior — code that relied on silently using only the first element of a longer vector will now fail, so always confirm your condition is length one, e.g. with any()/all() when reducing a vector to one logical value.
- if evaluates a single TRUE/FALSE condition and runs the following block only when it is TRUE.
- else if chains test additional mutually exclusive conditions in order; only the first matching branch executes.
- ifelse() is vectorized and returns a value for every element of a logical vector in one call.
- switch() matches a string or integer against named cases and supports fall-through with empty cases.
- Since R 4.2.0, if() and while() require a length-one condition or they throw an error.
- Use && and || inside if() conditions instead of & and | to guarantee a single scalar result.
- Prefer vectorized functions like ifelse() over explicit loops when recoding whole columns in a data frame.
Practice what you learned
1. What happens in R 4.2.0+ if you pass a logical vector of length 3 directly to if()?
2. Which function is best suited to recode an entire numeric column in a data frame into 'high'/'low' labels without writing a loop?
3. In switch(x, 'a' = , 'b' = 'found_ab', 'other'), what does switch('a', ...) return?
4. Why should you prefer && over & inside an if() condition?
5. What does an else if chain guarantee about which block executes?
Was this page helpful?
You May Also Like
Loops in R
How R's for, while, and repeat loops work, including break/next control flow and the classic vector-preallocation performance fix.
Vectorized Operations in R
How R applies operations across entire vectors at once, including the recycling rule, logical indexing, and why vectorized code outperforms loops.
Functions in R
How R functions are defined, scoped, and evaluated — covering default arguments, lexical scoping, return values, and the ... variadic argument.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics