See the Work Along - Loops, etc. for in-class exercises.
One of the most fundamental features of a programming language like C is the for
loop, which permits iteration of a process over some index set. Iteration in R is a more complex issue for reasons i’ll explain, but it does contain the basic functions for loops and flow control.
As a first example, compute the 12th Fibonnaci number, defined recursively by
\[F_n = F_{n-1} + F_{n-2}, \quad F_0 = 1,\; F_1 = 1\]
We’ll store the numbers in a numeric vector:
fib <- numeric(13)
fib[1] <- 1
fib[2] <- 1
Now fill out the next values, up to the index 13.
for(j in 3:13) {
fib[j] <- fib[j-1] + fib[j-2]
}
fib
## [1] 1 1 2 3 5 8 13 21 34 55 89 144 233
Everything in R is a function but it’s best to think of the for loop as a container for a sequence of commands.
Usually, you iterate over a sequence of integers, but you can also use other vectors.
double_letters <- character()
for(x in c("a", "b", "c")) {
double_letters <- c(double_letters, paste(x,x))
}
double_letters
## [1] "a a" "b b" "c c"
For a numeric sequence v, compute a new sequence in which the \(j^{th}\) entry is the sin
of v[j].
Here is the for
loop method.
set.seed(666)
v <- rnorm(25)
w <- numeric(length(v))
for(j in 1:25) {
w[j] <- sin(v[j])
}
w
## [1] 0.68406 0.90323 -0.34772 0.89722 -0.79845 0.68776 -0.96519
## [8] -0.71911 -0.97558 -0.04202 0.83688 -0.98018 0.76087 -0.98887
## [15] 0.13372 -0.07575 0.75673 0.33810 -0.55007 0.70765 -0.63815
## [22] -0.92576 0.95476 -0.30749 0.03057
However, we know that R vectorizes operations; i.e., it automatically iterates numeric functions over numeric vectors, entry by entry.
z <- sin(v)
z
## [1] 0.68406 0.90323 -0.34772 0.89722 -0.79845 0.68776 -0.96519
## [8] -0.71911 -0.97558 -0.04202 0.83688 -0.98018 0.76087 -0.98887
## [15] 0.13372 -0.07575 0.75673 0.33810 -0.55007 0.70765 -0.63815
## [22] -0.92576 0.95476 -0.30749 0.03057
Value of vectorization:
* simplicity of programming,
* speed
set.seed(555)
v2 <- rnorm(10000000)
Compute the exponential of each entry.
w2 <- numeric(10000000)
system.time(
for(j in 1:10000000) {
w2[j] <- exp(v2[j])
}
)
## user system elapsed
## 18.781 0.043 18.825
Try the vectorized method.
system.time(z2 <- exp(v2))
## user system elapsed
## 0.080 0.000 0.081
The speed-up due to vectorization is dramatic. This is because vectorization codes the iteration step in C. This is the real advantage of vectorization.
Later, we’ll discuss methods of iterating operations over lists and rows or columns of matrices and data.frames. These are extremely useful in working with large datasets.
R has a while
function as well as a for
function. This allows iterations of flexible length.
while(expression) { code block}
should be read as
while the expression is true, iteratively execute the code block and re-evaluate the expression based on the result.
The syntax of the if
function in R is
if(expression) { code block}
which is executed as “if the expression is TRUE, execute the code block, otherwise skip it”.
This is handy when the code block can only be executed when some condition holds.
There is also an if
else
combination.
if(expression) { code block}
else {other code block}