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.
🐈 @sauer_sebastian takes you through `partial()` & `pmap()`…
— Mara Averick (@dataandme) October 1, 2019
😺 "Looping over function arguments using purrr" https://t.co/LFdLP7a3g7 #rstats
✂️ figure monstrosity mine pic.twitter.com/JrcuHURirj
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