6

I generate a list of ggplot objects inside a loop as follows:

myPlots = list()
for(i in 1:length(maturities)){
  myPlots[[i]] <- ggplot(deltaIR.df, aes(sample = deltaIR.df[,i])) + 
                  stat_qq() + stat_qq_line() + 
                  labs(title=maturities[i],
                  x = "Theoretical (Normal)", 
                  y = "Empirical Distribution")
}

Depending on the dataset, there could be between 4 and 10 plots in myPlots. I now want to print them on one page in two rows, and have tried various methods with varying degrees of success. The most promising approach is

library(ggpubr)
grid.arrange(myPlots[[1]], myPlots[[2]], myPlots[[3]], myPlots[[4]], 
             myPlots[[5]], myPlots[[6]], myPlots[[7]], myPlots[[8]], nrow = 2)

This clearly works, but requires me to enumerate all the objects, and I don't know how many objects there will be. I tried to simplify this by writing

ggarrange(myPlots, nrow = 2)

but received a warning message:

Warning message:
In as_grob.default(plot) : Cannot convert object of class list into a grob.

What am I doing wrong, and how can I fix this? Ideally, a simple, single, line of code will print all the plots stored in myPlots in two rows.

Thanks in advance

Thomas Philips

Thomas Philips
  • 935
  • 2
  • 11
  • 22

4 Answers4

7

ggpubr::ggarrange is just a wrapper around cowplot::plot_grid().

But if you want to stay with ggpubr, then you can keep using ggarrange. And you need to save all your plots in a list, and use plotlist argument.

library(ggpubr)
library(ggplot2)
library(purrr)

myplot <- function(color){
    ggplot(iris,aes(x = Sepal.Length, y = Sepal.Width)) + geom_point(color = color)
}
plot_list <- map(c("red","green","blue","black","orange"),myplot)


ggarrange(plotlist = plot_list,nrow = 2,ncol = ceiling(length(plot_list)/2))

enter image description here

yusuzech
  • 5,896
  • 1
  • 18
  • 33
3

You can use cowplot::plot_grid to obtain that.

Here is an example with fake data:

##List with ten datasets
set.seed(3)
l <- lapply(1:10, function(i)tibble(
  letter = letters,
  values = rnorm(26)
))

##List of ten different plots
plot_list_1 <- lapply(l, function(i)i %>% ggplot(aes(x = values)) + geom_density())

##Display ten plots
cowplot::plot_grid(plotlist = plot_list_1,nrow = 2)

##Display four plots
cowplot::plot_grid(plotlist = plot_list_1[1:4],nrow = 2)

enter image description here

enter image description here

Henry Cyranka
  • 2,970
  • 1
  • 16
  • 21
  • Hallelujah - works like a charm! It didn't strike me that I had to explicitly set plotlist = myPlots and to declare both nrow and ncol. As soon as i wrote ```ggarrange(plotlist = myPlots, nrow = 2, ncol = ceiling(length(myPlots)/2))```, I got exactly what I was looking for. Thanks a mill for the quick response!!! – Thomas Philips Sep 26 '19 at 20:52
  • No problem. Would you mind approving the answer and upvoting it? Thank you – Henry Cyranka Sep 26 '19 at 20:53
  • Done!. One last question. When I type ```ggarrange(plotlist = myPlots, nrow = 2, ncol = ceiling(length(myPlots)/2))``` in the Console in RStudio, I get the 8 graphs I expect. However, if I Source the entire script, no figures are thrown up. Even more confusingly, if I put my cursor on the line and click run, I get the plots. Is there an additional command I need to execute so that it displays when I source the script? – Thomas Philips Sep 26 '19 at 21:07
  • This is probably an issue with the devices (the plot windows). Make sure that you close all devices using dev.off() – Henry Cyranka Sep 26 '19 at 21:10
  • I start the script with dev.off() ``` rm(list = ls(all = TRUE)) #Clear all objects in the workspace if(!is.null(dev.list()["RStudioGD"])) dev.off() #Clear all graphs ``` but it fails to display the results of ```garrange```. When I ran the line by itself, for the first time I got a warning: ``` Warning message: In doTryCatch(return(expr), name, parentenv, handler) : display list redraw incomplete ``` Does this ring a bell? – Thomas Philips Sep 26 '19 at 21:53
0

this works for me and its similar to the code you already use.

library(gridExtra)    
grid.arrange(grobs=myPlots, nrow=2)
0

just add "plotlist" before 'myPlots' to claim myPlots is a list, as the Documentation said

ggarrange(plotlist = myPlots, nrow = 2)