Search code examples
rggplot2gisggmap

Merge separate size and fill legends in ggplot


I'm plotting point data on a map and would like to scale point size and fill to another column. However, ggplot produces two separate legends for size and fill, where I only want one. I have looked at several answers to the same problem, e.g. this one, but cannot understand what I'm doing wrong. My understanding ist that if both aesthetics are mapped to the same data, there should only be one legend, correct?

Here's some code to illustrate the problem. Any help is much appreciated!

lat <- rnorm(10,54,12)
long <- rnorm(10,44,12)
val <- rnorm(10,10,3)

df <- as.data.frame(cbind(long,lat,val))

library(ggplot2)
library(scales)
ggplot() +
 geom_point(data=df,
            aes(x=lat,y=long,size=val,fill=val),
            shape=21, alpha=0.6) +
  scale_size_continuous(range = c(2, 12), breaks=pretty_breaks(4)) +
   scale_fill_distiller(direction = -1, palette="RdYlBu") +
    theme_minimal()

Solution

  • Looking at this answer citing R-Cookbook:

    If you use both colour and shape, they both need to be given scale specifications. Otherwise there will be two two separate legends.

    Thus we can infer that it is the same with size and fill arguments. We need both scales to fit. In order to do that we could add the breaks=pretty_breaks(4) again in the scale_fill_distiller() part. Then by using guides() we can achieve what we want.

    set.seed(42)  # for sake of reproducibility
    lat <- rnorm(10, 54, 12)
    long <- rnorm(10, 44, 12)
    val <- rnorm(10, 10, 3)
    
    df <- as.data.frame(cbind(long, lat, val))
    
    library(ggplot2)
    library(scales)
    ggplot() +
      geom_point(data=df, 
                 aes(x=lat, y=long, size=val, fill=val), 
                 shape=21, alpha=0.6) +
      scale_size_continuous(range = c(2, 12), breaks=pretty_breaks(4)) +
      scale_fill_distiller(direction = -1, palette="RdYlBu", breaks=pretty_breaks(4)) +
      guides(fill = guide_legend(), size = guide_legend()) +
      theme_minimal()
    

    Produces: enter image description here