rggplot2gridextraggpubr

Align legends in ggarrange


I have several different plots that I would like to display together, each type of plot on each row, sharing the same legend.

In order to share the same legend, I used grid.arrange().
To display each family of plots with the same legend, I used ggarrange() so that each family of plot is displayed on a specific row.

My issue is that the legend doesn't align when the legend name size is different.
In the following reproducible example, I have a short title and long one but they are not aligned (on the left).

I tried using the ggarrange option align='v' but it seems to exclusively work for plots, not for legends.

##### Loading libraries
library(ggplot2)
library(ggpubr)
library(gridExtra)
library(lemon)

##### Initiating objects
### COlors
dfCol1 <- data.frame(Groups=0:3,
                       col=c("grey80", "#87c5ff", "#477cad", "#113c63"))
dfCol2 <- data.frame(Groups=0:3,
                       col=c("grey80", "#87ffd5", "#47ad88", "#116349"))

### Legends
legend1 <- g_legend(ggplot(dfCol1, aes(x=2, y=1, fill=factor(Groups))) + 
                        geom_bar(stat="identity") + 
                        scale_fill_manual(values=dfCol1$col, name="short") + 
                        theme(legend.position="right", legend.text=element_text(size=7), legend.key.size=unit(0.4, 'cm')) + 
                        guides(fill=guide_legend(title.position="top", title.hjust=0.5)))
legend2 <- g_legend(ggplot(dfCol2, aes(x=2, y=1, fill=factor(Groups))) + 
                      geom_bar(stat="identity") + 
                      scale_fill_manual(values=dfCol2$col, name="veryLongTitle") + 
                      theme(legend.position="right", legend.text=element_text(size=7), legend.key.size=unit(0.4, 'cm')) + 
                      guides(fill=guide_legend(title.position="top", title.hjust=0.5)))

### Plots
barPlot1 <- 
  ggplot(dfCol1, aes(x=2, y=1, fill=factor(Groups))) + 
  geom_bar(stat="identity") + 
  scale_fill_manual(values=dfCol1$col, name="abc") + 
  guides(fill="none")
barPlot2 <- 
  ggplot(dfCol2, aes(x=2, y=1, fill=factor(Groups))) + 
  geom_bar(stat="identity") + 
  scale_fill_manual(values=dfCol2$col, name="abc") + 
  guides(fill="none")

##### Display plots
ggarrange(
  grid.arrange(barPlot1, barPlot1, barPlot1, nrow=1, legend1),
  grid.arrange(barPlot2, barPlot2, barPlot2, nrow=1, legend2),
  nrow=2
  )

enter image description here

I would like to achieve the following.

enter image description here

Thank you


Solution

  • One option would be to set left align your legends using legend.justification and to add some margin on the left of the legend box via legend.box.margin:

    library(ggplot2)
    library(ggpubr)
    library(gridExtra)
    library(lemon)
    
    ### Legends
    legend1 <- g_legend(ggplot(dfCol1, aes(x = 2, y = 1, fill = factor(Groups))) +
      geom_bar(stat = "identity") +
      scale_fill_manual(values = dfCol1$col, name = "short") +
      theme(
        legend.position = "right",
        legend.text = element_text(size = 7),
        legend.key.size = unit(0.4, "cm"),
        legend.justification = "left",
        legend.box.margin = margin(l = 1, unit = "cm")
      ) +
      guides(fill = guide_legend(title.position = "top", title.hjust = 0.5)))
    legend2 <- g_legend(ggplot(dfCol2, aes(x = 2, y = 1, fill = factor(Groups))) +
      geom_bar(stat = "identity") +
      scale_fill_manual(values = dfCol2$col, name = "veryLongTitle") +
      theme(
        legend.position = "right",
        legend.text = element_text(size = 7),
        legend.key.size = unit(0.4, "cm"),
        legend.justification = "left",
        legend.box.margin = margin(l = 1, unit = "cm")
      ) +
      guides(fill = guide_legend(title.position = "top", title.hjust = 0.5)))
    
    ### Plots
    barPlot1 <-
      ggplot(dfCol1, aes(x = 2, y = 1, fill = factor(Groups))) +
      geom_bar(stat = "identity") +
      scale_fill_manual(values = dfCol1$col, name = "abc") +
      guides(fill = "none")
    barPlot2 <-
      ggplot(dfCol2, aes(x = 2, y = 1, fill = factor(Groups))) +
      geom_bar(stat = "identity") +
      scale_fill_manual(values = dfCol2$col, name = "abc") +
      guides(fill = "none")
    
    ##### Display plots
    ggarrange(
      grid.arrange(barPlot1, barPlot1, barPlot1, nrow = 1, legend1),
      grid.arrange(barPlot2, barPlot2, barPlot2, nrow = 1, legend2),
      nrow = 2
    )
    

    enter image description here