将图保存在对象中


80

在中ggplot2,可以轻松地将图形保存到R对象中。

p = ggplot(...) + geom_point()      # does not display the graph
p                                   # displays the graph

标准函数plot将图形生成为void函数,并返回NULL。

p = plot(1:10)     # displays the graph
p                  # NULL

是否可以保存由plot对象创建的图形?


plotplot据我所知,是通用的,并且不同的方法确实会返回此类对象。plot.default但是,确实会返回NULL
康拉德·鲁道夫2015年

您的目标是仅p在将图形另存为对象后才能通过键入来重新绘制图形吗?还是想将其另存为对象,然后例如可以更改其值?
LyzandeR 2015年

我可能想在已保存的图形上叠加其他图形,但是我不打算修改已创建并保存的图。我回答了你的问题吗?THKS
Remi.b

@ Remi.b的确谢谢。我发布了可能有帮助的解决方案。
LyzandeR 2015年

Answers:


91

基本图形直接在设备上绘制。

你可以用

1- recordPlot

2-最近推出的gridGraphics软件包,用于将基本图形转换为等效的网格

这是一个最小的例子,

plot(1:10) 

p <- recordPlot()
plot.new() ## clean up device
p # redraw

## grab the scene as a grid object
library(gridGraphics)
library(grid)
grid.echo()
a <- grid.grab()

## draw it, changes optional
grid.newpage()
a <- editGrob(a, vp=viewport(width=unit(2,"in")), gp=gpar(fontsize=10))
grid.draw(a)

1
我不清楚:(1)和(2)是实现同一目标的单独方法,还是回答OP的问题都需要两个步骤?
NLi10Me

@ NLi10Me 2种不同的方法。
zx8754

如果尝试saveRDS(object = p, file = "p.Rds"),然后加载一个新的R会话,p <- readRDS(file = "p.Rds")然后运行p,我得到一个错误提示Error in replayPlot(x) : loading snapshot from a different session。我保存p对象不正确吗?
user5359531

似乎我得到的错误已在R 3.3.0中解决,使用该版本即可。当我使用gridGraphics此处显示的方法时,即使使用grid.grab(wrap=TRUE)
user5359531 '18

34

我对此很迟,但是这是我搜索问题时出现的第一个问题。因此,我想为遇到此问题的未来观众添加我的解决方案。

我通过使用函数而不是对象解决了这个问题。例如,假设我们要比较两个具有不同参数的beta分布。我们可以运行:

z1<-rbeta(10000,5,5)
z2<-rbeta(10000,20,20)
plotit<-function(vector,alpha,beta){
plot(density(vector),xlim=c(0,1))
abline(v=alpha/(alpha+beta),lty="longdash")
}

并将图另存为函数而不是对象。

z.plot1<-function(){plotit(z1,5,5)}
z.plot2<-function(){plotit(z2,20,20)}

接下来,我们可以通过简单地将两个图称为函数而不是对象来调用每个图。

z.plot1()

绘制第一个图并

z.plot2()

绘制第二个。

希望这对以后偶然跌倒的人有所帮助!


这非常有用!我认为这是一个很好的主意,以便准备预设图,这就是我要寻找的内容
Jojostack

这是一个天才的基于R的方法!recordPlot绝对有用(如果您已经打开了一个窗口),但是这个答案正是人们访问此帖子时正在寻找的东西。+1!
森林生态学家

对于复杂的多图尤其有用。

让我加入真正欣赏这一技巧的人们的合唱。还要代表我的学生:-)
Laryx Decidua

再次进行词汇范围救援!:)
詹森

17

pryr如果您不想直接更改创建的对象的值,则可以使用包的活动绑定功能。

library(pryr)
a %<a-% plot(1:10,1:10)

每次a在控制台上键入时,图形都会重新打印在屏幕上。该%<a-%运营商将每一次(在一个图的情况下,这是没有问题的,我认为)重新运行该脚本。因此,基本上,每次使用a该代码时,都会重新运行,从而生成图形,您当然可以对其进行操作(在顶部覆盖另一个图)或使用png例如保存。a但是,将不会存储任何值本身。该值仍将为NULL。

我不知道以上是否是您要寻找的,但这可能是可以接受的解决方案。


谢谢。这是一个非常方便的解决方案。您是否知道该图是通过多条线构建的(plot(1:10);abline(v=4)例如),这是否可行?+1
Remi.b 2015年

@ Remi.b当然可以。但是,您需要像这样键入它a %<a-% {plot(1:10);abline(v=4)}。”如果在大括号内键入它,则可以有任意多行!此外,如果您要重新分配一个值,则a需要先使用删除它rm(a),然后使用重新分配它。在%<a-%操作,否则你会得到一个警告,我不知道为什么会这样,但我想这不是什么大不了的事。
LyzandeR

这真是太酷了!我将不得不阅读一些有关此程序包的信息,因为对于我来说,做这个奇怪的函数%<a-%正在做的事情听起来是不可能的。谢谢
Remi.b 2015年

是的,这是哈德利(Hadley)制作的那些非常酷的包裹中的另一个。它是一组功能,可让您深入了解R语言。也可以看看%<d-%,以后可能会派上用场。很高兴能为您提供帮助:)
LyzandeR 2015年

1
@LyzandeR是否可以将保存的图合并为多图?
user2300940 '16

-2
library(ggplot2)
# if mygraph is a plot object
ggsave("myplot1.png",mygraph)

# if the plot is in a list (e.g. created by the Bibliometrics package)
ggsave("myplot1.png",mygraphs[[1]])

尽管您的答案看起来“正确”(但是我不是R程序员),但是在Stack Overflow上通常的做法是添加一些说明性文字,而不是仅仅发布“仅”代码块。从长远来看,这对于更广泛的用户而言,答案将更有价值。(但无论如何都要赞成!)
Adrian Mole19年

3
OP正在询问如何使用ggplot2来执行此操作。
杰森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.