跨多页绘图

28

我使用facet_wrap函数制作了多个图表(n = ~51),但它们都出现在同一页上。现在经过搜索,我发现ggplot2无法将图表放置在多个页面上。

有没有办法做到这一点?我看了这个问题(Multiple graphs over multiple pages using ggplot)并尝试了其中的代码,但效果不佳。

以下是我的图表代码,它在一页上生成了大约51个图表,使它们非常小且难以看清。如果我能将其打印成每页1个图表的PDF文件,那就太好了:

ggplot(indbill, aes(x = prey, y = weight), tab) +
geom_polygon(aes(group = load, color = capture), fill = NA, size = 0.75) +
facet_wrap(~ individual) +
theme(axis.ticks.x = element_blank(),
    axis.text.x = element_text(size=rel(0.5)),
    axis.ticks.y = element_blank(),
    axis.text.y = element_blank()) +
xlab("") + ylab("") +
guides(color = guide_legend(ncol=2)) +
coord_radar()

如果有人可以给我写一点代码并解释一下,那就太好了。

3个回答

31

有多种实现分页的方法:ggforcegridExtra::marrangeGrob。还可以参考这个答案中的另一个示例。

ggforce:

library(ggplot2)
# install.packages("ggforce")
library(ggforce)

# Standard facetting: too many small plots
ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_wrap(~cut:clarity, ncol = 3)

# Pagination: page 1
ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_wrap_paginate(~cut:clarity, ncol = 3, nrow = 3, page = 1)

# Pagination: page 2
ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_wrap_paginate(~cut:clarity, ncol = 3, nrow = 3, page = 2)

# Works with grid as well
ggplot(diamonds) +
  geom_point(aes(carat, price), alpha = 0.1) +
  facet_grid_paginate(color~cut:clarity, ncol = 3, nrow = 3, page = 4)

gridExtra:

# install.packages("gridExtra")
library(gridExtra)

set.seed(123)
pl <- lapply(1:11, function(.x) 
  qplot(1:10, rnorm(10), main=paste("plot", .x)))

ml <- marrangeGrob(pl, nrow=2, ncol=2)

## non-interactive use, multipage pdf
## ggsave("multipage.pdf", ml)
## interactive use; calling `dev.new` multiple times
ml

此内容由reprex package (v0.2.0.9000)在2018-08-09创建。


23

一个选择是每次只绘制六个水平的individual,使用您现在正在使用的相同代码。 您只需要多次迭代它,每次为数据的每个子集迭代一次。 您没有提供示例数据,因此这里是使用Baseball数据框的示例:

library(ggplot2)
library(vcd) # For the Baseball data
data(Baseball)

pdf("baseball.pdf", 7, 5)
for (i in seq(1, length(unique(Baseball$team87)), 6)) {
   print(ggplot(Baseball[Baseball$team87 %in% levels(Baseball$team87)[i:(i+5)], ], 
                  aes(hits86, sal87)) + 
    geom_point() +
    facet_wrap(~ team87) +
    scale_y_continuous(limits=c(0, max(Baseball$sal87, na.rm=TRUE))) +
    scale_x_continuous(limits=c(0, max(Baseball$hits86))) +
    theme_bw())
}
dev.off()

上面的代码将生成一个包含四页图形的PDF文件,每页有六个小面板。您还可以创建四个单独的PDF文件,每个文件包含六个小面板的一组:

for (i in seq(1, length(unique(Baseball$team87)), 6)) {
pdf(paste0("baseball_",i,".pdf"), 7, 5)
  ...ggplot code...
dev.off()
}

如果需要更多的灵活性,另一种选择是为每个分面变量(即每个唯一值)创建一个单独的图形,并将所有单个图形保存在列表中。然后您可以在每个页面上排列任意数量的图形。这可能有些过度了,但这里有一个例子,其中灵活性会派上用场。

首先,让我们创建所有的图形。我们将使用team87作为我们的分面列。因此,我们要为team87的每个级别制作一个图形。我们将通过按team87拆分数据并为数据的每个子集创建单独的图形来完成此操作。

在下面的代码中,split将数据拆分为每个team87级别的单独数据框。 lapply包装器依次将每个数据子集馈送到ggplot中,以为每个团队创建一个图形。我们将输出保存在plist中,即(在本例中)24个图形的列表。

plist = lapply(split(Baseball, Baseball$team87), function(d) {
  ggplot(d, aes(hits86, sal87)) + 
    geom_point() +
    facet_wrap(~ team87) +
    scale_y_continuous(limits=c(0, max(Baseball$sal87, na.rm=TRUE))) +
    scale_x_continuous(limits=c(0, max(Baseball$hits86))) +
    theme_bw() +
    theme(plot.margin=unit(rep(0.4,4),"lines"),
          axis.title=element_blank())
})

现在我们将在PDF文件中一次绘制六个图。以下有两个选项,一个是四个单独的PDF文件,每个文件有六个图,另一个是一个四页PDF文件。我还在底部粘贴了一个图。我们使用grid.arrange来布置这些图形,包括使用leftbottom参数添加坐标轴标题。

library(gridExtra)

# Four separate single-page PDF files, each with six plots
for (i in seq(1, length(plist), 6)) {
  pdf(paste0("baseball_",i,".pdf"), 7, 5)
  grid.arrange(grobs=plist[i:(i+5)], 
               ncol=3, left="Salary 1987", bottom="Hits 1986")
  dev.off()
}

# Four pages of plots in one PDF file
pdf("baseball.pdf", 7, 5)
for (i in seq(1, length(plist), 6)) {
  grid.arrange(grobs=plist[i:(i+5)], 
               ncol=3, left="Salary 1987", bottom="Hits 1986")
}
dev.off()

嗨 @eipi10!那个工作得很好,而且很容易理解!然而我遇到了一个问题。似乎代码不喜欢我的某个元素,出现了这个错误。它在遇到这个元素后停止打印: = list(grobs Error in gList(705-70773 = list(grobs = list(list(x = 0.5, y = 0.5, : only 'grobs' allowed in "gList"帮助将不胜感激! - LearningTheMacros
1
是否有关于该个体数据的问题导致没有绘图呢?如果没有绘图,则绘图代码的输出将不是grob(图形对象)。例如,该个体的所有数据是否都缺失或类似情况?尝试创建您的绘图,但提供一个仅包含该个体数据的数据框并查看发生了什么。查看该个体的数据,看看是否有明显不同之处。 - eipi10
情节是在我使用HubertL的建议时制作的,所以我不知道。无论如何,我理解了你的答案,它将对我未来有所帮助。再次感谢! - LearningTheMacros
这个真的很有帮助。我遇到了一个情况,在 for 循环中需要绘制的 plot 只是对 ggplot() 的简单调用,我不得不先将其赋值给一个对象,然后使用 print(my_plot) 以便将其保存到文件中。 - Nicholas G Reich

2

类似以下内容:

by(indbill, indbill$individual, function (x){
    ggplot(x, aes(x = prey, y = weight), tab) +
    geom_polygon(aes(group = load, color = capture), fill = NA, size = 0.75) +
    theme(axis.ticks.x = element_blank(),
        axis.text.x = element_text(size=rel(0.5)),
        axis.ticks.y = element_blank(),
        axis.text.y = element_blank()) +
    xlab("") + ylab("") +
    guides(color = guide_legend(ncol=2)) +
    coord_radar()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接