views:

54

answers:

1

I have a dataframe:

priors <- data.frame(dist = c('lnorm', 'beta', 'gamma'),
                      a   = c(0.5, 1, 10),
                      b   = c(0.4, 25, 4),
                      n   = c(100, 100, 100)
                     )

and I would like to take n samples from the distribution with parameters a and b.

I have written this function:

pr.samp <- function(n,dist,a,b) {eval (parse ( 
                    text = 
                    paste("r",dist,"(",n,",",a,",",b,")",sep = "")
                    ))}

I would like to know:

  1. is there a better approach?
  2. how would I use one of the apply functions to run this on each row?
  3. do I have to convert the dataframe to a matrix to do this?

Thanks in advance!

+2  A: 

see ?do.call

pr.samp <- function(n,dist,a,b) {
    do.call(paste('r',dist,sep=""),list(n,a,b))
}

Using an apply is difficult, as you have mixed character and numeric vectors in your dataframe. using apply on the rows will give you character vectors, which will cause errors. Converting to a matrix will give a character matrix. I'd do something like :

sapply(1:nrow(priors),function(x){
  pr.samp(priors$n[x],priors$dist[x],priors$a[x],priors$b[x])})

Alternatively, the solution of Joshua is cleaner :

sapply(1:nrow(priors), function(x) do.call(pr.samp,as.list(priors[x,])))
Joris Meys
Or you could use `do.call` again: `sapply(1:nrow(priors), function(x) do.call(pr.samp,as.list(priors[x,])))`
Joshua Ulrich
@Joshua : thx for the pointer
Joris Meys
Thanks Joris and Joshua!
David
@Joris I don't know that it's "cleaner", but it reinforces the usefulness of `do.call`.
Joshua Ulrich
Note that you don't need `as.list` - a data frame is already a list.
hadley