Home > OS >  How can I add two y-axis labels using ggarrange for a 2x3 grid?
How can I add two y-axis labels using ggarrange for a 2x3 grid?

Time:04-05

I am trying to add y axis labels to my figure (a compilation of 6 figures in a 2x3 arrangement. The top 3 figures are part of one group, and the bottom 3 are part of another so I'd like to add two separate y axis labels at the start of each row. I am using the ggarrange function in {ggpubr}.

The image below is what I would like to have (i.e. the additional "Abundance" and "Presence/Absence" labels.

enter image description here

Below is the code I am using:

fig <- ggarrange(p1, p2 p3, p4, p5, p6, ncol=3, nrow=2, common.legend=FALSE, align="v", labels=c("A)","B)","C)","D)","E)","F)"))

Thank you in advance for your suggestions!

CodePudding user response:

It seems the thing you're trying to do is not super easy to do natively with ggpubr::ggarrange. I usually prefer {patchwork} but didn't find an easy solution there either. However, there is a feature request on github that contains some code which I was able to turn into a solution here.

library(tidyverse)
library(patchwork)

# borrowed from: https://github.com/thomasp85/patchwork/issues/43
add_global_label <- function(pwobj, Xlab = NULL, Ylab = NULL, Xgap = 0.03, Ygap = 0.03, ...) {
    ylabgrob <- patchwork::plot_spacer()
    if (!is.null(Ylab)) {
        ylabgrob <- ggplot()  
            geom_text(aes(x = .5, y = .5), label = Ylab, angle = 90, ...)  
            theme_void()
    }
    if (!is.null(Xlab)) {
        xlabgrob <- ggplot()  
            geom_text(aes(x = .5, y = .5), label = Xlab, ...)  
            theme_void()
    }
    if (!is.null(Ylab) & is.null(Xlab)) {
        return((ylabgrob   patchworkGrob(pwobj))   
            patchwork::plot_layout(widths = 100 * c(Ygap, 1 - Ygap)))
    }
    if (is.null(Ylab) & !is.null(Xlab)) {
        return((ylabgrob   pwobj)   
            (xlabgrob)  
            patchwork::plot_layout(heights = 100 * c(1 - Xgap, Xgap),
                                   widths = c(0, 100),
                                   design = "
                                   AB
                                   CC
                                   "
            ))
    }
    if (!is.null(Ylab) & !is.null(Xlab)) {
        return((ylabgrob   pwobj)   
            (xlabgrob)  
            patchwork::plot_layout(heights = 100 * c(1 - Xgap, Xgap),
                                   widths = 100 * c(Ygap, 1 - Ygap),
                                   design = "
                                   AB
                                   CC
                                   "
            ))
    }
    return(pwobj)
}

p <- mtcars %>% 
  ggplot(aes(disp, mpg))  
  geom_point(aes(color = factor(cyl)))  
  theme_classic()

top <- ((p p p)   
    plot_annotation(tag_levels = list(LETTERS[1:3]), tag_suffix = ")")) %>% 
  add_global_label(Ylab = "Top Row")

bottom <- ((p p p)   
    plot_annotation(tag_levels = list(LETTERS[4:6]), tag_suffix = ")")) %>% 
  add_global_label(Ylab = "Bottom Row")

top/bottom

Created on 2022-04-04 by the reprex package (v2.0.1)

CodePudding user response:

The {cowplot} package has a native solution to this problem, but it will probably take a little more fiddling to get the spacing right to avoid the label overlapping the y axis title.

library(tidyverse)
library(cowplot)

# make basic plot
p <- mtcars %>% 
  ggplot(aes(disp, mpg))  
  geom_point(aes(color = factor(cyl)))  
  theme_classic()

# compose top row of plots with labels
t <- plot_grid(
  p, p, p,
  labels = paste0(LETTERS[1:3], ")"),
  label_size = 12,
  nrow = 1) %>% 
  ggdraw()  
  draw_label("Top Row", size = 16, angle = 90, x = 0.01, y = 0.5)

# compose bottom row of plots with labels
b <- plot_grid(
  p, p, p,
  labels = paste0(LETTERS[4:6], ")"),
  label_size = 12,
  nrow = 1) %>% 
  ggdraw()  
  draw_label("Bottom Row", size = 16, angle = 90, x = 0.01, y = 0.5) 

# compose overall layout
plot_grid(t, b, nrow = 2)

Created on 2022-04-04 by the reprex package (v2.0.1)

  • Related