Ggplot, Feature Request: Two different legends with sizes

Please, add the ability to properly have two legends with the same concept, for example two legends related to the size.

If I run this simple code

DF <- data.frame(x=c(1,2,3,4), y=c(1,2,3,4), 
z=c(3.4,1.2,1.1,0.5))
ggplot() + geom_segment(data=DF, aes(x=x, y=y, 
xend=x+1, yend=y+1, size=z/10 ), colour="blue") +
geom_point(data=DF,aes(x=x, y=y, size=z)) +   
scale_size_continuous(name="size")

I get the legend for two variables that define sizes but they overlap and they are unusable.
Example

I have also tried using
+scale_size_continuous(name="size1") + scale_size_continuous(name="size2")
But it generates an error.

I've asked this at ggplot2 github but they told me to do it here.

Hi @skan,

It's definitely possible to add multiple legends— in fact, you have, the problem is with their positioning. Maybe take a look at Custom Layout: Legends from the R Graph Gallery. There's a detailed vignette by Stefan McKinnon Edwards, Working with legends, you can check out, (and I'm sure there are several others :wink:).

Some of the ggplot extensions here might be useful (or easier) as well: http://www.ggplot2-exts.org/gallery/ (perhaps cowplot).

4 Likes

It's a little bit workaroundey, but Nicola Sturaro Sommacal has written a great blog post on a solution to this. Basically, for one of the geoms, you assign the data-relevant mapping to some dummy aesthetic that won't appear anyway (in the illustrated case, fill), and then you specify the colour as a literal. Finally, you provide those colours again to a scale function for the dummy aesthetic.

It's not super scalable, though: you have to provide a separate geom for each... uh, point? Whatever the generalised version of a point is. If you have four records that you want to draw points or segments or whatever of, you need to give four geom calls. It works well in this case because the second geom is horizontal lines, which people tend to only use a few of. But if you had a full set of however many records, it would be horrid. But it's something!

2 Likes

@mara and @rensa I'll have a look, thank you, it seems a little bit complex.

You could suppress one of point or line or tweak the legend aesthetics to show the differences more clearly. There’s only one underlying scale so two legends are a bit redundant.

No because they are different variables.
I have 4 variables, one goes to the x-axis, other one to the y-axis, another one to the width of the points, and the last one to the thicknes of the lines.
Each variable represents something different.
They must be represented on a paper, thus on a 2D plane, but I can use different ways to paint the legends.

Imagine for example you have a map where the points represent cities (their population), its coordinates represent the coordinates of the cities, and the thickness of the lines represent how many cars travel from one city to the other.

I could also use different colors instead of thicknesses but now I need to use thicknesses.

Sounds like the kind of complexity that merits some "bespoke" layout above and beyond typical options. Check out Ilya Kashnitsky's Hacking maps with ggplot2— it doesn't do what you're describing (to be honest, I can't quite picture what you're getting at yet :thinking:). Given the layered nature of ggplot, there's nothing I can think of that would keep you from putting the legends in two different places.

One could probably create a new geom + scale to map a linewidth variable for the lines, which would get its own legend independent of the point size. But to be honest it would be just as fragile as a hack to combine bits and pieces from two separate plots.

1 Like

We just need the scale_size_continuous function to take an extra parameter specifying the name of the variable to map. That way we could do it with several variables.

No, the changes required would be much bigger than that; it's basically a core design decision in ggplot2 that there be only one scale of a specific type per plot.

2 Likes