64

I want to write a little function to generate samples from appropriate distributions, something like:

makeSample <- function(n,dist,params)
values <- makeSample(100,"unif",list(min=0,max=10))
values <- makeSample(100,"norm",list(mean=0,sd=1))

Most of the code works, but I'm having problems figuring out how to pass the named parameters for each distribution. For example:

params <- list(min=0, max=1)
runif(n=100,min=0,max=1) # works
do.call(runif,list(n=100,min=0,max=1)) # works
do.call(runif,list(n=100,params)) # doesn't work

I'm guessing I'm missing a little wrapper function somewhere but can't figure it out.

Thanks!

jkeirstead
  • 2,881
  • 3
  • 23
  • 26

3 Answers3

105

Almost there: try

do.call(runif,c(list(n=100),params)) 

Your variant, list(n=100,params) makes a list where the second element is your list of parameters. Use str() to compare the structure of list(n=100,params) and c(list(n=100),params) ...

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Just would like to add a comment that: the c() operation essentially expands/extends an existing list--ie, list(n=100)--by adding the items from a second list--ie, params. – Jerry T Dec 26 '19 at 15:50
14

c(...) has a concatenating effect, or in FP parlance, a flattening effect, so you can shorten the call; your code would be:

params <- list(min=0, max=1)
do.call(runif, c(n=100, params))

Try the following comparison:

params = list(min=0, max=1)
str(c(n=100, min=0, max=1))
str(list(n=100, min=0, max=1))
str(c(list(n=100),params))
str(c(n=100,params))

Looks like if a list is in there at any point, the result is a list ( which is a desirable feature in this use case)

Darren Bishop
  • 2,379
  • 23
  • 20
3

rlang::exec enables dynamic dots on any function.

args <- list(x = c(1:10, 100, NA), na.rm = TRUE)
rlang::exec(mean, !!!args)
Thomas Luechtefeld
  • 1,316
  • 15
  • 23