Help in understanding behavior of functions as arguments when passed to map_dbl

Using map_dbl in a function works as I expected.

my_func <- function(){map_dbl(1:5, ~ sample(1:10, size = 1))}
my_func()
[1] 6 8 9 7 6

But let's redefine my_func to accept a function as an argument:

my_func <- function(FUN){map_dbl(1:5, ~ FUN)}

I would expect this to work the same as the above. But, instead, it produces a vector of identical numbers each time is it called.

my_func(sample(1:10, size = 1))
[1] 2 2 2 2 2
my_func(sample(1:10, size = 1))
[1] 10 10 10 10 10

  1. I am interested in understanding why this is so.

  2. How can I get the same behavior when passing in the full function as an argument? That is, I want my_func(sample(1:10, size = 1)) to produce a 5 element vector with each element being the result of an independent call to sample(1:10, size = 1)

Here's your function: my_func <- function(FUN){map_dbl(1:5, ~ FUN)}.

What I understand is that you expect that this function will take any function, say f as an argument and return c(f(1), f(2), f(3), f(4), f(5)). So, if you use a function that doesn't really depend its argument, it'll be same as 5 repetitions of the same function.

Is that so?

If yes, then it's not doing anything as such. It doesn't check whether FUN is a function or not, and if it's not, it doesn't care. It actually takes a number as an argument, and returns that 5 times.

Here's an illustration:

> library(purrr)
> 
> my_func <- function(FUN) map_dbl(1:5, ~ FUN)
> 
> set.seed(seed = 35763)
> a <- sample(x = 1:10, size = 1)
> my_func(FUN = a)
[1] 8 8 8 8 8
> 
> set.seed(seed = 35763)
> my_func(FUN = sample(x = 1:10, size = 1))
[1] 8 8 8 8 8

I would have done simply this:

> set.seed(seed = 35763)
> replicate(n = 5, expr = sample(x = 1:10, size = 1))
[1]  8  6  1 10  3

If you're a tidy person, consider purrr::rerun. Or, just use map_dbl this way:

> set.seed(seed = 35763)
> purrr::map_dbl(.x = 1:5, .f = ~ sample(x = 1:10, size = 1))
[1]  8  6  1 10  3

Hope this helps.

1 Like

Thanks for your reply!

So, if you use a function that doesn't really depend its argument, it'll be same as 5 repetitions of the same function. Is that so?

Yes. But I want these repetitions to be "fresh", that is, not as if the same seed were set before each one. So, sample() should not produce the same answer 5 times in a row.

I would have done simply this:

But, my issue is that this code needs to run within another function. So, I could use map_dbl, as in your example, but then I get:

my_func <- function(FUN){map_dbl(.x = 1:5, .f = ~ FUN)}
my_func(FUN = sample(x = 1:10, size = 1))
[1] 9 9 9 9 9

Which is not what I want, obviously.

Here is a simpler example of my question. This works as expected. I am calling runif(1) five times and, each time, it produces a different number.

map_dbl(.x = 1:5, .f = ~ runif(1))
[1] 0.4758260 0.1840778 0.4199492 0.5779564 0.8983577

But when I pass in runif(1) as an argument, I get five copies of the same answer:

my_func <- function(FUN){map_dbl(.x = 1:5, .f = ~ FUN)}
my_func(runif(1))
[1] 0.7555603 0.7555603 0.7555603 0.7555603 0.7555603

For reasons that are unclear to me, this solves my problem:

my_func <- function(FUN){map_dbl(.x = 1:5, .f = FUN)}
my_func(~ runif(1))
[1] 0.92841984 0.66576421 0.45799861 0.88515905 0.03660372

Thanks again to Yarnabrina for the help.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.