Crash Courses · Masters
Control Flow & Functions
Write if/else, for and while loops in R, and build reusable functions with default arguments, return values, and proper documentation.
16 min read+170 XP on completionCert: R Crash Course
Tap any word in the text below to start reading from there.
Control Flow & Functions
if / else
# Scalar if (single TRUE/FALSE)
x <- 15
if (x > 10) {
cat("Greater than 10\n")
} else if (x == 10) {
cat("Equal to 10\n")
} else {
cat("Less than 10\n")
}
# Compact form (single expressions)
result <- if (x > 0) "positive" else "non-positive"
# ifelse() — vectorized (processes every element)
scores <- c(92, 78, 85, 61, 95)
grades <- ifelse(scores >= 90, "A",
ifelse(scores >= 80, "B",
ifelse(scores >= 70, "C", "F")))
print(grades) # "A" "C" "B" "F" "A"---
Loops
# for loop
fruits <- c("apple", "banana", "cherry")
for (fruit in fruits) {
cat(toupper(fruit), "\n")
}
# for with index
for (i in 1:5) {
cat(sprintf("Item %d: %.2f\n", i, i^2))
}
# while loop
n <- 1
while (n < 100) {
n <- n * 2
}
cat("First power of 2 >= 100:", n, "\n") # 128
# next (continue) and break
for (i in 1:10) {
if (i %% 2 == 0) next # skip even numbers
if (i > 7) break # stop when i > 7
cat(i, "")
}
# Output: 1 3 5 7Important: R loops are slow. Prefer vectorized operations for data processing — use loops only for truly sequential logic.
---
Functions
# Basic function
square <- function(x) {
x ^ 2 # implicit return — last expression is returned
}
square(5) # 25
square(1:5) # c(1, 4, 9, 16, 25) — vectorized automatically
# Default arguments
greet <- function(name, greeting = "Hello", punctuation = "!") {
paste0(greeting, ", ", name, punctuation)
}
greet("Jordan") # "Hello, Jordan!"
greet("Alice", greeting = "Hi") # "Hi, Alice!"
greet("Bob", punctuation = ".") # "Hello, Bob."
# Multiple return values (use a list or named vector)
stats_summary <- function(x) {
list(
mean = mean(x, na.rm = TRUE),
median = median(x, na.rm = TRUE),
sd = sd(x, na.rm = TRUE),
n = sum(!is.na(x))
)
}
result <- stats_summary(c(3, 7, NA, 2, 9, 1, 8))
cat("Mean:", result$mean, "\n")
cat("Median:", result$median, "\n")
cat("N (non-NA):", result$n, "\n")---
Input Validation and Error Handling
safe_divide <- function(a, b) {
if (!is.numeric(a) || !is.numeric(b)) {
stop("Both arguments must be numeric") # fatal error
}
if (b == 0) {
warning("Division by zero — returning Inf")
return(Inf)
}
a / b
}
# tryCatch for error handling
result <- tryCatch({
safe_divide(10, 0)
}, warning = function(w) {
message("Warning caught: ", conditionMessage(w))
NA # return NA on warning
}, error = function(e) {
message("Error: ", conditionMessage(e))
NA
})---
Functional Idioms: lapply, sapply, Map, Reduce
# lapply — apply function to list, returns list
nums <- list(a = 1:5, b = 6:10, c = 11:15)
lapply(nums, mean) # list(a=3, b=8, c=13)
# sapply — simplify result to vector/matrix
sapply(nums, mean) # named vector: a=3, b=8, c=13
sapply(nums, range) # 2×3 matrix
# vapply — safer sapply with expected type
vapply(nums, mean, FUN.VALUE = numeric(1)) # guaranteed numeric vector
# Map — apply function to multiple vectors simultaneously
x <- c(1, 2, 3)
y <- c(10, 20, 30)
Map(function(a, b) a + b, x, y) # list(11, 22, 33)
mapply(function(a, b) a + b, x, y) # simplified: c(11, 22, 33)
# Reduce — fold a vector with a function
Reduce("+", 1:5) # 15: ((((1+2)+3)+4)+5)
Reduce(max, c(3,1,4)) # 4
# Anonymous functions (R 4.1+: the \ shorthand)
sapply(1:5, \(x) x^2) # c(1, 4, 9, 16, 25)Reading progress
0% read
In this module
ifelse()
lapply / sapply
Function environment
return()
0%