Martin Rittner
2008-Feb-15 20:21 UTC
[R] ggplot2 used in a function - variable scope/environment
Hi everybody!
I'm trying to use ggplot2 to return a plot from a function (so I can add
something or alter it then). Unfortunately, if I add a mapping to a
layer in the function, the variable *name* is stored in the layer,
rather than the variable's *value* - so that after the function returns
the ggplot2-object, it doesn't plot because the variable don't exist in
the environment calling the function.. e.g:
my function does something like:
getPlot<-function(da=NULL,...){
#1st column holds x-values, others hold data series to plot...
co<-as.character(names(da))
co<-co[2:length(co)]
pl<-ggplot(data=da)
pl<-pl+scale_y_log10()+scale_x_continuous()
for(c in co){
pl<-pl+geom_line(x=da[[1]],y=da[[c]],mapping=aes(x=da[[1]],y=da[[c]]))
}
return(pl)
}
I need to add every layer separately, because I want to be able to
explicitly define attributes for every data series (colour, size... e.g.
highlight only two specific out of 10 series...).
Anyway, my problem is this:
d<-data.frame(x=seq(0.0,1.0,length=5),y1=rnorm(5),y2=rnorm(5))
p<-getPlot(da=d)
p
returns with
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 0, 5
and the plot object contains:
Title:
Labels: x=, y-----------------------------------
Data: x, y1, y2 [5x3]
Mapping:
Scales: y,x -> y,x
$margins
[1] FALSE
$facets
[1] ". ~ ."
-----------------------------------
geom_line: (colour=black, size=1, linetype=1, x=NA, y=NA) + (x=c(0,
0.25, 0.5, 0.75, 1), y=c(0.180036717548597, -0.369556903134046,
-0.924474152821948, -2.40773640658189, 0.801471591443009))
stat_sort: (...=) + (x=c(0, 0.25, 0.5, 0.75, 1), y=c(0.180036717548597,
-0.369556903134046, -0.924474152821948, -2.40773640658189,
0.801471591443009))
position_identity: ()
mapping: (x=da[[1]], y=da[[c]])
geom_line: (colour=black, size=1, linetype=1, x=NA, y=NA) + (x=c(0,
0.25, 0.5, 0.75, 1), y=c(-1.59744511956184, -0.9333541477049,
1.88697835844878, 0.921829569181679, -0.741077741846118))
stat_sort: (...=) + (x=c(0, 0.25, 0.5, 0.75, 1), y=c(-1.59744511956184,
-0.9333541477049, 1.88697835844878, 0.921829569181679, -0.741077741846118))
position_identity: ()
mapping: (x=da[[1]], y=da[[c]])
Note the mappings, they refer to "da" and "c" (defined in
the function)
which are not available in the calling environment. Any Idea how I can
avoid the problem/paste the actual values in, like it did for the
geometry and the statistics?
Thanks, Martin
hadley wickham
2008-Feb-15 21:16 UTC
[R] ggplot2 used in a function - variable scope/environment
Hi Martin, Two comments: * ggplot always requires the data to be plotted to be stored in a data.frame, not the environment - this makes it possible to (e.g.) save self contained plot objects - but that isn't the problem here, the problem is setting up the appropriate mapping * aes_string makes it easier to build up aesthetic mappings programmatically - aes_string(x = names(data)[1], y = names(data)[c]) Does that help? Hadley On Fri, Feb 15, 2008 at 2:21 PM, Martin Rittner <martin.rittner at thegeologician.net> wrote:> Hi everybody! > > I'm trying to use ggplot2 to return a plot from a function (so I can add > something or alter it then). Unfortunately, if I add a mapping to a > layer in the function, the variable *name* is stored in the layer, > rather than the variable's *value* - so that after the function returns > the ggplot2-object, it doesn't plot because the variable don't exist in > the environment calling the function.. e.g: > > my function does something like: > > getPlot<-function(da=NULL,...){ > #1st column holds x-values, others hold data series to plot... > co<-as.character(names(da)) > co<-co[2:length(co)] > > pl<-ggplot(data=da) > pl<-pl+scale_y_log10()+scale_x_continuous() > for(c in co){ > pl<-pl+geom_line(x=da[[1]],y=da[[c]],mapping=aes(x=da[[1]],y=da[[c]])) > } > > return(pl) > } > > I need to add every layer separately, because I want to be able to > explicitly define attributes for every data series (colour, size... e.g. > highlight only two specific out of 10 series...). > > Anyway, my problem is this: > > d<-data.frame(x=seq(0.0,1.0,length=5),y1=rnorm(5),y2=rnorm(5)) > p<-getPlot(da=d) > p > > returns with > > Error in data.frame(..., check.names = FALSE) : > arguments imply differing number of rows: 0, 5 > > and the plot object contains: > > Title: > Labels: x=, y> ----------------------------------- > Data: x, y1, y2 [5x3] > Mapping: > Scales: y,x -> y,x > $margins > [1] FALSE > > $facets > [1] ". ~ ." > > ----------------------------------- > geom_line: (colour=black, size=1, linetype=1, x=NA, y=NA) + (x=c(0, > 0.25, 0.5, 0.75, 1), y=c(0.180036717548597, -0.369556903134046, > -0.924474152821948, -2.40773640658189, 0.801471591443009)) > stat_sort: (...=) + (x=c(0, 0.25, 0.5, 0.75, 1), y=c(0.180036717548597, > -0.369556903134046, -0.924474152821948, -2.40773640658189, > 0.801471591443009)) > position_identity: () > mapping: (x=da[[1]], y=da[[c]]) > > geom_line: (colour=black, size=1, linetype=1, x=NA, y=NA) + (x=c(0, > 0.25, 0.5, 0.75, 1), y=c(-1.59744511956184, -0.9333541477049, > 1.88697835844878, 0.921829569181679, -0.741077741846118)) > stat_sort: (...=) + (x=c(0, 0.25, 0.5, 0.75, 1), y=c(-1.59744511956184, > -0.9333541477049, 1.88697835844878, 0.921829569181679, -0.741077741846118)) > position_identity: () > mapping: (x=da[[1]], y=da[[c]]) > > Note the mappings, they refer to "da" and "c" (defined in the function) > which are not available in the calling environment. Any Idea how I can > avoid the problem/paste the actual values in, like it did for the > geometry and the statistics? > > Thanks, Martin > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- http://had.co.nz/