rggplot2patchwork

Merging two y-axes titles in patchwork


Any ideas as to how I can "merge" two identical y-axes titles into one, and then place this y-axis title in the middle between the plot? I have succeded in merging legends by using plot_layout(guides = "collect") but I cannot seem to find anything similar for axes. In this case I would merge the two axes titles called disp_disp_disp into one.

enter image description here

mtcars

library(ggplot2)
library(patchwork)

p1 <- ggplot(mtcars) + 
  geom_point(aes(mpg, disp)) + 
  labs(x = "mpg", y = "disp_disp_disp_disp_disp")

p2 <- ggplot(mtcars) + 
  geom_boxplot(aes(gear, disp, group = gear)) + 
  labs(x = "gear", y = "disp_disp_disp_disp_disp")

p3 <- ggplot(mtcars) + 
  geom_point(aes(hp, wt, colour = mpg)) + 
  ggtitle('Plot 3')

p1 / (p2 | p3)

Solution

  • I guess it would be slightly easier to strip out the y axis title before the plot is built then draw it back on after it is plotted:

    library(ggplot2)
    library(patchwork)
    
    p1 <- ggplot(mtcars) + 
      geom_point(aes(mpg, disp)) + 
      labs(x = "mpg", y = "disp_disp_disp_disp_disp")
    
    p2 <- ggplot(mtcars) + 
      geom_boxplot(aes(gear, disp, group = gear)) + 
      labs(x = "gear", y = "disp_disp_disp_disp_disp")
    
    p3 <- ggplot(mtcars) + 
      geom_point(aes(hp, wt, colour = mpg)) + 
      ggtitle('Plot 3')
    
    ylab <- p1$labels$y
    p1$labels$y <- p2$labels$y <- " "
    
    p1 / (p2 | p3)
    grid::grid.draw(grid::textGrob(ylab, x = 0.02, rot = 90))
    

    enter image description here

    Another option if you want to avoid getting your hands dirty with grobs altogether is to specify a text-only ggplot and add that as your axis text:

    p4 <- ggplot(data.frame(l = p1$labels$y, x = 1, y = 1)) +
          geom_text(aes(x, y, label = l), angle = 90) + 
          theme_void() +
          coord_cartesian(clip = "off")
    
    p1$labels$y <- p2$labels$y <- " "
    
    p4 + (p1 / (p2 | p3)) + plot_layout(widths = c(1, 25))
    

    enter image description here

    This behaves a bit better on resizing too.