2015-07-16 5 views
3

Я хочу определить функцию сохранения сюжета, которая использует устройство gridsvg из пакета gridSVG.gridsvg не работает при использовании внутри функции

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

Однако, если я попытаюсь использовать функцию, это не сработает. Произойдет ошибка:

savePlot("~/Desktop/myplot.svg", myPlot) 
Show Traceback 

Rerun with Debug 
Error in eval(expr, envir, enclos) : object 'filename' not found 

Однако, если я делаю эти шаги с консоли это работает:

gridSVG::gridsvg(name = "~/Desktop/myPlot.svg", width = 15, height = 10) 
myPlot 
dev.off() 

Есть ли способ, что я мог бы использовать функцию gridsvg из другой функции?

Интересно, могу ли я сделать это с помощью eval из какой-либо среды.

Thanks, Ben.

+0

Как любопытно! 'gridsvg' имеет кучу' eval (fncall [[i]]), который, кажется, вызывает проблему, но вы бы подумали, что именованные аргументы будут отфильтрованы до правильной среды? –

ответ

2

Вот окольным, но чуть более принципиален, способ, не прилипая все в глобальной среде (вдохновленный обсуждение обзорного в 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) дает нам рамки оценки родительского контекста (есть описание ok here для всех вариантов функций, которые обращаются к стеку вызовов).

Я отделяю вызов grid.export() от вызова к dev.off(), потому что по существу все в dev.off от gridSVG делает вызов grid.export, а затем вызвать grDevices::dev.off. Это также позволяет напрямую указывать имя файла на grid.export.

2

Как любопытно. gridsvg, похоже, имеет шаг eval(fncall[[i]]), где он просматривает все аргументы и назначает их, и он должен искать в неправильной среде или что-то в этом роде? Я не уверен, что это проблема с пакетом gridSVG; eval -семантика всегда путают меня.

Это обходное решение: если вы убедитесь, что аргумент -values- get прошел до gridsvg (а не имена аргументов), он работает, хотя я согласен, что это не особенно элегантно. И вы должны явно указать 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()) 
} 

Все это делает по существу называть gridsvg с width=15, а не width=plotWidth и так далее.

Смежные вопросы