Align multi-figure ggplots with patchwork and single legend

Viewed 407

I am using patchwork to create a multi-plot figure in R. They share one legend, so I am including the legend at the top right panel using ggpubr::get_legend() (note: I cannot use patchwork::plot_layout() because the legends have different underlying values).

Base plot

library(ggplot2)
library(patchwork)
library(ggpubr)

p <- ggplot(data = mtcars %>% mutate(cyl = as.factor(cyl)),
                mapping = aes(x = wt, y = mpg, group = cyl, color = cyl)) +
   geom_smooth(method = "lm")

When there are 6 of the same plots on the top and bottom rows, the plots align:

(p | p | p | p | p | p) /
   (p | p | p | p | p | p) &
   theme(legend.position = "none")

enter image description here

When the 5th plot on the top row is a legend, they do not align:

leg <- as_ggplot(get_legend(p))

(p | p | p | p | p | leg) /
   (p | p | p | p | p | p) &
   theme(legend.position = "none")

enter image description here

2 Answers

One option to achieve your desired result would be to put all plots including the legend in one list and make use of patchwork::wrap_plots:

library(ggplot2)
library(patchwork)
library(ggpubr)

p <- ggplot(data = mtcars %>% mutate(cyl = as.factor(cyl)),
            mapping = aes(x = wt, y = mpg, group = cyl, color = cyl)) +
  geom_smooth(method = "lm")

leg <- as_ggplot(get_legend(p))

p_list <- lapply(1:12, function(x) if (x == 6) leg else p)
wrap_plots(p_list, nrow = 2) &
  theme(legend.position = "none")

This can also be done with grid.arrange() from the gridExtra package:

library(gridExtra)

grid.arrange(p, p, p, p, p, leg,
             p, p, p, p, p, p,
             nrow = 2)
Related