Control structures in R allow you to control the
flow of execution of the program,
depending on runtime conditions. Common structures are
if, else: testing a condition
for: execute a loop a fixed number of times
while: execute a loop while a condition is true
repeat: execute an infinite loop
break: break the execution of a loop
next: skip an iteration of a loop
return: exit a function
Most control structures are not used in interactive sessions, but rather when writing
functions or longer expresisons.
The
if(
do something
} else {
do something else
}
if(
do something
} else if(
do something different
} else {
do something different
}
This is a valid if/else structure.
If else function
x <- 3
if (x > 3) {
y <- 10
} else {
y <- 0
}
x
## [1] 3
y
## [1] 0
the else clause is not necessary.
if(
if(
}
5
if with no else statement
x <- 5
if (x < 4) {
5
}
if (x > 4) {
6
}
## [1] 6
for (i in 1:10) {
print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
These three loops have the same behavior.
x <- c(“a”, “b”, “c”, “d”)
for(i in 1:4) {
print(x[i])
}
for(i in seq_along(x)) {
print(x[i])
}
for(letter in x) {
print(letter)
}
for(i in 1:4) print(x[i])
7
x <- c("a", "b", "c", "d")
for (i in 1:4) {
print(x[i])
}
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"
for (i in seq_along(x)) {
print(x[i])
}
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"
Be careful with nesting
Nesting beyond 2 or 3 levels is often very difficult to
read/understand.
x <- matrix(1:6, 2, 3)
for (i in seq_len(nrow(x))) {
for (j in seq_len(ncol(x))) {
print(x[i, j])
}
}
## [1] 1
## [1] 3
## [1] 5
## [1] 2
## [1] 4
## [1] 6
While loops begin by testing a condition. If it is true, then they execute the loop body.
Once the loop body is executed, the condition is tested again, and so forth.
While loops can potentially result in infinite loops if not written properly. Use with
care!
count <- 0
while (count < 10) {
print(count)
count <- count + 1
}
## [1] 0
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
Sometimes there will be more than one condition in the test.
Conditions are always evaluated from left to right.
z <- 5
while (z >= 3 && z <= 10) {
print(z)
coin <- rbinom(1, 1, 0.5)
if (coin == 1) {
## random walk
z <- z + 1
} else {
z <- z - 1
}
}
## [1] 5
## [1] 4
## [1] 5
## [1] 4
## [1] 5
## [1] 6
## [1] 5
## [1] 4
## [1] 5
## [1] 6
## [1] 5
## [1] 4
## [1] 5
## [1] 4
## [1] 3
## [1] 4
## [1] 3
Repeat initiates an infinite loop; these are not commonly used in statistical applications
but they do have their uses. The only way to exit a repeat loop is to call break.
x0 <- 1
tol <- 1e-8
repeat {
x1 <- computeEstimate()
if(abs(x1 - x0) < tol) {
break
} else {
x0 <- x1
}
}
The loop in the previous slide is a bit dangerous because there's no guarantee it will
stop. Better to set a hard limit on the number of iterations (e.g. using a for loop) and
then report whether convergence was achieved or not.
next is used to skip an iteration of a loop
for (i in 1:10) {
if (i <= 5) {
print(i)
y <- i^2
print(y)
next
}
y <- i^3
print(i)
print(y)
}
## [1] 1
## [1] 1
## [1] 2
## [1] 4
## [1] 3
## [1] 9
## [1] 4
## [1] 16
## [1] 5
## [1] 25
## [1] 6
## [1] 216
## [1] 7
## [1] 343
## [1] 8
## [1] 512
## [1] 9
## [1] 729
## [1] 10
## [1] 1000
Control structures like if, while, and for allow you to control the
flow of an R program.
Infinite loops should generally be avoided, even if they are theoretically correct.
Control structures mentiond here are primarily useful for writing programs; for
command-line interactive work, the *apply functions are more useful.