Here’s a code snippet I thought I’d share. Very often I find myself checking the output of a function f(a,b) for a lot of different values of a and b, which I then need to plot somehow.

An example: here’s a function that computes the value of a sinusoidal function on a grid of points, and returns a data.frame.

fun <- function(freq,phase) { x <- seq(0,2*pi,l=100); data.frame(x=x,value=sin(freq*x-phase)) }

It takes a frequency and a phase argument, and we want to know what the output looks like for frequencies between 1 and 6 and phase values of 0 and 1.

Usually this means calling e.g., expand.grid(freq=1:6,phase=c(0,1)), to get all possible combinations of the two variables, then calling one of the plyr functions to get the results in a useable form. The edply function does it all in one line:

d <- edply(list(freq=c(1,2,4,8),phase=c(0,1)),fun)

which returns a data.frame:

> head(d,3)

freq phase x value

1 1 0 0.00000000 0.00000000

2 1 0 0.06346652 0.06342392

3 1 0 0.12693304 0.12659245

which we can then plot:

ggplot(d,aes(x,value,col=as.factor(phase)))+facet_wrap( ~ freq)+geom_path()

The edply function can also be used to compute and plot a heatmap:

fun <- function(x,y) dnorm(x)*dnorm(y)*sin(x) d <- edply(list(x=seq(-3,3,l=40),y=seq(-3,3,l=40)),fun) ggplot(d,aes(x,y))+geom_raster(aes(fill=V1))

I’ve attached the code below, there really isn’t much to it. Note that there’s also an “elply” function that (not unexpectedly) returns a list.

#eply: combining plyr and expand.grid. #Simon Barthelmé, University of Geneva # #Example usage #------------- #fun <- function(x,y) dnorm(x)*dnorm(y)*sin(x) #d <- edply(list(x=seq(-3,3,l=40),y=seq(-3,3,l=40)),fun) #ggplot(d,aes(x,y))+geom_raster(aes(fill=V1)) #Heatmap of f(x,y) elply <- function(vars,fun,...,.progress="none",.parallel=FALSE) { df <- do.call("expand.grid",vars) if (all(names(vars) %in% names(formals(fun)))) { #We assume that fun takes the variables in vars as named arguments funt <- function(v,...) { do.call(fun,c(v,list(...))) } res <- alply(df,1,funt,...,.progress=.progress,.parallel=.parallel) } else { #We assume that fun takes a named list as first argument res <- alply(df,1,fun,...,.progress=.progress,.parallel=.parallel) } res } edply <- function(...) { res <- elply(...) plyr:::list_to_dataframe(res,attr(res, "split_labels")) }