Get arguments supplied to a purrr::pmap call

172 views Asked by At

I'm running a function with many arguments and I'm exploring how changes in some arguments affect the output of the function. I'm doing that through purrr::pmap. I'd like to keep track of the arguments used for each function call: I'd like the function to return its output, as well as a named list of the values of all the arguments used.

Here's a MWE:

f <- function (a, b, c) a + b + c
a_values <- 1:5
effect_of_a <- pmap(list(a = a_values), f, b = 0, c = 0)

I'd like effect_of_a to be a list of list, where each sublist contains not only the result f(a,b,c), but also the values of a, b and c used. I could code that list manually, but I have many arguments and they may change. So is there a way to capture the list of arguments and their values in a function call initiated by purrr:pmap?

3

There are 3 answers

0
starja On BEST ANSWER

Here is a general solution where the arguments are captured in an extra function f_2, which is called with pmap instead of f:

library(purrr)
f <- function (a, b, c) a + b + c
f_2 <- function(a, b, c) {
  list(result = f(a, b, c),
       args = c(as.list(environment())))
}
a_values <- 1:3
pmap(list(a = a_values), f_2, b = 0, c = 0)
[[1]]
[[1]]$result
[1] 1

[[1]]$args
[[1]]$args$a
[1] 1

[[1]]$args$b
[1] 0

[[1]]$args$c
[1] 0



[[2]]
[[2]]$result
[1] 2

[[2]]$args
[[2]]$args$a
[1] 2

[[2]]$args$b
[1] 0

[[2]]$args$c
[1] 0



[[3]]
[[3]]$result
[1] 3

[[3]]$args
[[3]]$args$a
[1] 3

[[3]]$args$b
[1] 0

[[3]]$args$c
[1] 0
1
Waldi On

You could use with :

pmap(list(a = a_values), ~with(list(...), list(f = f(...),args = list(...))),
          b = 0,
          c = 0)

[[1]]
[[1]]$f
[1] 1

[[1]]$args
[[1]]$args$a
[1] 1

[[1]]$args$b
[1] 0

[[1]]$args$c
[1] 0
...
0
CzechInk On

For a list of lists, you could also try something like:

effect_of_a <- map(a_values %>% as.list, function(a, b = 0, c = 0) {
  list(f_eval = f(a, b, c),
       a = a, 
       b = b, 
       c = c)
})

If the values for b & c are changing too, you could try:

b_values <- 2:6
c_values <- 3:7

effect_of_a <- list(a_values, b_values, c_values) %>%
  map(~.x %>% as.list) %>%
  pmap(~list(f_eval = f(..1, ..2, ..3),
             a = ..1, 
             b = ..2, 
             c = ..3))