8.1 The for Loop
The most important is the for loop, which executes a series of commands for each element of an object such as a vector or a list. The basic synthax of the for loop is for(i in obj){ ... }, where the code ... gets executed for each element in the object obj. In each iteration of the loop, the current element of obj is available through the specified variable, in this case i. Note that the name of the variable can be freely chosen.
> for(x in 1:4){ print(x) }
[1] 1
[1] 2
[1] 3
[1] 4
> b <- c("one","two","three")
> for(j in b){ print(j) }
[1] "one"
[1] "two"
[1] "three"In most cases, it is more helpful to loop over an object using indexes. This is commonly done by creating a vector of indexes over which the loop runs.
> g <- paste("Number", 1:3)
> for(i in 1:5){
+ print(g[i])
+ }
[1] "Number 1"
[1] "Number 2"
[1] "Number 3"
[1] NA
[1] NAIt is usually advisable to not specify the length of the indexes explicitly, but to use length() (vectors and lists) dim(), nrow() or ncol (matrices and data frames) to obtain the appropriate length. This makes the code easier to maintain as the for loop always runs across the entire vector, regardless of its length.
> d <- data.frame(a=1:4, b=seq(0, 1, length.out=4))
> for(i in 1:dim(d)[1]){
+ print(d[i,])
+ }
a b
1 1 0
a b
2 2 0.3333333
a b
3 3 0.6666667
a b
4 4 1A neat shortcut to writing 1:length(x) is provided by the function seq_along().
Indexes is the preferred way to loop over vectors if an object is modified during the loop and / or if multiple objects are accessed. Here is an example:
The above loop accesses vectors x and y during the loop and modifies vector x. Such a loop can not be written (efficiently) by looping over the elements of one vector.
The code inside a for loop can be arbitrarily complex, including other for loops or conditionals.
> for(i in 1:3){
+ for(j in i:4){
+ if(i %% 2 == 0){
+ print(paste(i, "+", j, "=", i+j))
+ } else {
+ print(paste(i, "*", j, "=", i*j))
+ }
+ }
+ }
[1] "1 * 1 = 1"
[1] "1 * 2 = 2"
[1] "1 * 3 = 3"
[1] "1 * 4 = 4"
[1] "2 + 2 = 4"
[1] "2 + 3 = 5"
[1] "2 + 4 = 6"
[1] "3 * 3 = 9"
[1] "3 * 4 = 12"Nesting for loops is particularly useful when looping over two-dimensional objects such as matrices.
> a <- matrix(c(1,2,3, 11,12,13), nrow = 2, ncol = 3, byrow = TRUE)
> for(i in 1:nrow(a)){
+ for(j in 1:ncol(a)){
+ print(paste("The element in the row",i, "and in the column", j, "is:", a[i,j]))
+ }
+ }
[1] "The element in the row 1 and in the column 1 is: 1"
[1] "The element in the row 1 and in the column 2 is: 2"
[1] "The element in the row 1 and in the column 3 is: 3"
[1] "The element in the row 2 and in the column 1 is: 11"
[1] "The element in the row 2 and in the column 2 is: 12"
[1] "The element in the row 2 and in the column 3 is: 13"Finally, for loops can be stopped using the command break such as:
> x <- 1:10
> for(i in 1:length(x)){
+ print(x[i])
+ if(x[i] > 3){
+ break
+ }
+ }
[1] 1
[1] 2
[1] 3
[1] 48.1.1 Exercises: For loops
See Section 18.0.19 for solutions.
Use a
forloop to test where a vector of arbitrary length is strictly increasing. If it is not, it should print “Vector is not strictly increasing!”.Use two
forloops to create a vector containing the elements 1, 2, 2, 3, 3, 3, …Create a matrix with 3 rows containgin the numbers 1, 2, …, 120. Loop over each column, calculate the sum of the values inside this column and store them in a new vector.
Use a loop to create the first 100 elements of the (https://en.wikipedia.org/wiki/Fibonacci_number)[Fibonacci sequence] 0, 1, 1, 2, 3, 5, …. The Fibonacci sequence starts with 0 and 1, and each of the following elements \(F_n= F_{n-1} + F_{n-2}\).
Create two vectors \(\boldsymbol{x}\) and \(\boldsymbol{y}\) containg both the numbers 1:100 in shuffled order. Then loop over these vectors and print the prodcut whenever \(x_i>y_i\) and the sum when \(x_i<y_i\).
Use nested loops to create the same matrix you get with
matrix(c(2,3,4,3,4,5,4,5,6), nrow = 3, ncol = 3, byrow = TRUE).