I want to use a gradient along a single color (i.e. from light to dark) for a set of integers that can be considered discrete in the sense that there cannot be any fractional values between them.
But if I use a continuous scale then the legend unnecessarily displays colors for the potential fractional values. And if I use a discrete scale then fundamentally different colors are displayed (as opposed to gradient of shades). What to do?
Consider the following chart:
library(ggplot2)
set.seed(123)
(df <-rbind(data.frame(x=1:5, y=rnorm(5, 3), age=1),
data.frame(x=1:5, y=rnorm(5, 5), age=2),
data.frame(x=1:5, y=rnorm(5, 7), age=3)))
(p <- ggplot(df, aes(x, y, group=age, color=age)) +
geom_point() + geom_line())
.
To get rid of the fractional values I attempted the following, which produced different legends showing unnecessary colors for the in-between values.
p + scale_color_continuous(n.breaks=3)
p + scale_color_binned()
If I use a factor then I don't get a gradient. Here are the legends after two attempts.
(q <- ggplot(df, aes(x, y, group=age, color=factor(age, ordered = T))) +
geom_point() + geom_line())
q + scale_color_discrete()
How do I get a legend that shows colors only for the discrete values but auto-selects those colors from a gradient of shades (i.e. light to dark) rather than using fundamentally different colors.
To apply a color gradient to the discrete values you can map factor(age)
to the color aesthetic as you tried, and use a palette that provides the gradient appearance you're looking for.
You can create a vector of colors manually, and there are many sources that can help generate a suitable gradient.
custom_blues <- c("#5E93CF","#21548D","#002650")
p +
scale_color_manual(values = custom_blues) +
labs(color = 'Age')
This package is an interface to a large collection of color palettes.
library(paletteer)
p +
scale_color_paletteer_d("beyonce::X40") +
labs(color = 'Age')
Using the RColorBrewer package was in my original answer. If you like the Paletteer interface, you can still access and apply palettes from this package (e.g. RColorBrewer::Blues
)
library(RColorBrewer)
p +
scale_color_brewer(palette= "Blues") +
labs(color = 'Age') +
theme_bw()
library(ggplot2)
set.seed(123)
(df <-rbind(data.frame(x=1:5, y=rnorm(5, 3), age=1),
data.frame(x=1:5, y=rnorm(5, 5), age=2),
data.frame(x=1:5, y=rnorm(5, 7), age=3)))
#> x y age
#> 1 1 2.439524 1
#> 2 2 2.769823 1
#> 3 3 4.558708 1
#> 4 4 3.070508 1
#> 5 5 3.129288 1
#> 6 1 6.715065 2
#> 7 2 5.460916 2
#> 8 3 3.734939 2
#> 9 4 4.313147 2
#> 10 5 4.554338 2
#> 11 1 8.224082 3
#> 12 2 7.359814 3
#> 13 3 7.400771 3
#> 14 4 7.110683 3
#> 15 5 6.444159 3
p <- ggplot(df, aes(x, y, group=age, color=factor(age, ordered = TRUE))) +
geom_point(size = 4) +
geom_line(linewidth = 2)