When starting to use R
, most people use loops whenever they need to iterate over elements of a vector
, list
or data.frame
. While it is natural to do this in other languages, with R
we generally want to use vectorization. That said, sometimes loops are unavoidable, so R
offers both for
and while
loops.
The most commonly used loop is the for
loop. It iterates over an index—provided as a vector
—and performs some operations. For a first simple example, we print out the first ten numbers.
The loop is declared using for
, which takes one English-seeming argument in three parts. The third part is any vector
of values of any kind, most commonly numeric
or character
. The first part is the variable that is iteratively assigned the values in the vector
from the third part. The middle part is simply the word in
indicating that the variable (the first part) is in the vector
(the third part).
> 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
Here we generated a vector
holding the numbers 1 through 10, and then printed each. Notice that this could have been performed simply by using the built-in vectorization of the print
function.
> print(1:10)
[1] 1 2 3 4 5 6 7 8 9 10
Sure, it does not look exactly the same, but that is just cosmetic.
The vector
in for
loops does not have to be sequential; it can be any vector
.
> # build a vector holding fruit names
> fruit <- c("apple", "banana", "pomegranate")
> # make a variable to hold their lengths, with all NA to start
> fruitLength <- rep(NA, length(fruit))
> # show it, all NAs
> fruitLength
[1] NA NA NA
> # give it names
> names(fruitLength) <- fruit
> # show it again, still NAs
> fruitLength
apple banana pomegranate
NA NA NA
> # loop through the fruit assigning their lengths to the result vector
> for (a in fruit)
+ {
+ fruitLength[a] <- nchar(a)
+ }
> # show the lengths
> fruitLength
apple banana pomegranate
5 6 11
Again, R
’s built-in vectorization could have made all of this much easier.
> # simply call nchar
> fruitLength2 <- nchar(fruit)
> # give it names
> names(fruitLength2) <- fruit
> # show it
> fruitLength2
apple banana pomegranate
5 6 11
This, as expected, provides identical results, as seen next.
> identical(fruitLength, fruitLength2)
[1] TRUE
Although used far less frequently in R
than the for
loop, the while
loop is just as simple to implement. It simply runs the code inside the braces repeatedly as long as the tested condition proves true. In the following example, we print the value of x
and iterate it until it reaches 5. This is a highly trivial example but shows the functionality nonetheless.
> x <- 1
> while (x <= 5)
+ {
+ print(x)
+ x <- x + 1
+ }
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
Sometimes we have to skip to the next iteration of the loop or completely break out of it. This is accomplished with next
and break
. We use a for
loop to demonstrate.
> for (i in 1:10)
+ {
+ if (i == 3)
+ {
+ next
+ }
+ print(i)
+ }
[1] 1
[1] 2
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
Notice that the number 3 did not get printed.
> for (i in 1:10)
+ {
+ if (i == 4)
+ {
+ break
+ }
+ print(i)
+ }
[1] 1
[1] 2
[1] 3
Here, even though we told R
to iterate over the first ten integers, it stopped after 3 because we broke the loop at 4.
The two primary loops are for
, which iterates over a fixed sequence of elements, and while
, which continues a loop as long as some condition holds true. As stated earlier, if a solution can be done without loops, via vectorization or matrix algebra, then avoid the loop. It is particularly important to avoid nested loops. Loops inside other loops are extremely slow in R
.