Gridsvg doesn't work when used inside a function
I want to define a plot save function that uses the gridsvg device from the gridSVG package.
library(ggplot2)
library(gridExtra)
mtcars$gear <- factor(mtcars$gear,levels=c(3,4,5),
labels=c("3gears","4gears","5gears"))
mtcars$am <- factor(mtcars$am,levels=c(0,1),
labels=c("Automatic","Manual"))
mtcars$cyl <- factor(mtcars$cyl,levels=c(4,6,8),
labels=c("4cyl","6cyl","8cyl"))
myPlot <- qplot(mpg, data=mtcars, geom="density", fill=gear, alpha=I(.5),
main="Distribution of Gas Milage", xlab="Miles Per Gallon",
ylab="Density")
savePlot <- function(filename, plot, plotWidth = 15, plotHeight = 10){
gridSVG:::gridsvg(name = filename, width = plotWidth, height = plotHeight)
print(plot)
dev.off(which = dev.cur())
}
However, if I try to use the function, it doesn't work. Error result:
savePlot("~/Desktop/myplot.svg", myPlot)
Show Traceback
Rerun with Debug
Error in eval(expr, envir, enclos) : object 'filename' not found
However, if I do these steps from the console, it works:
gridSVG::gridsvg(name = "~/Desktop/myPlot.svg", width = 15, height = 10)
myPlot
dev.off()
Can the gridsvg function be used from another function?
I wonder if I can do this using eval from some environment.
Thanks Ben.
source to share
Here's a circular, but slightly more principled way, without pushing everything into the global environment (inspired by the discussion in R Inferno ):
library(gridSVG)
savePlot <- function(filename, plot, plotWidth = 15, plotHeight = 10){
gridsvg(sys.frame(1))
print(plot)
grid.export(filename)
grDevices::dev.off(which = dev.cur())
}
sys.frame(1)
gives us a framework for evaluating the parent context (there is an explanation here for all options for functions that access the call stack).
I have separated the call grid.export()
from the call to dev.off()
, because essentially everything dev.off
from gridSVG is a call grid.export
, and then call grDevices::dev.off
. It also allows you to specify the filename directly grid.export
.
source to share
How curious. gridsvg
seems to have a step eval(fncall[[i]])
where it goes through all the arguments and assigns them and it should be looking for the wrong environment or something? I'm not sure if this is a package problem gridsvg
; eval
-semantics always confuse me.
Here's a workaround: if you make sure the -values- get argument is passed in gridsvg
(and not in the argument names), it works, although I agree it's not particularly elegant. And you should explicitly library(gridSVG)
.
library(gridSVG)
savePlot <- function(filename, plot, plotWidth = 15, plotHeight = 10){
eval(call('gridsvg', name=filename, width=plotWidth, height=plotHeight))
print(plot)
dev.off(which = dev.cur())
}
Everything it does is essentially call gridsvg
with width=15
, not width=plotWidth
, etc.
source to share