Controlling ggplot2 legend order with new_scale_color() of ggnewscale

Viewed 67

I can't seem to arrange the order of legend items when using the new_scale_color() feature of the ggnewscale package. Here's a minimal example:

n <- 10
sd_res <- 1
beta0 <- 0
beta1 <- 1

x <- runif(n, 0, 10)
y <- beta0 + beta1*x + rnorm(n, 0, sd_res)
dat <- data.frame(x,y)

ggplot() + theme_minimal() + labs(x = '', y = '') + 
  geom_abline(aes(color = 'x', linetype = 'x', slope = 1, intercept = 0)) + 
  geom_abline(aes(color = 'y', linetype = 'y', slope = 2, intercept = 0)) +
  scale_color_manual(name = '', values = c('x' = 'orange', 'y' = 'black')) + 
  scale_linetype_manual(name = '', values = c('x' = 1, 'y' = 2)) + 
  new_scale_color() + 
  geom_point(data=dat, aes(x=x, y=y, shape = 'z', size = 'z', color = 'z'), alpha = 1) + 
  scale_size_manual(name = '', values = c('z' = 1.5)) +
  scale_shape_manual(name = '', values = c('z' = 16)) +
  scale_color_manual(name = '', values = c('z' = 'black')) +
  theme(legend.position = 'bottom')

What I'd like is for the z-item to appear before the x- and y-items in the legend.

2 Answers

You could use guides with guide_legend and specify the order of your aes. Here I set the order of your "z" to 1 which will set it as the first legend like this:

n <- 10
sd_res <- 1
beta0 <- 0
beta1 <- 1

x <- runif(n, 0, 10)
y <- beta0 + beta1*x + rnorm(n, 0, sd_res)
dat <- data.frame(x,y)

library(ggplot2)
library(ggnewscale)
p <- ggplot() + theme_minimal() + labs(x = '', y = '') + 
  geom_abline(aes(color = 'x', linetype = 'x', slope = 1, intercept = 0)) + 
  geom_abline(aes(color = 'y', linetype = 'y', slope = 2, intercept = 0)) +
  scale_color_manual(name = '', values = c('x' = 'orange', 'y' = 'black')) + 
  scale_linetype_manual(name = '', values = c('x' = 1, 'y' = 2)) + 
  new_scale_color() + 
  geom_point(data=dat, aes(x=x, y=y, shape = 'z', size = 'z', color = 'z'), alpha = 1) + 
  scale_size_manual(name = '', values = c('z' = 1.5)) +
  scale_shape_manual(name = '', values = c('z' = 16)) +
  scale_color_manual(name = '', values = c('z' = 'black')) +
  theme(legend.position = 'bottom') +
  guides(size = guide_legend(order = 1), 
         color = guide_legend(order = 1), 
         shape = guide_legend(order = 1))

p

Created on 2022-08-26 with reprex v2.0.2

When using ggnewscale, I don't recommend using guides() to define guides, since the name of the aesthetics change internally. It's better to use the guide argument of the scale_ function

Example from ggnewscale documentation:

library(ggplot2)
library(ggnewscale)
# Equivalent to melt(volcano)
topography <- expand.grid(x = 1:nrow(volcano),
                          y = 1:ncol(volcano))
topography$z <- c(volcano)

# point measurements of something at a few locations
set.seed(42)
measurements <- data.frame(x = runif(30, 1, 80),
                           y = runif(30, 1, 60),
                           thing = rnorm(30))

ggplot(mapping = aes(x, y)) +
  geom_contour(data = topography, aes(z = z, color = stat(level))) +
  # Color scale for topography
  scale_color_viridis_c(option = "D", 
                        guide = guide_colorbar(order = 2)) +
  # geoms below will use another color scale
  new_scale_color() +
  geom_point(data = measurements, size = 3, aes(color = thing)) +
  # Color scale applied to geoms added after new_scale_color()
  scale_color_viridis_c(option = "A", 
                        guide = guide_colorbar(order = 8))

Created on 2022-08-26 by the reprex package (v2.0.1)

Related