2 min read

Looping over function arguments using purrr

Load packages

library(tidyverse)

Problem statement

Assume you have to call a function multiple times, but each with (possibly) different argument. Given enough repitioons, you will not want to repeat yourself.
In other words, we would like to loop over function arguments, each round in the loop giving the respective argument’value(s) to the function.

One example would be to generate many random values but each with different mean and/or sd:

rnorm(n = 1, mean = 0, sd = 1)
#> [1] -1.125083
rnorm(n = 2, mean = 0, sd = 2)
#> [1] 2.542126 4.880299
rnorm(n = 3, mean = 0, sd = 3)
#> [1]  0.3925394 -0.4260117  0.0236865
# heck, my wrists strains!

Note that some arguments may not change.

Enter purrr

One way to build a loop is using purrr.

First we define the list of arguments.

args <- list(sd = c(1, 2, 3), n = c(1, 2, 3))

If we have some arguments that do not change, we can come up with a “prefilled” function, called a partial in purrr:

rnorm_m0 <- partial(rnorm, mean = 0)

With pmap we can map many lists (“values”, here: arguments and their values) to a function.

The following image taken from Hadley Wickham’s book Advanced R helps to visualize what pmap does:


UPDATE

Mara Averick built a figure that illustrates the example of this post. Maybe more than words can, such a figure illustrate what map() and friends (here: pmap()) do. Check out Mara’s cheatsheet on purrr, it’s super helpful.


set.seed(42)
pmap(args, rnorm_m0)
#> [[1]]
#> [1] 1.370958
#> 
#> [[2]]
#> [1] -1.1293963  0.7262568
#> 
#> [[3]]
#> [1]  1.8985878  1.2128050 -0.3183735

Alternatively, we can directly hand-over the “constant” argument to pmap:

set.seed(42)
pmap(args, rnorm, mean = 0)
#> [[1]]
#> [1] 1.370958
#> 
#> [[2]]
#> [1] -1.1293963  0.7262568
#> 
#> [[3]]
#> [1]  1.8985878  1.2128050 -0.3183735