Introduction to R: Loops
Loops are one of the most useful things you can do in programming, because they allow you to apply a function many times. The simplest type of loop is a ‘for’ loop. For loops have the structure ‘for (var in seq)’, by which is meant that a variable ‘var’ is assigned values ‘in’ a sequence defined by ‘seq’.
for (i in seq(0, 1, by = 0.1)) {
# the open bracket says that this for loop will contain multiply lines of
# code
print(i) # print the value of i to the screen
}
## [1] 0
## [1] 0.1
## [1] 0.2
## [1] 0.3
## [1] 0.4
## [1] 0.5
## [1] 0.6
## [1] 0.7
## [1] 0.8
## [1] 0.9
## [1] 1
You can see that all this loop did was assign the variable ‘i’ to values in the sequence for 0 to 1 in steps of 0.1, and then printed those values to the screen. Of course, you could also do something to manipulate the values of i.
for (i in seq(0, 1, by = 0.1)) {
j = i^2
print(j)
}
## [1] 0
## [1] 0.01
## [1] 0.04
## [1] 0.09
## [1] 0.16
## [1] 0.25
## [1] 0.36
## [1] 0.49
## [1] 0.64
## [1] 0.81
## [1] 1
Or, if you had a vector of length 12, you could use a for loop to do something to each entry in that vector. For example, you could add two to every entry in the vector ‘a’ and store it in a new vector, ‘b’.
a = c(1, 5, 3, 19, -4, 3, 6)
b = vector(mode = "numeric", length = length(a)) # create an empty vector of the same length as a
for (i in seq(1, length(a))) {
# for i taking on values from 1 to the length of the vector a
b[i] = a[i] + 2 # set the i_th entry of b equal to the i_th entry of a, plus 2
}
b
## [1] 3 7 5 21 -2 5 8
Of course, we could have gotten the same answer simply by adding 2 to ‘a’ directly, but you can do more interesting things with loops. For example, imagine that, instead of adding 2 to each entry in the vector, you want to add the value of the previous entry in the vector. This operation is not defined for the very first entry in the vector, so we will start our ‘for’ loop with the second entry.
b = vector(mode = "numeric", length = length(a))
# set the first entry in the b vector equal to the first entry in the a
# vector
b[1] = a[1]
for (i in seq(2, length(a))) {
b[i] = a[i] + a[i - 1] # add the current entry in a to the previous entry in a
}
b
## [1] 1 6 8 22 15 -1 9
You can also call other functions from inside of a loop. In this example, we have a matrix ‘m’ that has 5 columns and 5000 rows. You want to compute the mean of each column and store it in a new vector. That is, compute the average of the 5000 entries occurring in the first column, and save them in the first entry of our new vector, then repeat for the second through fifth columns.
## [1] 5000 5
## [,1] [,2] [,3] [,4] [,5]
## [1,] -1.3808 0.4451 0.05009 0.2910 -0.15576
## [2,] -0.7447 1.7207 -0.90276 -2.0080 0.09732
## [3,] 0.1212 1.6068 0.74943 0.4079 1.46409
## [4,] 0.2638 0.1401 0.43251 -1.1857 -1.91818
## [5,] 0.9043 -0.3684 -2.03799 -0.1699 1.34214
## [6,] -0.3600 0.9713 0.14078 0.5253 -0.07988
## [1] 0.019105 0.017532 0.012273 -0.007506 0.021627
Of course, the mean is almost equal to 0, as it should be, since all of the values stored in ‘m’ were drawn from the normal distribution with mean equal to 0. What if we also wanted to store the standard deviation of the values in each column? Instead of creating a vector to store our results, we could create a matrix with two rows, and store means in the first row and standard deviations in the second row.
## [,1] [,2] [,3] [,4] [,5]
## [1,] -0.006162 -0.0125 0.01042 -0.008228 0.02606
## [2,] 0.994284 1.0041 1.00016 1.010257 0.99837
Another common loop structure is a ‘while’ loop. ‘while’ loops execute the loop code as long as some condition is not met. For example,
i = 1.01 # set the value of the variable i
while (i < 6) {
# as long as the value of i is less than 6, execute the code here
print(i)
i = i^2 # change the value of i by squaring it
}
## [1] 1.01
## [1] 1.02
## [1] 1.041
## [1] 1.083
## [1] 1.173
## [1] 1.375
## [1] 1.89
## [1] 3.574
i
## [1] 12.77
Of course, this was a pretty trivial example. You could imagine something more complicated, for example, applying Newton’s method to find the 0 of a complicated function. Newton’s method says that if you are trying to find the value of \(x\) such that the function \(f(x) = 0\), and you have an initial guess of \(x_0\), a better guess is \[ x_1 = x_0 - \frac{f(x_0)}{f'(x_0)},\] where \(f'(x_0)\) is the derivative of \(f(x)\) with respect to \(x\), evaluated at \(x_0\). If the function \(f(x)\) is complicated enough, it can be essentially impossible to find the actual value of \(x\) that causes \(f(x) = 0\), so you want to the method when the the value of \(f(x_0)\) is sufficiently small.
# compute the value of the function at any x
f = function(x) return(-x^10 + 8 * x^8 + 4 * x^6 - 3 * x^5 + 7 * x^3 + x^2 -
pi) # f(x)
# compute the derivative f'(x) at any x
df = function(x) return(-10 * x^9 + 64 * x^7 + 24 * x^5 - 15 * x^4 + 21 * x^2 +
2 * x) # f'(x)
# initial guess for x
x = 2
# while the absolute value of f(x) is greater than 1e-9 (0.000000001), keep
# performing Newton's method
while (abs(f(x)) > 1e-09) {
# use newton's method to change the value of x
x = x - f(x)/df(x)
print(f(x)) # print the value of f(x)
}
## [1] 385.3
## [1] 128.5
## [1] 43.75
## [1] 14.88
## [1] 4.776
## [1] 1.22
## [1] 0.158
## [1] 0.003692
## [1] 2.136e-06
## [1] 7.168e-13
In general, you will probably have less occasion to use ‘while’ loops than ‘for’ loops, but both can be very helpful.