edply: combining plyr and expand.grid

November 30, 2012
By

(This article was first published on dahtah » R, and kindly contributed to R-bloggers)

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()

edply_1
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))

edply_2
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"))
}

To leave a comment for the author, please follow the link and comment on his blog: dahtah » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.