4

I'm using the package patchwork to combine multiple ggplot2 plots vertically. I'd like the scales for each plot to be directly above one another, regardless of the length of the scale name. At the moment, the scales are not aligned above one another.

I'm open to using ggpubr or facet_grid() if they would make it possible, but I've seen that facets doesn't allow multiple scales, and I haven't found any solution using ggpubr

library(ggplot2)
library(patchwork)

set.seed(0)
testdata <- data.frame(x=1:10, y=1:10, col=runif(10))

g1 <- ggplot(testdata, aes(x=x,y=y,col=col)) + geom_point() + 
  scale_color_gradient(name="Short")
g2 <- ggplot(testdata, aes(x=x,y=y,col=col)) + geom_point() + 
  scale_color_gradient(name="A rather longer name")
g1/g2

ggsave("testfile.tiff", units = "mm", device="tiff", 
       width=100, height=100, dpi = 100)

Example plot with scales not aligned

Ideal output:

Example plot with scales aligned

Miff
  • 7,486
  • 20
  • 20
  • Does this answer your question? [Align multiple legends with patchwork](https://stackoverflow.com/questions/59360162/align-multiple-legends-with-patchwork) – tjebo Feb 21 '21 at 22:00

2 Answers2

4

With plot_layout you can "collect" the legends. This uses as default theme(legend.position = 'right'). You can add this after plot_layout with & theme(legend.position = 'right') and adjust the position if you want to change the location of the legends.

g1/g2 + plot_layout(guides = 'collect') # & theme(legend.position = 'right') <- adjust position here!

ggsave("testfile.tiff", units = "mm", device="tiff", 
       width=100, height=100, dpi = 100)  

enter image description here

phiver
  • 23,048
  • 14
  • 44
  • 56
  • Excellent, I encourage the question asker to prefer this answer over mine. – teunbrand Feb 12 '21 at 15:54
  • I don't seem to be seeing the expected effect here. Running `g1/g2 + plot_layout(guides="collect")` moves the bottom guide up, and top guide down so they're closer together, but doesn't change their horizontal alignment. – Miff Feb 12 '21 at 16:00
  • Perhaps you meant `theme(legend.box.just = 'left')` - that seems to solve it – Miff Feb 12 '21 at 16:04
  • @Miff, On my machine everything works out of the box, but it is a clean session. ` & theme(legend.box.just = 'left')` or `& theme(legend.position = 'right')` all show the same as the picture above. If the legends are the same except for the title, you might want to look rename the title to combine them all into 1 legends. Or you might look into `guide_area` for collecting all the legends in 1 place in the graph space. – phiver Feb 12 '21 at 16:25
3

I'd also be curious to learn of a patchwork parameter than could fix this, but I don't think there is one (please correct me if I'm wrong). You may have noticed that Hadley's answer is more than 10 years old and people have been working on ggplot2 since then. The ggnewscale package solves the problem of having multiple scales per plot. Here is a facetted approach using multiple colourscales:

library(ggplot2)
library(ggnewscale)

set.seed(0)
testdata <- data.frame(x=1:10, y=1:10, col=runif(10))

ggplot(mapping = aes(x = x, y, y)) +
  geom_point(data = transform(testdata, 
                              facet = factor("Top", c("Top", "Bottom"))),
             aes(colour = col)) +
  scale_colour_continuous(name = "Short") +
  new_scale_colour() +
  geom_point(data = transform(testdata,
                              facet = factor("Bottom", c("Top", "Bottom"))),
             aes(colour = col)) +
  scale_colour_continuous(name = "A rather longer name") +
  facet_wrap(~ facet, ncol = 1)

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • This correctly addresses the problem, but has the disadvantage that the scales don't vertically match well with the plots with more than a couple of facets. – Miff Feb 12 '21 at 16:23