R 将多个绘图打印到单个pdf中,每页打印多个绘图

R 将多个绘图打印到单个pdf中,每页打印多个绘图,r,ggplot2,R,Ggplot2,我有一个列表,p,其中p的每个元素都是ggplot2绘图对象的列表 我想输出一份pdf,其中包含p中的所有绘图,这样p[[1]]中的绘图位于第1页,p[[2]]中的绘图位于第2页,等等。我该如何做 下面是一些示例代码,为您提供了我正在使用的数据结构——为这些枯燥的绘图道歉,我随机选取了变量 require(ggplot2) p <- list() cuts <- unique(diamonds$cut) for(i in 1:length(cuts)){ p[[i]] &l

我有一个列表,
p
,其中
p
的每个元素都是ggplot2绘图对象的列表

我想输出一份pdf,其中包含
p
中的所有绘图,这样
p[[1]]
中的绘图位于第1页,
p[[2]]
中的绘图位于第2页,等等。我该如何做

下面是一些示例代码,为您提供了我正在使用的数据结构——为这些枯燥的绘图道歉,我随机选取了变量

require(ggplot2)
p <- list()

cuts <- unique(diamonds$cut)
for(i in 1:length(cuts)){
    p[[i]] <- list()
    dat <- subset(diamonds, cut==cuts[i])
    p[[i]][[1]] <- ggplot(dat, aes(price,table)) + geom_point() + 
        opts(title=cuts[i])
    p[[i]][[2]] <- ggplot(dat, aes(price,depth)) + geom_point() + 
        opts(title=cuts[i])
}
require(ggplot2)

p这里有一个解决方案,但我并不特别喜欢:

ggsave(“test.pdf”、do.call(“marrangeGrob”、c(unlist(p,recursive=FALSE)、nrow=2、ncol=1))


问题在于,它依赖于每组中有相同数量的地块。如果
all(sapply(p,length)==2)
为false,则它将中断。

此解决方案与列表
p
中列表的长度是否不同无关

library(gridExtra)

pdf("plots.pdf", onefile = TRUE)
for (i in seq(length(p))) {
  do.call("grid.arrange", p[[i]])  
}
dev.off()

由于
onefile=TRUE
函数
pdf
保存同一文件中按顺序出现的所有图形(一页对应一个图形)。

对于那些盲目使用do.call和嵌套列表的R初学者,这里有一个更简单的Sven解决方案,他们既不需要也不理解。我有经验证据

库(ggplot2)
图书馆(gridExtra)
pdf(“plots.pdf”,onefile=TRUE)

不使用
gridExtra
软件包就可以切割一个很好的解决方案:

library(plyr)
library(ggplot2)

li = structure(p, class = c("gglist", "ggplot"))
print.gglist = function(x, ...) l_ply(x, print, ...)
ggsave(li, file = "test.pdf")

下面是一个基于Sven方法的函数,包括roxygen2文档和一个示例

#' Save list of ggplot2 objects to single pdf
#'
#' @param list (list) List of ggplot2 objects.
#' @param filename (chr) What to call the pdf.
#'
#' @return Invisible NULL.
#' @export
#'
#' @examples
#' #plot histogram of each numeric variable in iris
#' list_iris = map(names(iris[-5]), ~ggplot(iris, aes_string(.)) + geom_histogram())
#' #save to a single pdf
#' GG_save_pdf(list_iris, "test.pdf")
GG_save_pdf = function(list, filename) {
  #start pdf
  pdf(filename)

  #loop
  for (p in list) {
    print(p)
  }

  #end pdf
  dev.off()

  invisible(NULL)
}

我尝试过其中一些解决方案,但没有成功。我做了更多的研究,找到了一个非常适合我的解决方案。它将我所有的图形保存在一个pdf文件中,每个图表放在一页上

library(ggplot2)


pdf("allplots.pdf",onefile = TRUE)
for(i in glist){
   tplot <- ggplot(df, aes(x = as.factor(class), y = value))
   print(tplot)
}
dev.off()
库(ggplot2)
pdf(“allplots.pdf”,onefile=TRUE)
因为(我用英语){

tplot一个使用
ggpubr
包(Github上的包,安装代码:
devtools::install_Github(“kassambara/ggpubr”)
)为我提供的解决方案

假设有4个图p1、p2、p3和p4

library(ggpubr)
multi.page <- ggarrange(p1,p2,p3,p4, nrow=1, ncol=1) # for one plot per page
multi.page[[1]] # for seeing the first plot
ggexport(multi.page, filename="my-plots.pdf")
库(ggpubr)

multi.page这是使用
ggplot2::ggsave()
gridExtra::marrangeGrob()
将ggplot对象列表导出到单个pdf文件的最优雅的解决方案

假设您使用
lappy()


这里有一个潜在的开始:
require(gridExtra);do.call(“grid.arrange”,p[[i]])
。这将在p[[i]]中绘制ggplot对象在一台设备中,将它们很好地排列。同时查看gridExtra软件包。我认为这会让您了解我的大部分情况,这会导致无法打开的损坏PDF。单独绘图看起来很好。任何提示?opts()在
ggplot2_2.2.1
R版本3.3.2
上对我都不起作用。请使用
+ggtitle>(cuts[i])
相反。@half pass,我也有同样的问题。在我的例子中,对ggplot2对象执行显式的
print()
解决了这个问题(即,将绘图保存到对象,然后在循环的每次迭代中打印出来)。
seq_-along(p)
可以用来代替
seq(length(p))
对于使用此方法遇到困难的其他人:请注意,此解决方案仅在ggplot对象位于列表中时有效。如果将它们作为单独的参数添加到grid.arrange,则pdf中会有多个页面,只有最后一个页面是您想要的组合。
library(ggpubr)
multi.page <- ggarrange(p1,p2,p3,p4, nrow=1, ncol=1) # for one plot per page
multi.page[[1]] # for seeing the first plot
ggexport(multi.page, filename="my-plots.pdf")
library(ggplot2)
library(gridExtra)
p <- lapply(names(mtcars), function(x) {
  ggplot(mtcars, aes_string(x)) + 
    geom_histogram()
})
ggsave(
   filename = "plots.pdf", 
   plot = marrangeGrob(p, nrow=1, ncol=1), 
   width = 15, height = 9
)