Add a common Legend for combined ggplots

common legend for multiple plots in r
ggplot add legend manually
ggplot legend
arrangegrob
grid_arrange_shared_legend
grid.arrange list of plots
cowplot shared legend
grid.arrange title

I have two ggplots which I align horizontally with grid.arrange. I have looked through a lot of forum posts, but everything I try seem to be commands that are now updated and named something else.

My data looks like this;

# Data plot 1                                   
        axis1     axis2   
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.417117 -0.002592
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.186860 -0.203273

# Data plot 2   
        axis1     axis2
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988

#And I run this:
library(ggplot2)
library(gridExtra)


groups=c('group1','group2','group3','group4','group1','group2','group3','group4')

x1=data1[,1]
y1=data1[,2]

x2=data2[,1]
y2=data2[,2]

p1=ggplot(data1, aes(x=x1, y=y1,colour=groups)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

p2=ggplot(data2, aes(x=x2, y=y2,colour=groups)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

#Combine plots
p3=grid.arrange(
p1 + theme(legend.position="none"), p2+ theme(legend.position="none"), nrow=1, widths = unit(c(10.,10), "cm"), heights = unit(rep(8, 1), "cm")))

How would I extract the legend from any of these plots and add it to the bottom/centre of the combined plot?

Update 2015-Feb

See Steven's answer below


df1 <- read.table(text="group   x     y   
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.417117 -0.002592
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.186860 -0.203273",header=TRUE)

df2 <- read.table(text="group   x     y   
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988",header=TRUE)


library(ggplot2)
library(gridExtra)

p1 <- ggplot(df1, aes(x=x, y=y,colour=group)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8) + theme(legend.position="bottom")

p2 <- ggplot(df2, aes(x=x, y=y,colour=group)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

#extract legend
#https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
g_legend<-function(a.gplot){
  tmp <- ggplot_gtable(ggplot_build(a.gplot))
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
  legend <- tmp$grobs[[leg]]
  return(legend)}

mylegend<-g_legend(p1)

p3 <- grid.arrange(arrangeGrob(p1 + theme(legend.position="none"),
                         p2 + theme(legend.position="none"),
                         nrow=1),
             mylegend, nrow=2,heights=c(10, 1))

Here is the resulting plot:

ggplot2 - Easy way to mix multiple graphs on the same page, Add a common legend for multiple ggplot2 graphs​​ This can be done in four simple steps : Create the plots : p1, p2, …. Save the legend of the plot p1 as an external graphical element (called a “grob” in Grid terminology) Remove the legends from all plots. In order to draw our two plots side-by-side and in order to add a common legend, we can use the grid.arrange and arrangeGrob functions of the gridExtra package: # Draw plots with shared legend grid.arrange(arrangeGrob (ggp1, ggp2, ncol = 2), shared_legend, nrow = 2, heights = c (10, 1)) Figure 1 illustrates the output of the previous R code.

You may also use ggarrange from ggpubr package and set "common.legend = TRUE":

library(ggpubr)

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data = dsamp, colour = clarity)
p2 <- qplot(cut, price, data = dsamp, colour = clarity)
p3 <- qplot(color, price, data = dsamp, colour = clarity)
p4 <- qplot(depth, price, data = dsamp, colour = clarity) 

ggarrange(p1, p2, p3, p4, ncol=2, nrow=2, common.legend = TRUE, legend="bottom")

Add a common Legend for combined ggplots, To add a common legend for the combined plots, you can do the following: library(ggplot2) library(gridExtra) library(grid) groups=c('group1','group2','group3','group4','group1','group2','group3','group4') df1 <- read.table(text="group x y. group1 -0.212201 0.358867. group2 -0.279756 -0.126194. group3 0.186860 -0.203273. How to add a common legend to a side-by-side graph with the ggplot2 package in the R programming language. Add Common Legend to Combined ggplot Plots in R (Example) | ggplot2 & gridExtra

Roland's answer needs updating. See: https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs

This method has been updated for ggplot2 v1.0.0.

library(ggplot2)
library(gridExtra)
library(grid)


grid_arrange_shared_legend <- function(...) {
    plots <- list(...)
    g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
    legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
    lheight <- sum(legend$height)
    grid.arrange(
        do.call(arrangeGrob, lapply(plots, function(x)
            x + theme(legend.position="none"))),
        legend,
        ncol = 1,
        heights = unit.c(unit(1, "npc") - lheight, lheight))
}

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data=dsamp, colour=clarity)
p2 <- qplot(cut, price, data=dsamp, colour=clarity)
p3 <- qplot(color, price, data=dsamp, colour=clarity)
p4 <- qplot(depth, price, data=dsamp, colour=clarity)
grid_arrange_shared_legend(p1, p2, p3, p4)

Note the lack of ggplot_gtable and ggplot_build. ggplotGrob is used instead. This example is a bit more convoluted than the above solution but it still solved it for me.

Add Common Legend to Combined ggplot2 Plots in R (Example), How to add a shared legend to a side-by-side graph created with the ggplot2 package - R programming example - Reproducible R syntax. To add a common legend for the combined plots, you can do the following: library (ggplot2) library (gridExtra) library (grid) groups=c ('group1','group2','group3','group4','group1','group2','group3','group4') df1 <- read.table (text="group x y. group1 -0.212201 0.358867.

A new, attractive solution is to use patchwork. The syntax is very simple:

library(ggplot2)
library(patchwork)

p1 <- ggplot(df1, aes(x = x, y = y, colour = group)) + 
  geom_point(position = position_jitter(w = 0.04, h = 0.02), size = 1.8)
p2 <- ggplot(df2, aes(x = x, y = y, colour = group)) + 
  geom_point(position = position_jitter(w = 0.04, h = 0.02), size = 1.8)

combined <- p1 + p2 & theme(legend.position = "bottom")
combined + plot_layout(guides = "collect")

Created on 2019-12-13 by the reprex package (v0.2.1)

How to Combine Multiple GGPlots into a Figure, Create some basic plots; Combine the plots on one page; Change column and row span of a plot; Use shared legend for combined ggplots; Combine the plots  Use shared legend for combined ggplots. To place a common unique legend in the margin of the arranged plots, the function ggarrange() [in ggpubr] can be used with the following arguments: common.legend = TRUE: place a common legend in a margin; legend: specify the legend position. Allowed values include one of c(“top”, “bottom”, “left”, “right”)

I suggest using cowplot. From their R vignette:

# load cowplot
library(cowplot)

# down-sampled diamonds data set
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]

# Make three plots.
# We set left and right margins to 0 to remove unnecessary spacing in the
# final plot arrangement.
p1 <- qplot(carat, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt"))
p2 <- qplot(depth, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt")) + ylab("")
p3 <- qplot(color, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt")) + ylab("")

# arrange the three plots in a single row
prow <- plot_grid( p1 + theme(legend.position="none"),
           p2 + theme(legend.position="none"),
           p3 + theme(legend.position="none"),
           align = 'vh',
           labels = c("A", "B", "C"),
           hjust = -1,
           nrow = 1
           )

# extract the legend from one of the plots
# (clearly the whole thing only makes sense if all plots
# have the same legend, so we can arbitrarily pick one.)
legend_b <- get_legend(p1 + theme(legend.position="bottom"))

# add the legend underneath the row we made earlier. Give it 10% of the height
# of one plot (via rel_heights).
p <- plot_grid( prow, legend_b, ncol = 1, rel_heights = c(1, .2))
p

Working with legends, Shared legend across multiple plot; Shared legend with grid.arrange; More examples actual plot: reposition_legend; Combine multiple plots, but use only one legend: ggplot2 by default places the legend in the margin of the entire plot. For this, use theme(legend.box.background) to put a background  Figure 2: ggplot2 Plot with Legend. As you can see based on Figure 2, we just added a legend to our plot, by moving the col argument within the aes function in the first line of the code. Note that the colors are different compared to Figure 1, since the aes function is using the default colors of the ggplot2 package.

Add Common Legend to Combined ggplot Plots in R (Example , How to add a common legend to a side-by-side graph with the ggplot2 package in the R Duration: 7:07 Posted: Feb 26, 2020 Use common legend for combined ggplots. To place a common unique legend in the margin of the arranged plots, the function ggarrange() [in ggpubr] can be used with the following arguments: common.legend = TRUE: place a common legend in a margin; legend: specify the legend position. Allowed values include one of c(“top”, “bottom”, “left

ggplot2 wiki that allows multiple plots to share a legend., Extract legend, combines plots using arrangeGrob / grid.arrange, and places legend in a margin. arguments that are not defined for grid_arrange_shared_legend . ggplot2 objects have their legends hidden. Logical, when TRUE (default), draws combined plot on a new page. Add the following code to your website. Recommend:ggplot2 - R: common legend for multiple plots with different scales. legend for all the plots. I read this answer from this question which explained things in a very nice way. Add a common Legend for combined ggplots but the problem is that the idea mentioned here will take the legend of p1. in my case, the

grid_arrange_shared_legend: Share a legend between multiple , Add Tags to combined plot: Patchwork sometimes you might want to put legends in a common place instead of right next to each plot. We can  To put a legend inside the plot, you supply legend.position as coordinates on a relative scale that runs from [0,0] in the lower left to [1,1] in the upper right. You'll usually want to use legend.justification, too — this tells ggplot which part of the legend box should align with the coordinates.

Comments
  • I occasionally have this problem. If you don't want to facet the plot the easiest solution I know is just to save one with a legend then use Photoshop/Ilustrator to paste it onto the blank legend plots. Inelegant I know -- but practical quick and easy.
  • @StephenHenderson That's an answer. Facet or post-process with gfx editor.
  • both answers point to the same wiki page which can be updated as new versions of ggplot2 break the code.
  • More than six year later this answer solved my problem. Thanks!
  • Is it possible that this doesn't work inside a shiny application (or flexdashboard) with renderPlot()? It works perfectly fine in a normal R script with normal plots. But when I do the exact same thing with plots made with renderPlot() in my flexdashboard, nothing appears.
  • Thank you for this - I think this was by far the easiest solution for what I was looking
  • This is awesome! Thank you!
  • @Tingolfin I have had to sometimes wrap print(ggarrangeobject) around one of my ggarrange objects when I needed it to be plotted by some other function, that may be similar to the solution for your renderPlot()?
  • common.legend = TRUE is all that I need!
  • Hi, I have 6 plots, and I would like to arrange the 6 plots as 2 row × 3 col and draw the legend on the top, so how to change the function grid_arrange_shared_legend? Thank you!
  • @just_rookie did you find a solution how to change the function so that one can use different ncol and nrow arrangements instead of only ncol = 1?
  • Hi, i tried this solution, it works good, however when printing it, i got 2 pdf pages instead of only 1, the first is blank while the later contains my plot, why i got such behavior ? thanks,