Add Common Legend to Combined ggplot2 Plots in R (Example)

 

In this article, I’ll illustrate how to create a shared legend for multiple ggplot2 graphics in the R programming language.

Table of contents:

Let’s get started…

 

Example Data

In the example of this R tutorial, we’ll use the following example data frames:

# Create example data
set.seed(35753)
data1 <- data.frame(x = round(runif(2000), 2),
                    y = round(runif(2000), 2),
                    group = c(rep("A", 1000), rep("B", 1000)))
data2 <- data.frame(x = round(rnorm(2000), 2),
                    y = round(rnorm(2000), 2),
                    group = c(rep("A", 1000), rep("B", 1000)))

The previous R code creates two data frames. Both of these data frames contain the three columns x, y, and a grouping variable.

Furthermore, we need to install and load the ggplot2 package to draw our data:

# Install and load ggplot2 package
install.packages("ggplot2")
library("ggplot2")

Now, we can move on to the plotting of the data…

Example 1: Add Shared Legend to ggplot2 Plots Using patchwork Package

Example 1 explains how to merge multiple ggplot2 legends using the patchwork package.

First, we have to install and load the package:

# Install and load patchwork package
install.packages("patchwork")
library("patchwork")

Furthermore, we have to create two plot objects containing our ggplot2 plots separately:

ggp1 <- ggplot(data1, aes(x = x, y = y, group = group, col = group)) +
  geom_point()
ggp2 <- ggplot(data2, aes(x = x, y = y, group = group, col = group)) +
  geom_point()

In the next step, we can use the plot_layout function of the patchwork package to create a grid of plots with a common legend:

ggp1 + ggp2 + plot_layout(guides = "collect")

 

shared legend ggplot2 & patchwork plot in r

Figure 1: Two ggplot2 Plots with a Common Legend Using the patchwork Package.

 

As you can see, the previous R code has created a shared legend on the right side of the plot.

 

Example 2: Add Shared Legend to ggplot2 Plots Using gridExtra Package

Alternatively to the patchwork package, we can also use the gridExtra package to draw a grid of ggplot2 plots with a shared legend.

First, let’s install and load the gridExtra package:

# Install and load gridExtra package
install.packages("gridExtra")
library("gridExtra")

Next, we need to create two (or more) plots using the ggplot2 package. The following R syntax stores two ggplot2 graphics in the data objects ggp1 and ggp2. Note that these two plots do not show a legend:

# Create two plots without legends
ggp1 <- ggplot(data1, aes(x = x, y = y, group = group, col = group)) +
  geom_point() +
  theme(legend.position = "none")
ggp2 <- ggplot(data2, aes(x = x, y = y, group = group, col = group)) +
  geom_point() +
  theme(legend.position = "none")

Now, we need to create one of these plots again, but this time with the legend that we want to show later on in the side-by-side graphic. In this case, we are creating a legend at the bottom of the plots. However, you may modify this legend to your specific needs.

# Create plot with legend
ggp1_legend <- ggplot(data1, aes(x = x, y = y, group = group, col = group)) +
  geom_point() +
  theme(legend.position = "bottom")

Next, we define our own function, which enables us to extract the legend of the previously created plot. Note that the code for this function is based on this Stack Overflow thread.

# Create user-defined function, which extracts legends from ggplots
extract_legend <- function(my_ggp) {
  step1 <- ggplot_gtable(ggplot_build(my_ggp))
  step2 <- which(sapply(step1$grobs, function(x) x$name) == "guide-box")
  step3 <- step1$grobs[[step2]]
  return(step3)
}

We can now apply our function to our ggplot2 plot as shown in the following R syntax:

# Apply user-defined function to extract legend
shared_legend <- extract_legend(ggp1_legend)

Our legend is now stored in the data object shared_legend. 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. As you can see, we created a graph with a shared legend below the two plots.

 

shared legend ggplot2 plot in r

Figure 1: Two ggplot2 Plots with a Common Legend in R.

 

In this example, we created a common legend for two scatterplots. However, please note that we could also use other types of ggplot2 plots (e.g. barplots, heatmaps, line graphs, boxplots, and so on…) and we could use any number of plots we want.

Do you want to know more about the creation of shared legends in grid-plots using the gridExtra package? Then you may want to watch the following video of my YouTube channel. In the video, I’m explaining the topics of this article.

 

 

Further Resources & Summary

You might want to have a look at some of the other tutorials of www.statisticsglobe.com. Some other tutorials are shown below:

 

In this tutorial you learned how to share a legend for multiple combined ggplot2 plots in R programming. Don’t hesitate to tell me about it in the comments section, in case you have further questions.

 

Subscribe to the Statistics Globe Newsletter

Get regular updates on the latest tutorials, offers & news at Statistics Globe.
I hate spam & you may opt out anytime: Privacy Policy.


12 Comments. Leave new

  • Excellent on the legend extraction. What would be the code to have the legend at the top? I have manipulated the provided code but no luck

    Reply
    • Hi Tim,

      Thanks for the great question! You would have to modify the grid.arrange() code as follows:

      grid.arrange(shared_legend,
                   arrangeGrob(ggp1, ggp2, ncol = 2),
                   nrow = 2, heights = c(1, 10))

      I hope that helps!

      Joachim

      Reply
  • Thank you so much for code to get the legend at the top of the Grob. However, I am having trouble creating the Grob for exporting to a PNG file. Here is code I am using:
    P3<-(arrangeGrob(shared_legend, P1 + theme(legend.position="none"), P2, ncol = 3), heights = c(0.5, 10))

    I get the error stating ("Unexpected token ','"). I think the code does not like the "," after shared_legend

    I am creating the P3 file so that I can export the PNG file with this code
    ggsave(P3,file="c:/destination/P3.png", width=9.5, height=6.5)

    Please advise. Unless you have a different method to export the Grob as a PNG file?

    Reply
  • Muhammad Usman
    December 30, 2020 7:26 pm

    Dear Joan, Thank you for your tutorial for making singlle ledend for multiple figures. It is good for discrete values. How to modify this code, If I have continous values inform of matrices and I want to make single legends for two different matrices have different scale range.

    Reply
  • Hi Joachim,
    thank you so much for your helpful tutorial video on how extracting the legend. Is it possible to modify your code to put the legend on the right of the graphs?

    Reply
    • Hey Farzaneh,

      Thanks a lot, glad you like it!

      Yes, this is possible. You have to remove this line of code when creating the legend:

      theme(legend.position = "bottom")

      i.e.

      ggp1_legend <- ggplot(data1, aes(x = x, y = y, group = group, col = group)) +
        geom_point()

      And then you have to modify the last line of code when creating the final graphic:

      grid.arrange(arrangeGrob(ggp1, ggp2, shared_legend, ncol = 3, widths = c(2, 2, 1)))

      I hope that helps!

      Joachim

      Reply
  • Hi Joachim,
    Thank you for the tips shared in your articles. However, I have been trying to find how to add external elements to the legend (such as the meaning of trend lines or linear models). Do you have any tips for this? I haven’t found anything that explains how to do this using ggplot

    Thanks

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Top