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

RGgplot2

R Problem Overview


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?

R Solutions


Solution 1 - R

How about this:

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

enter image description here

Solution 2 - R

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

Solution 3 - R

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

Solution 4 - R

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

Solution 5 - R

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMaiasauraView Question on Stackoverflow
Solution 1 - RJosh O'BrienView Answer on Stackoverflow
Solution 2 - RMichael OhlroggeView Answer on Stackoverflow
Solution 3 - RUweView Answer on Stackoverflow
Solution 4 - RMichael HarperView Answer on Stackoverflow
Solution 5 - RAdam WaringView Answer on Stackoverflow