It’s commonly believed that for loops in R are very slow, but this isn’t true – it’s actually that modifying data structures in a particular way using a loop can be slow.

A for loop that does nothing

This for loop does nothing, and is fast:

nums <- 1:1e7

time <- system.time({
  for (i in nums) {
    NULL
  }
})

Total time is 0.601 seconds, which is 1.6639 × 107 iterations per second.

Growing a vector in a loop

Growing a vector is much slower. First, we’ll try growing an empty vector to 10,000 elements.

nums <- 1:1e4
vec <- numeric()

time <- system.time({
  for (i in nums) {
    vec[i] <- 1
  }
})

Total time is 0.113 seconds, which is 8.8496 × 104 iterations per second.

Now we’ll try growing a vector to 100,000 elements.

nums <- 1:1e5
vec <- numeric()

time <- system.time({
  for (i in nums) {
    vec[i] <- 1
  }
})

Total time is 11.135 seconds, which is 8981 iterations per second.

The time per iteration grows with the length of the vector: this vector is 10x larger than the previous one, but it took about 100x as long to create.

Modifying each element of a vector in a loop

Modifying the elements of a vector without changing its size is much faster than growing the vector:

# This uses the existing vec from previous
time <- system.time({
  for (i in nums) {
    vec[i] <- 2
  }
})

Total time is 0.096 seconds, which is 1.0417 × 106 iterations per second.