15

I would like to combine two or more plots merging their legends.

For example, I can create some data and two scenarios as follows.

# packages
library(ggplot2)
library(patchwork)

# first plot
set.seed(07042020)
x <- runif(50)
y <- runif(50)
data1 <- data.frame(x = x, y = y, z = runif(50, 0, 2))
p1 <- ggplot(data1) + geom_point(aes(x, y, col = z))
p1

data2 <- data.frame(x = x, y = y, z = runif(50, -1, 1))
p2 <- ggplot(data2) + geom_point(aes(x, y, col = z))
p2

The following code is what I tried so far but it's not the intended result. I would like to merge the two plots with a single legend, i.e. create a unique and common legend "z" in such a way that the points of the two plots are coloured according to this common legend. Is this possible?

p1 + p2 + plot_layout(guides = "collect")

Created on 2020-04-07 by the reprex package (v0.3.0)

agila
  • 3,289
  • 2
  • 9
  • 20
  • 1
    Why doesn’t a simple ggplot with facet and free y axes do what is required? – Mark Neal Apr 07 '20 at 09:59
  • I should have add more details, sorry. I thought about using facets but I'm not 100% sure that it will work since, in the near future, I have to use this type of code to plot 4 or 9 simple features objects having several geometries. The facet solution implies that I have to repeat each geometry object several times and create a big dataset (which maybe is also really slow to plot, I'm not sure yet). So I was wondering if it's possible to avoid that step a simple merge the single plots. – agila Apr 07 '20 at 10:15

2 Answers2

28

I think two legends can only be combined when they have the exact same properties, i.e. share limits, titles, labels, breaks etc. You can provide a common legend by sharing a common scale, one way to do that in patchwork is to use the & operator, which sort of means 'apply this to all previous plots':

p1 + p2 + plot_layout(guides = "collect") & 
  scale_colour_continuous(limits = range(c(data1$z, data2$z)))

enter image description here

Only downside is that you'd probably manually have to specify the limits as the scale in p1 does not know about the values in p2.

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • I'm sorry but it took me a few days to check the results on the "real geometry object" and it seems to work perfectly. Thanks! – agila Apr 11 '20 at 15:26
  • I don't seem to be able to make that work in version 1.1.1. Anyone else having that issue? Edit: Nevermind, the issue was that I was not using `na.rm = TRUE` when setting my scale limits with `range()`. – stragu Feb 16 '22 at 04:32
1

I know what you are trying to accomplish and have had luck. Perhaps, R is reading these as two seperate legends. Can you try manually editing each legend (even if to keep it as "z"), then using patchwork to combine?

another troubleshooting thing I've tried is to try to re-arrange your code just to ensure everything is read in correctly:

(p1 + p2) + plot_layout(guides = "collect")

Millionhorns
  • 55
  • 1
  • 6