Skip to content

ggplot2: Two Or More Plots Sharing The Same Legend

May 26, 2009

Sometimes there is a need to combine two or more different plots that have a common legend. If these plots were placed in the same window, then one of the legends would be redundant.

This post shows how two ggplot2 plots can share the same legend. The solution was inspired by a thread on the ggplot2 mailinglist.

Let’s assume that we want to plot the following two relationships in the R’s built-in dataset mtcars, and use colour to display the cars with varying number of cylinders on the graph.:

a) Miles/(US) gallon – Gross horsepower – Number of cylinders

b) Weight (lb/1000) – Displacement (cu.in.) – Number of cylinders

Using qplot we first create the two plots, and make sure that the legends are not displayed by specifying opts(legend.position = "none"). Next we create a plot that displays only the legend, all the other elements of the plot are removed by opts(keep= "legend_box"). Finally, the two plots and the legend plot are placed onto a page with the help of grid.layout(), resulting in two plots with different axis sharing the same legend.

> library(ggplot2)
> p <- qplot(data = mtcars, mpg, hp, geom = "point",
     colour = cyl)
> p1 <- p + opts(legend.position = "none")
> p2 <- qplot(data = mtcars, wt, disp, geom = "point",
     colour = cyl) + opts(legend.position = "none")
> legend <- p + opts(keep = "legend_box")
> Layout <- grid.layout(nrow = 2, ncol = 2, widths = unit(c(2,
     0.4), c("null", "null")), heights = unit(c(1,
     1), c("null", "null")))
> vplayout <- function(...) {
     grid.newpage()
     pushViewport(viewport(layout = Layout))
 }
> subplot <- function(x, y) viewport(layout.pos.row = x,
     layout.pos.col = y)
> vplayout()
> print(p1, vp = subplot(1, 1))
> print(p2, vp = subplot(2, 1))
> print(legend, vp = subplot(1:2, 2))
https://learnr.files.wordpress.com/2009/05/sharedlegend.png
Advertisement
15 Comments leave one →
  1. September 3, 2009 12:25 pm

    Thanks for this template! I built upon this post to make a 2D plot with histograms (or better: density plots) for each axis: http://blog.mckuhn.de/2009/09/learning-ggplot2-2d-plot-with.html

  2. blessedboy permalink
    July 18, 2010 12:13 am

    what about if the data frames for plot1 and plot2 are different how can we share a legend for the two plots while we put them in the same are likes the example you give ?

    • learnr permalink*
      July 18, 2010 12:21 pm

      You can specify the data frame used by setting data=….

      Legend is independent of plot1 and plot2, so it is up to you to come up with a suitable legend.

  3. aeon permalink
    June 9, 2011 6:44 pm

    Thanks! I’m still learning ggplot2 learing-by-doing-style. Your post was more an more helpful than Hadley’s UseR book.

  4. BDH permalink
    April 2, 2012 12:32 pm

    It seems the “viewport” function does not exist any more. Does anyone else have this problem (with an up-to-date ggplot2)? Is there a new, easier solution?

    • Oscar permalink
      June 9, 2012 3:08 am

      If you are using the new ggplot2 version (>=0.9.0), that’s the reason.
      ggplot2 now has a NAMESPACE, so it doesn’t attach other packages like plyr, reshape2 or grid when loaded.

      Since viewport is a function found on package grid, you should explicitly attach it using library(grid) to use it.

    • SGS permalink
      June 28, 2012 9:19 pm

      I’m actually looking for a solution to this issue. I’ll let you know as soon as I find something. Cheers, S.

  5. Zach permalink
    June 7, 2012 7:06 pm

    When I run this code, I end up with a little squished plot in the right hand column, with the legend. How do I fix this?

    • learnr permalink*
      October 3, 2012 2:40 pm

      ggplto2 syntax changed in version 0.9.2 – this might be the reason.

  6. Maria Quintero permalink
    June 18, 2012 6:40 pm

    I try to make the same example in R but the part when I am supposed to create a plot with nly the legend usin opts(keep=”legend_box”) it doesn´t work. I keep gatting a the same plot p. Do you know what could be the reason?
    Thanks

  7. September 29, 2012 3:23 pm

    in the ggplot2 mailing someone asked abut how to reproduce this example with the new syntax in ggplot 0.9.x and Hadley response was to use gtable() because is the more maintainable option for future version: http://article.gmane.org/gmane.comp.lang.r.ggplot2/5791

    >> QUOTE
    Kohske Takahashi
    wrote:
    > Here is a 0.9.2 compatible example:
    >
    > […..]
    > p1 \ p2 \
    > gt1 \ gt2 \
    > gt \ gt \ gt \ gt \
    > grid.newpage()
    > grid.draw(gt)
    > […]

    And this style of code (using gtables) will continue to work in the
    future, except will hopefully provide better abstractions so that it’s
    easier to see what’s going on.

    Hadley
    <<END-OF-QUOTE

Trackbacks

  1. Duplicating ggplot axis labels « Defective Semantics
  2. ggplot séparer la légende et l'intrigue

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: