How do I arrange a variable list of plots using grid.arrange?
Asked Answered
S

5

120
library(ggplot2)
df <- data.frame(x=1:10, y=rnorm(10))
p1 <- ggplot(df, aes(x,y)) + geom_point()
plist <- list(p1,p1,p1,p1,p1)
# In my real example,a plot function will fit a ggplot to a list of datasets 
#and return a list of ggplots like the example above.

I'd like to arrange the plots using grid.arrange() in gridExtra.

How would I do this if the number of plots in plist is variable?

This works: grid.arrange(plist[[1]],plist[[2]],plist[[3]],plist[[4]],plist[[5]])

but I need a more general solution. thoughts?

Stefanstefanac answered 22/5, 2012 at 17:8 Comment(0)
T
178

How about this:

library(gridExtra)
n <- length(plist)
nCol <- floor(sqrt(n))
do.call("grid.arrange", c(plist, ncol=nCol))

enter image description here

Thermy answered 22/5, 2012 at 17:14 Comment(3)
This is nice, except the function can't handle NULL objects.Udell
Josh. I love you. Have spent 2 hours on this until now. Would you care to explain why this does not work:grid.arrange(plist[[1:length(plist)]], ncol = nCol)) I get an error like this: Error in hl.plots[[1:12]] : no such index at level 3 Thanks!Metaphysical
@Metaphysical There seem to be several things wrong with that code, but the one giving you the displayed error is probably caused by the same sort of error as is shown here: x <- list(1,2); x[[3:1]]. More broadly, use something like plist[...] rather than plist[[...]] to do your subsetting. And then use do.call(), which we have to use because grid.arrange() isn't set up to take a list as its first argument. Cheers, and best of luck!Neutrophil
S
54

You can use grid.arrange() and arrangeGrob() with lists as long as you specify the list using the grobs = argument in each function. E.g. in the example you gave:

library(ggplot2)
library(gridExtra)
df <- data.frame(x=1:10, y=rnorm(10))
p1 <- ggplot(df, aes(x,y)) + geom_point()
plist <- list(p1,p1,p1,p1,p1)

grid.arrange(grobs = plist, ncol = 2) ## display plot
ggsave(file = OutFileName, arrangeGrob(grobs = plist, ncol = 2))  ## save plot
Semifluid answered 15/3, 2017 at 19:17 Comment(1)
Took me wayyy too long to find this answer...thanks! This is the simplest.Cns
F
23

For the sake of completeness (and as this old, already answered question has been revived, recently) I would like to add a solution using the cowplot package:

cowplot::plot_grid(plotlist = plist, ncol = 2)

enter image description here

Font answered 16/3, 2017 at 5:54 Comment(3)
any idea why passing a list of plots using this code returns this error: Error in ggplot_to_gtable(x) : Argument needs to be of class "ggplot" or "gtable"Inodorous
How were the plots generated? Using the ggplot2 package or base graphics?Font
ggplot2. grid.arrange almost worked for me - but, turns out my list of plots is not getting populated. I posted the issue as a question: #43216762 . So, I am wondering if that could have been the issue for cowplot as wellInodorous
C
13

I know the question specifically states using the gridExtra package, but the wrap_plots function from the patchwork package is a great way to handle variable length list:

library(ggplot2)
# devtools::install_github("thomasp85/patchwork")
library(patchwork)

df <- data.frame(x=1:10, y=rnorm(10))
p1 <- ggplot(df, aes(x,y)) + geom_point()
plist <- list(p1,p1,p1,p1,p1)

wrap_plots(plist)

enter image description here

A useful thing about it is that you don't need to specify how many columns are required, and will aim to keep the numbers of columns and rows equal. For example:

plist <- list(p1,p1,p1,p1,p1,p1,p1,p1,p1,p1,p1,p1,p1)
wrap_plots(plist) # produces a 4 col x 4 row plot

Find out more about the patchwork package here

Charge answered 15/7, 2018 at 23:22 Comment(4)
I can't seem to install the package that you've mentioned hereAylward
Have you tried running the installation line which is commented out above devtools::install_github("thomasp85/patchwork")?Charge
Thank you, I didn't. I just tried to use the install from RStudio.Aylward
The package is not available on CRAN yet, so you have to install it via GitHub. Hopefully this won't be the case for much longer though as it is an excellent package!Charge
A
2

To fit all plots on one page you can calculate the number of columns and rows like this:

x = length(plots)

cols = round(sqrt(x),0)
rows = ceiling(x/cols)

As most multiple plotting functions have ncol and nrow as arguments you can just put these in there. I like ggarrange from ggpubr.

ggarrange(plotlist = plots, ncol=cols, nrow = rows)

This favours more rows than columns so reverse if you want the opposite. I.e. for 6 plots it will give 3 rows and 2 columns not the other way around.

Amphitheater answered 27/11, 2018 at 7:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.