Iteration

Computers: good at applying rigid rules over and over again. Humans: not so good at this. Iteration is at the heart of programming

Summary of methods for performing iteration in R:

Reminder: conditionals and boolean operators

Control flow:

Boolean operators:

In summary, use && and || for conditionals, & and | for indexing or subsetting

Examples of boolean operators

set.seed(0)
x = runif(10, -1, 1)
x
##  [1]  0.7933944 -0.4689827 -0.2557522  0.1457067  0.8164156 -0.5966361
##  [7]  0.7967794  0.8893505  0.3215956  0.2582281
x[0 <= x & x <= 0.5] = 999 # Elementwise AND
x
##  [1]   0.7933944  -0.4689827  -0.2557522 999.0000000   0.8164156
##  [6]  -0.5966361   0.7967794   0.8893505 999.0000000 999.0000000
(0 > 0) && all(matrix(0,2,2) == matrix(0,3,3)) # Lazy AND
## [1] FALSE
(0 > 0) && (ThisVariableIsNotDefined == 0) # Lazy AND
## [1] FALSE

In the last two lines, R never evaluates the expression on the right (each of these would throw an error on its own!)

for() loop

A for() loop increments a counter variable along a vector. It repeatedly runs a code block, called the body of the loop, with the counter set at its current value, until it runs through the vector

n = 10
log.vec = vector(length=n, mode="numeric")
for (i in 1:n) {
  log.vec[i] = log(i)
}
log.vec
##  [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101
##  [8] 2.0794415 2.1972246 2.3025851

Here i is the counter and the vector we are iterating over is 1:n. The body is the code in between the braces

Breaking from the loop

We can break out of a for() loop early (before the counter has been iterated over the whole vector), using break

n = 10
log.vec = vector(length=n, mode="numeric")
for (i in 1:n) {
  if (log(i) > 2) {
    cat("I'm outta here. I don't like numbers bigger than 2\n")
    break
  }
  log.vec[i] = log(i)
}
## I'm outta here. I don't like numbers bigger than 2
log.vec
##  [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101
##  [8] 0.0000000 0.0000000 0.0000000

Variations on standard for() loops

Many different variations on standard for() are possible. Two common ones to be aware of:

for (str in c("Prof", "Ryan", "Tibs")) {
  cat(paste(str, "declined to comment\n"))
}
## Prof declined to comment
## Ryan declined to comment
## Tibs declined to comment
for (i in 1:4) {
  for (j in 1:i^2) {
    cat(paste(j,""))
  }
  cat("\n")
}
## 1 
## 1 2 3 4 
## 1 2 3 4 5 6 7 8 9 
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

while() loop: conditional iteration

A while() loop repeatedly runs a code block, called the body, until some condition is no longer TRUE

i = 1
log.vec = c()
while (log(i) <= 2) {
  log.vec = c(log.vec, log(i))
  i = i+1
}
log.vec
## [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101

for() versus while()

while(TRUE) or repeat: unconditional iteration

while(TRUE) and repeat: both have the same function, just repeat the body indefinitely, until something causes the flow to break

Try running the code below in your console

repeat {
  ans = readline("Who is the best Professor of Statistics at CMU? ")
  if (ans == "Tibs" || ans == "Tibshirani" || ans == "Ryan") {
    cat("Yes! You get an 'A'.")
    break
  }
  else {
    cat("Wrong answer!\n")
  } 
}

Avoiding explicit iteration

Warning: some people have a tendency to overuse for() and while() loops in R. They aren’t always needed. Useful alternatives: