3
votes

Say for instance I'm trying to use purrr::map2() to iterate rnorm() over a vector and I want to specify the options n and sd but not mean.

Using the "formula" way, I could do this:

len <- c(1, 3, 10); sigma <- c(1, 1, 10)
set.seed(123)
map2(len, sigma, ~rnorm(n = .x, sd = .y))

But is it possible to specify n and sd without specifying mean with the "function" way? If I do the following, it fills "sigma" in for mean because mean is the next option in rnorm() after n.

set.seed(123)
map2(len, sigma, rnorm) 

I could specify that mean is 0 so that "sigma" would apply to sd, as below:

set.seed(123)
map2(len, sigma, rnorm, mean = 0) 

But what if I wanted to leave mean at its default (without specifying it) and still have "sigma" apply to sd? As in, is there a way to do something like .x/.y if I'm using the "function" method.

Sorry that was wordy. Thanks a lot!

2
Yeah that is (editing my original Q to make that clearer), but I appreciate it. It's easy enough in this example, but for more complex functions I'd prefer not listing every option before the one I'm trying to get to. Thanks!Danny

2 Answers

4
votes

No, because you have to manually direct the data to parameters other than the first one[s]. This is one of the advantages of base R's Map, which can take named parameters for iteration:

library(purrr)

len <- c(1, 3, 10) 
sigma <- c(1, 1, 10)

set.seed(123)
map2(len, sigma, ~rnorm(n = .x, sd = .y)) %>% str()
#> List of 3
#>  $ : num -0.56
#>  $ : num [1:3] -0.2302 1.5587 0.0705
#>  $ : num [1:10] 1.29 17.15 4.61 -12.65 -6.87 ...

set.seed(123)
Map(rnorm, n = len, sd = sigma) %>% str()
#> List of 3
#>  $ : num -0.56
#>  $ : num [1:3] -0.2302 1.5587 0.0705
#>  $ : num [1:10] 1.29 17.15 4.61 -12.65 -6.87 ...

You can't do the same thing in map2 because the input parameters are named .x and .y, whereas Map slurps up all the parameters in ....

3
votes

Another option, aside from using Map, is to use pmap. This requires that you have your inputs in a list though.

set.seed(123)
a <- map2(len, sigma, ~rnorm(n = .x, sd = .y))

set.seed(123)
input <- list(n = len, sd = sigma)
b <- pmap(input, rnorm)

identical(a, b)
# [1] TRUE