Chapter 4 Loops in R
Loops are typically used when we want to repeat some type of calculation many times.
The two types of loops in R are the for loop and the while loop.
For loops:
- Typically used when we know exactly how many times we need to repeat a calculation.
While loops:
- Typically used when we only want to repeat some calculation until some condition is satisfied.
4.1 For Loops
- The general form of a for loop in R is
The for loop will execute the code underneath the for statement \(T\) times where \(T\) is the length of the vector
vec_name
.Each time the code is executed,
x
will be set to one element invec_name
.
4.1.1 Example 1: printing the first 5 integers
- As an example, let’s write a for loop that prints the first 5 positive integers:
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
- Each time you go inside the loop, the variable
k
takes the next value in the vector1:5
and is printed to the screen.
4.1.2 Example 2: computing 10 factorial
- As another example, let’s use a for loop to compute the product \[\begin{equation} 10! = 1 \times 2 \times 3 \times ... \times 9 \times 10 \nonumber \end{equation}\]
prod_ten <- 1 # start from 1
for(x in 2:10) { # iterate x from 1 thru 10
prod_ten <- prod_ten*x # multiply each value
}
print(prod_ten) # print the product of first 10 integers
## [1] 3628800
4.1.3 Example 3: a non-numeric looping variable
The looping variable does not need to be numeric.
Here is an example where the looping variable has character type.
fruits <- c("apple","orange","grape") # character vector
for(fruit in fruits) { # iterate each element
print(fruit)
}
## [1] "apple"
## [1] "orange"
## [1] "grape"
4.1.4 Example 4: first Fibonacci numbers
The Fibonacci sequence is a sequence of numbers \(x_{1}, x_{2}, x_{3}, ...\) defined by the relationship: \[\begin{equation} x_{k} = x_{k-1} + x_{k-2} \nonumber \end{equation}\]
The first two numbers in the Fibonacci sequence are \(x_{1} = 0\) and \(x_{2} = 1\).
We want to write R code that stores the first \(n\) Fibonacci numbers in a vector.
To do this, it is more efficient to first create a vector of zeros and then fill in the Fibonacci numbers into this vector.
- This is done by first assigning
x
the vectorrep(0, n)
- This is done by first assigning
## R code for computing first 12 Fibonacci numbers
x <- rep(0, 12) # First initialize a vector of size 12
x[1] <- 0
x[2] <- 1
for(k in 3:12) {
## start at index 3 since first 2 elements are filled in
x[k] <- x[k-1] + x[k-2]
}
x
## [1] 0 1 1 2 3 5 8 13 21 34 55 89
You could create a vector of the first \(n\) Fibonacci numbers by “appending” an extra number to the vector x each time we go in the loop.
This is usually much slower than first initializing a vector as was done on the previous slide.
## R code for computing first 12 Fibonacci numbers
x <- c(0, 1)
for(k in 3:12) {
x <- c(x, x[k-1] + x[k-2])
}
x
## [1] 0 1 1 2 3 5 8 13 21 34 55 89
4.1.5 Nested for loops
- You can have a for loop within another for loop.
- These are usually referred to as nested for loops.
for (i in 1:3) { # i iterates over 1,2,3
for (j in 1:i) { # j iterates over 1 to i
print(c(i,j))
}
}
## [1] 1 1
## [1] 2 1
## [1] 2 2
## [1] 3 1
## [1] 3 2
## [1] 3 3
4.1.6 break and next: Exiting for loops and skipping iterations
- You can use the break statement to terminate a loop.
- The for loop will be stopped whenever the statement break is encountered.
- As an example of this, let’s write a loop that should run for 5 iterations, but is terminated after during it’s 3rd iteration.
## [1] 1
## [1] 2
## [1] 3
- Note that if we move the
print
statement afterbreak
in the above example, then only1
and2
will be printed to the screen.
## [1] 1
## [1] 2
break statements can be used within nested loops.
If using a break statement in the inner loop of a nested loop, only the inner loop will be terminated when break is run.
for (i in 1:3) { # i iterates over 1,2,3
for (j in 1:3) { # j iterates over 1,2,3
print(c(i,j))
if (j == i) { ## if j and i are the same
break ## finish the inner loop
}
}
}
## [1] 1 1
## [1] 2 1
## [1] 2 2
## [1] 3 1
## [1] 3 2
## [1] 3 3
The next statement is used to skip the remainder of a current iteration.
When the next statement is encountered, you will go directly to the next iteration and not execute whatever was remaining inside the body of the for loop.
Let’s try an example where we have 5 iterations setup, but we use a next statement within the 3rd iteration
## [1] 1
## [1] 2
## [1] 4
## [1] 5
next
can also be used within a nested loop.If used in an inner loop, the next statement will skip the remainder of the current inner loop iteration and go to the next inner loop iteration.
for (i in 1:3) { # i iterates over 1,2,3
for (j in 1:3) { # j iterates over 1,2,3
if (j == i) { ## if j equals i
next ## go to next iteration
} ## of inner loop
print(c(i,j))
}
}
## [1] 1 2
## [1] 1 3
## [1] 2 1
## [1] 2 3
## [1] 3 1
## [1] 3 2
4.2 While Loops
For loops execute a piece of code a set number of times.
While loops keep executing the piece of code as long as a certain condition is
TRUE
.The general form of a while loop in R is
condition
is a logical expression.The
code_chunk
inside the loop is repeated until thecondition
becomesFALSE
in which case the loop stops.
- Basic example of while loop:
prod <- 1 # start from 1
while(prod < 100) { # repeat the block until condition is true
print(prod) # print the value of prod
prod <- prod * 2 # and double the value
}
## [1] 1
## [1] 2
## [1] 4
## [1] 8
## [1] 16
## [1] 32
## [1] 64
4.2.1 Example 1: a “first which” function
We can use a while loop to find the first occurrence of a number in a vector.
Specifically, for an input vector x and input number num, we want to find the first index
k
such thatx[k] == num
This function will also return
NA
if no match is found.
first_while <- function(x, num) {
index.count <- 0
match.not.found <- TRUE
while(match.not.found && index.count < length(x)) {
# want to keep loop running while match is not found
# and the index is less than the length of x
index.count <- index.count + 1
match.not.found <- !(x[index.count] == num)
}
if(match.not.found) {
index.count <- NA
}
return(index.count)
}
- Let’s try running
first_while
on a few examples:
## [1] 3
## [1] NA
## [1] 5
## [1] 5