Control Flow in R
Master conditionals, loops, and vectorized control flow in R with practical Docker-ready examples for statistical computing
Control flow determines the order in which your code executes and lets your programs make decisions and repeat work. R provides all the familiar building blocks—if/else conditionals, for and while loops, and a switch statement—but it approaches control flow from the perspective of a language built for statistical computing.
R is a multi-paradigm language (Array, Object-Oriented, Functional, Procedural, and Reflective) with dynamic, strong typing. Because R was designed to work with vectors and data frames, the most idiomatic “control flow” often isn’t a loop at all—it’s a vectorized operation that applies a decision to an entire vector at once. A subtle but important detail: in R, if is an expression that returns a value, so conditionals can be assigned directly to variables.
In this tutorial you’ll learn how to write conditionals with if/else if/else, make vectorized decisions with ifelse(), branch on values with switch(), iterate with for, while, and repeat loops, and control loop execution with break and next. Just as importantly, you’ll learn when to avoid explicit loops in favor of R’s vectorized approach.
Conditionals: if, else if, else
The if statement evaluates a condition and runs a block only when that condition is TRUE. You can chain conditions with else if and provide a fallback with else.
Create a file named conditionals.R:
| |
The condition inside if (...) must evaluate to a single logical value (TRUE or FALSE). Note the placement of else: it must appear on the same line as the closing brace } so R knows the statement continues. The final two lines show R’s distinctive feature—if returns a value, so the whole conditional can be assigned to status in one expression.
Vectorized Conditionals and switch
A plain if only handles a single value. When you need to apply a condition to an entire vector—a common situation in data analysis—use ifelse(), which evaluates the condition element by element and returns a vector. To branch on a single discrete value, switch() is cleaner than a long if/else if chain.
Create a file named vectorized_conditions.R:
| |
ifelse(test, yes, no) returns the yes value wherever test is TRUE and the no value wherever it’s FALSE, preserving the shape of the input vector—a single call replaces an entire loop. The switch() function matches its first argument against the named cases; an unnamed final argument acts as the default when nothing matches, which is why grade_label("Z") returns "Unknown".
Loops: for, while, and repeat
R offers three loop constructs. A for loop iterates over the elements of a vector (or any sequence), a while loop runs as long as a condition holds, and repeat loops forever until you explicitly break. Inside any loop, next skips to the next iteration and break exits the loop entirely.
Create a file named loops.R:
| |
The for loop walks through 1:5, the integer sequence from 1 to 5. The while loop decrements countdown until the condition becomes FALSE. The repeat block has no built-in stopping condition, so break is mandatory—here next skips the iteration where n is 3, and break ends the loop once n exceeds 5, giving a sum of 1 + 2 + 4 + 5 = 12.
The R Way: Vectorize Instead of Looping
Because R is fundamentally an array language, explicit loops are often slower and less readable than operating on whole vectors at once. Many tasks that would require a loop in other languages become a single expression in R. Reaching for vectorized operations first is the idiomatic approach.
Create a file named vectorize.R:
| |
numbers^2 squares all ten elements in one operation—no loop needed. The expression numbers[numbers %% 2 == 0] uses logical subsetting: numbers %% 2 == 0 produces a logical vector that selects only the even values. Functions like sum() collapse an entire vector into a single result, replacing the accumulator pattern you’d write with a loop. This vectorized style is both faster and closer to how R is meant to be used.
Running with Docker
Docker lets you run these examples in a consistent R 4.4.2 environment without installing R locally.
| |
Expected Output
Running conditionals.R:
[1] "It's mild"
[1] "Status: comfortable"
Running vectorized_conditions.R:
[1] "Pass" "Pass" "Pass" "Fail" "Pass"
[1] "Excellent"
[1] "Unknown"
Running loops.R:
Square of 1 is 1
Square of 2 is 4
Square of 3 is 9
Square of 4 is 16
Square of 5 is 25
Countdown: 3
Countdown: 2
Countdown: 1
Sum (excluding 3): 12
Running vectorize.R:
[1] "1 4 9 16 25 36 49 64 81 100"
[1] "Evens: 2 4 6 8 10"
[1] "Sum: 55"
Key Concepts
ifis an expression: Unlike many languages, R’sif/elsereturns a value, so you can assign a conditional directly to a variable (e.g.,status <- if (x > 0) "pos" else "neg").elseplacement matters: In scripts,elsemust sit on the same line as the closing}of the preceding block, or R treats theifas complete.- Use
ifelse()for vectors: A scalarifcannot test an entire vector.ifelse(test, yes, no)applies the condition element-wise and returns a vector of the same length. switch()for value-based branching: Cleaner than longif/else ifchains; the unnamed final argument provides a default case.- Three loop forms:
foriterates over a sequence,whileruns while a condition holds, andrepeatloops until an explicitbreak. breakandnext:breakexits a loop entirely;nextskips to the next iteration—essential for controllingrepeatand filtering iterations.- Prefer vectorization: Operating on whole vectors (
x^2,sum(x), logical subsetting likex[x > 0]) is faster and more idiomatic in R than writing explicit loops.
Comments
Loading comments...
Leave a Comment