rggplot2patchwork

How to properly combine two ggplots and properly align axis and strips/titles?


I need to combine two ggplots. They should have labels (A, B, and C) as for being used in a publication. The first plot is a facet_wrap(). This is my code:

library(ggplot2)
library(dplyr)
library(patchwork)

# First plot with facets
p1 <- ggplot(mtcars %>%
               filter(cyl %in% c("4", "6")) %>%
               mutate(cyl_label=paste0("label_", cyl)), 
             aes(x=mpg, y=wt)) +
  geom_point() +
  theme_bw() +
  theme(aspect.ratio = 2,
        strip.text.x = element_text(hjust = 0, colour = "black", size = 14,
                                    margin = unit(c(t=0.15,r=0,b=0.15,l=0), "cm")),
    strip.background = element_blank()) +
  facet_wrap(~ cyl_label, 
             labeller = labeller(cyl_label = c(label_4 = "(A) First plot",
                                               label_6 = "(B) Second plot"))) +
  theme(aspect.ratio = 2)

# Second plot with title
p2 <- ggplot(mtcars, aes(x=hp, y=wt)) +
  geom_point() +
  ggtitle("(C) Third plot") +
  theme_bw() +
  theme(
    aspect.ratio = 1, 
    plot.title = element_text(hjust = 0, colour = "black", size = 14,
                              margin = unit(c(t=0.15,r=0,b=0.15,l=0), "cm")))

# Combine plots side by side
combined_plot <- p1 + p2 + 
  plot_layout(ncol = 2) 

This is the plot I got:

The combined plot have two issues:

  1. The "(C)" label is not aligned, and
  2. the y dimension of both plots is not aligned.

Interestingly, the second plot by itself has the title in the correct position:


Solution

  • patchwork tries to makes the titles line up with titles and facets line up with facets. Since you are trying to mix and match, that's confusing. So why not use a facet for the third label

    p1 <- ggplot(mtcars %>%
                   filter(cyl %in% c("4", "6")) %>%
                   mutate(cyl_label=paste0("label_", cyl)), 
                 aes(x=mpg, y=wt)) +
      geom_point() +
      theme_bw() +
      theme(
        strip.text.x = element_text(hjust = 0, colour = "black", size = 14, margin = unit(c(t=0.15,r=0,b=0.15,l=0), "cm")),
        strip.background = element_blank()
      ) +
      facet_wrap(~ cyl_label, 
                 labeller = labeller(cyl_label = c(label_4 = "(A) First plot", label_6 = "(B) Second plot")))
    
    p1
    
    # Second plot with title
    p2 <- ggplot(mtcars, aes(x=hp, y=wt)) +
      geom_point() +
      theme_bw() +
      theme(
        strip.text.x = element_text(hjust = 0, colour = "black", size = 14, margin = unit(c(t=0.15,r=0,b=0.15,l=0), "cm")),
        strip.background = element_blank()
      ) +
      facet_wrap(~"(C) Third Plot") 
    
    p2
    
    # Combine plots side by side
    combined_plot <- p1 + p2 + 
      plot_layout(ncol = 2) 
    
    combined_plot
    

    enter image description here

    Is the aspect ratio part required? It seems to interfere a bit with getting the bounding boxes to line up with each other. I wasn't sure if you were just trying to squeeze the first two plots together or if you needed a particular aspect ratio.