14.5 Functionals vs. Loops

The higher-order functions we have studied in this chapter are often called functionals. As we pointed out earlier, they deliver results that could have been produced by a writing a loop of some sort.

Once you get used to functionals, you will find that they are often more “expressive” than loops—easier for others to read and to understand, and less prone to bugs. Also, many of them are optimized by the developers of R to run a bit faster than an ordinary loop written in R.

For example, consider the following list. It consists of ten thousand vectors, each of which contains 100 randomly-generated numbers.

lst <- map(rep(100, 10000), runif)

If we want the mean of each vector, we could write a loop:

means <- numeric(10000)
for ( i in 1:10000 ) {
  means[i] <- mean(lst[[i]])
}

Or we could use map_dbl():

means <- map_dbl(lst, mean)

Comparing the two using system.time() , on my machine I got:

system.time(means <- map_dbl(lst, mean))
##   user  system elapsed 
##  1.557   0.073   1.630 

For the loop, I get:

system.time({
  means <- numeric(10000)
  for ( i in 1:10000 ) {
    means[i] <- mean(lst[[i]])
  }
})
##   user  system elapsed 
##  1.653   0.075   1.730 

The map-function is a bit faster, but the difference is small.

Remember also that vectorization is much faster than looping, and is also usually quite expressive, so don’t struggle to take a functional approach when vectorization is possible. (This advice applies to a several examples from this Chapter, in which the desired computations had already been accomplished in earlier chapters by some form of vectorization.)