Applying R to Lifestyle and Brain Health Research
University of Kansas Medical Center
September 2, 2026
Control flow just refers to the order in which the code is executed.
The primary tools for controlling flow are choices and loops. Choices allow you to run different code depending on the input (e.g., if statements and switch). Loops allow you to repeatedly run code with changing options (e.g., for and while loops).
A basic if statement will evaluate if some expression is true or false and then execute a specific task if the expression is true.
To enhance the if statement, you can add an else condition. This means that the true_action is evaluated if the condition is TRUE and the false_action is evaluated if the condition is FALSE.
Using else if allows you to make a chain of statements where each input is evaluated through this chain of statements. This means that you are giving a list of conditions and seeing which matches your input. The actions are often compound statements contained within { and returns a value so you can assign the results.
The choices we just talked about do not work with vectors with multiple values, only single inputs at one time. So what if you want to evaluate a vector with multiple inputs?
Below is an example of ifelse() where all the numbers in the sequence 1 through 12 are being checked to see if they are divisible by 5. If they are, it will print “XXX”, otherwise it will just print the value as a character.
And here is an example of case_when() where you are evaluating multiple inputs for multiple conditions.
| You want to evaluate… | Type of Statement to use |
|---|---|
| One condition, one value | if / else |
| Multiple conditions, one value | if / elseif / else |
| One condition, multiple values | ifelse() (vectorized) |
| Multiple conditions, multiple values | case_when() |
The switch() function in R is a more compact alternative to writing long chains of if, else if, and else conditions when you are comparing a single input to several known options.
Instead of checking conditions one by one, switch() directly matches the input to a predefined list of values and returns the associated result. Compare this example using else if:
With this example using switch
With switch statements, if multiple inputs have the same value, you can leave it blank after the = and the input will fall through to the next value.
Loops are used when you want to repeat a block of code on multiple inputs and have the following basic form: for (item in vector) perform_action
for (i in 1:3) {
print(i)
}
#> [1] 1
#> [1] 2
#> [1] 3
weights <- c(60, 72, 85, 90)
height <- 1.7
for (w in weights) {
bmi <- w / height^2
print(paste("Weight:", w, "kg -> BMI:", round(bmi, 1)))
}
#>[1] "Weight: 60 kg -> BMI: 20.8"
#>[1] "Weight: 72 kg -> BMI: 24.9"
#>[1] "Weight: 85 kg -> BMI: 29.4"
#>[1] "Weight: 90 kg -> BMI: 31.1"There are two ways to terminate a for loop early:
next exits the current iteration.break exits the entire for loop.This can be especially useful in large data sets
There are three common pitfalls to watch out for when using for.
Make sure to pre-allocate the output container. Otherwise the loop will be very slow. This would be like you decide to put books on a bookshelf at home, but every time you get a new book, you have to go out to the store and buy a new bookshelf that is exactly 1 book larger than your last one.
timer <- function(prealloc, label) {
set.seed(123)
daily_avg_steps <- sample(x = 3000:12000, size = 1000000, replace = TRUE)
tictoc::tic(label)
for (i in seq_along(daily_avg_steps)) {
prealloc[[i]] <- rpois(7, lambda = daily_avg_steps[i])
}
tictoc::toc()
}
timer(prealloc = list(), label = "Without preallocation")
# Without preallocation: 1.12 sec elapsed
timer(
prealloc = vector("list", length(daily_avg_steps)),
label = "With preallocation"
)
# With preallocation: 0.77 sec elapsedAttempting to iterate over 1:length(x) will fail in unexpected ways if x has a length of 0. If x is 0, then this is read as 1:0 which is a two element vector [1,0].
Dates are an example of an S3 class and in R, dates get stored as days since Jan 1 1970. So if you want to run a loop, you need to preserve the class attribute with seq_along() and double brackets [[]]
For loops are useful if you know in advance the set of values that you want to iterate over. If you don’t know, there are two related tools with more flexible specifications:
while(condition) action: performs action while condition is TRUE.
repeat(action): repeats action forever (i.e. until it encounters break).
bpcut <- 120
bpsys <- 126
while (bpsys > bpcut) {
print("Your systolic blood pressure is elevated")
bpsys <- bpsys - 1
}
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
bpcut <- 120
bpsys <- 126
repeat {
if (bpsys <= bpcut) {
break
}
print("Your systolic blood pressure is elevated")
bpsys <- bpsys - 1
}
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
# [1] "Your systolic blood pressure is elevated"
step_goal <- 10000
current_steps <- 6500
repeat {
if (current_steps >= step_goal) {
print("Congrats! You've reached your daily step goal.")
break
}
print(paste(
"You have",
step_goal - current_steps,
"steps to go. Keep moving!"
))
steps_taken <- sample(500:1500, 1)
current_steps <- current_steps + steps_taken
Sys.sleep(1)
}
# {1] "You have 3500 steps to go. Keep moving!"
# [1] "You have 2901 steps to go. Keep moving!"
# [1] "You have 2131 steps to go. Keep moving!"
# [1] "You have 792 steps to go. Keep moving!"
# [1] "Congrats! You've reached your daily step goal."R for Lifestyle and Brain Health (R-LAB)