Search code examples
rggplot2ggnewscale

How to fix legend order using ggplot in R?


I am creating a plot that has 2 legends using both ggplot2 and ggnewscale. What I'm trying to achieve is to fix the order of the separate legends so they always appear in the same order. The images and code below show a basic example of the issue I'm having.

First, create some data and set the colour palettes:

df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))

pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))

Now create a plot (note the limits I set are between 0 and 1 for the legends):

library(ggplot2)
library(ggnewscale)

ggplot(df, mapping = aes(x, y)) +
  geom_point(size = 3, aes(fill = y)) +
  scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
  new_scale_fill() +
  geom_point(data = df_1, size = 3, aes(fill = y)) +
    scale_fill_gradientn(colors = pal_2, limits = c(0,1), name = "val2") 

This will result in the following image (note that the legend for val1 is on the top):

plot 1

Now, if we change the limits for val2 to something larger, like so:

ggplot(df, mapping = aes(x, y)) +
  geom_point(size = 3, aes(fill = y)) +
  scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
  new_scale_fill() +
  geom_point(data = df_1, size = 3, aes(fill = y)) +
    scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2") 

We will get this (note that val2 legend is now on top:

plot 2

It seems that ggplot will put the legend with the larger limit range on the top. I was wonder if there was a way to fix the legend order so that, say val1 is always on the top... no matter the range of the limits?


Solution

  • You could specify the order of the legends via the order argument of guide_xxx:

    df <- data.frame(x = c(1:5), y = runif(10))
    df_1 <- data.frame(x = c(1:5), y = runif(10))
    
    pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
    pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
    
    library(ggplot2)
    library(ggnewscale)
    
    ggplot(df, mapping = aes(x, y)) +
      geom_point(size = 3, aes(fill = y)) +
      scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1", 
                           guide = guide_colorbar(order = 1)) +
      new_scale_fill() +
      geom_point(data = df_1, size = 3, aes(fill = y)) +
      scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2",
                           guide = guide_colorbar(order = 2))