12

Based on the code and data below, is it possible to have common legend labels without having to remove xlab and ylab from the ggplot codes using patchwork?

The reason why I ask this is because I have lots of ggplots and so I don't find it ideal to remove xlab and ylab from each of the ggplots and then use the method in the code. I know I can use ggarrange but ggpubr is much slower than patchwork.

Sample data and code:

library(tidyverse)
library(patchwork)
library(gridextra)

gg1 = ggplot(mtcars) +
  aes(x = cyl, y = disp) +
  geom_point() +
  xlab("Disp") +
  ylab("Hp // Cyl") +
  theme(axis.title = element_blank())

gg2 = gg1 %+% aes(x = hp) +
  xlab("Disp") +
  ylab("Hp // Cyl")

# This method still keeps the individual axis labels.
p = gg1 + gg2
gt = patchwork::patchworkGrob(p)
gridExtra::grid.arrange(gt, left = "Disp", bottom = "Hp // Cyl")
1
  • 1
    Is gg1 meant where you refer to p1? Commented Jul 19, 2022 at 20:12

2 Answers 2

18
Update

With patchwork >= 1.2.0 it is now possible to collect the axis titles using the new axis_title= parameter of plot_layout(), i.e. similar to guides="collect" one can now set axis_title="collect" to add a shared axis titles.

library(ggplot2)
library(patchwork)

packageVersion("patchwork")
#> [1] '1.2.0'

gg1 <- ggplot(mtcars) +
  aes(x = cyl, y = disp) +
  geom_point() +
  xlab("Disp") +
  ylab("Hp // Cyl")

gg2 <- gg1 %+% aes(x = hp) +
  xlab("Disp") +
  ylab("Hp // Cyl")

gg1 + gg2 +
  plot_layout(axis_titles = "collect")

Original answer

One possible option to have a common axis title without having to remove xlab and ylab from the ggplot code would be to remove the axis labels via & labs(...) when creating the patch and adding a common axis title as a separate plot where I made use of cowplot::get_plot_component to create the axis title plot:

library(ggplot2)
library(patchwork)
library(cowplot)


gg1 <- ggplot(mtcars) +
  aes(x = cyl, y = disp) +
  geom_point() +
  xlab("Disp") +
  ylab("Hp // Cyl") +
  theme(axis.title = element_blank())

gg2 <- gg1 %+% aes(x = hp) +
  xlab("Disp") +
  ylab("Hp // Cyl")

gg_axis <- cowplot::get_plot_component(ggplot() +
  labs(x = "Hp // Cyl"), "xlab-b")

(gg1 + gg2 & labs(x = NULL, y = NULL)) / gg_axis + plot_layout(heights = c(40, 1))

UPDATE To add a y-axis it's basically the same. To get the left y axis title we have to use ylab-l. Additionally, we have to add a spacer to the patch. IMHO the best approach in this case would be to put all components in a list and use the design argument of plot_layout to place them in the patch.

p <- ggplot() + labs(x = "Hp // Cyl", y = "Disp")
x_axis <- cowplot::get_plot_component(p, "xlab-b")
y_axis <- cowplot::get_plot_component(p, "ylab-l")

design = "
DAB
#CC
"

list(
  gg1 + labs(x = NULL, y = NULL), # A
  gg2 + labs(x = NULL, y = NULL), # B
  x_axis,# C
  y_axis # D
) |> 
  wrap_plots() + 
  plot_layout(heights = c(40, 1), widths = c(1, 50, 50), design = design)
Sign up to request clarification or add additional context in comments.

3 Comments

Cheers, so for the y-axis label should I add labs(x = "Hp // Cyl"), "xlab-b", y = "Disp", "ylab-b" ?
A bit more work than that. :) See my update.
Good day Stefan, the code is not seem to be working as intended with my code, the code and data is the same as in this question. Should I edit my question and add the code and data here?
3

You could also just make a blank plot with the label you need, then use plotlayout() with a high width ratio to combine.

blanklabelplot<-ggplot()+labs(y="your title")+theme_classic()+ 
  guides(x = "none", y = "none")
  
blanklabelplot+plot+ plot_layout(widths=c(1,1000))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.