vignettes/color_fill_scales.Rmd
color_fill_scales.Rmd
Whenever we map color or fill as an aesthetic, ggplot2
uses a default color scheme, known as the color or fill scales in the grammar of graphics.
If you do not want to use the default color/fill scales, you can override the defaults by providing a different scale. This tutorial introduces some commonly-used scales which are accessible with ggplot2, including several popular scales from colorbrewer
(a set of color scales originally devised for maps) and viridis
(a set of color scales developed for plotting purposes).
Functions we can use to change the default color/fill scales include the following:
Mapped data type | Scale type | ggplot2 function |
---|---|---|
Discrete | colorbrewer | scale_<color/fill>_brewer(palette = 'name of palette') |
Continuous | colorbrewer | scale_<color/fill>_distiller(palette = 'name of palette') |
Discrete | viridis | scale_<color/fill>_viridis_d(option = 'name of palette') |
Continuous | viridis | scale_<color/fill>_viridis_c(option = 'name of palette') |
Discrete | Custom fills/colors | scale_<color/fill>_manual(values = c('array', 'of', 'colors', 'to', 'use')) |
Continuous | Sequential gradient of custom fills/colors | scale_<color/fill>_gradient(low = 'low color', high = 'high color') |
Continuous | Diverging gradient of custom fills/colors | scale_<color/fill>_gradient2(low = 'low color', high = 'high color', mid = 'mid color', midpoint = 'number') |
colorbrewer
and viridis
palettes
Below are the names and colors associated with colorbrewer
(left) and viridis
(right) palettes. Many, but not all, of these palettes are so-called “colorblind friendly,” meaning individuals with color vision deficiencies are still able to distinguish among the palette’s colors.
All colorbrewer
palettes can be used for discrete data, but the middle set of palettes (Set3 through Accent) can not be used for continuous data. All viridis
palettes can be used for both discrete and continuous data.
All examples shown here are made from a modified version of the msleep
dataset with certain NA
values removed (see below). Examples modify the default colors/fills of one of these plots, all of which use the default ggplot2 scales. We will also set the theme for all plots to include the legend on the bottom, for easier viewing in examples (learn more about that here)!
# Remove NAs from the columns awake, sleep_rem, and vore for plotting demonstration
# We'll call this dataset `msleep_clean`
msleep %>%
tidyr::drop_na(awake, sleep_rem, vore) -> msleep_clean
# Set the plotting theme to place legends below plots
theme_set(theme(legend.position = "bottom"))
# First plot used in examples. Uses discrete color mapping.
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = vore) +
geom_point() -> plot1
# Second plot used in examples. Uses discrete fill mapping.
ggplot(msleep_clean) +
aes(x = vore,
y = awake,
fill = vore) +
geom_boxplot() -> plot2
# Third plot used in examples. Uses continuous color mapping.
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) +
geom_point() -> plot3
# Add plots together, which is allowed when you load the {patchwork} library
plot1 + plot2 + plot3
To create your own discrete palette, use the function scale_<color/fill>_manual()
. Always make sure to use the right function name for the aesthetic you are considering. In other words, use scale_color_manual()
to customize a color mapping, not to customize a fill mapping.
# Specify custom _colors_ for each vore category
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = vore) +
geom_point() +
scale_color_manual(values = c("blue", "orange", "magenta", "yellow"))
# Specify custom _fills_ for each vore category
ggplot(msleep_clean) +
aes(x = vore,
y = awake,
fill = vore) +
geom_boxplot() +
scale_fill_manual(values = c("blue", "orange", "magenta", "yellow"))
colorbrewer
scale
To use a colorbrewer
palette with discrete data, use the function scale_<color/fill>_brewer()
with the argument palette
to specify which palette you want to use. Again, always make sure to use the right function name for the aesthetic you are considering. In other words, use scale_color_brewer()
to customize a color mapping, not to customize a fill mapping.
# Specify custom _colors_ for each vore category
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = vore) +
geom_point() +
scale_color_brewer(palette = "Greens")
# Specify custom _fills_ for each vore category
ggplot(msleep_clean) +
aes(x = vore,
y = awake,
fill = vore) +
geom_boxplot() +
# yellow --> green palette
scale_fill_brewer(palette = "YlGn")
# You can reverse the order of the palette with `direction = -1`
# This argument works with any brewer function
ggplot(msleep_clean) +
aes(x = vore,
y = awake,
fill = vore) +
geom_boxplot() +
# Switch palette direction
scale_fill_brewer(palette = "YlGn",
direction = -1)
viridis
scale
To use a viridis
palette with discrete data, use the function scale_<color/fill>_viridis_d()
(d for discrete!) with the argument option
(not palette
) to specify which palette you want to use. Again, always make sure to use the right function name for the aesthetic you are considering. In other words, use scale_color_viridis_d()
to customize a color mapping, not to customize a fill mapping.
# Specify custom _colors_ for each vore category
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = vore) +
geom_point() +
scale_color_viridis_d(option = "inferno")
# Specify custom _colors_ for each vore category
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = vore) +
geom_point() +
# without `option`, the default viridis palette is used
scale_color_viridis_d()
# You can reverse the order of the palette with `direction = -1`
# This argument works with any viridis function
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = vore) +
geom_point() +
# reverse the order of the palette
scale_color_viridis_d(direction = -1)
# Specify custom _fills_ for each vore category
ggplot(msleep_clean) +
aes(x = vore,
y = awake,
fill = vore) +
geom_boxplot() +
scale_fill_viridis_d(option = "plasma")
To create your own continuous palette, i.e. gradient, use either of these functions: + scale_<color/fill>_gradient()
: A gradient from one color to another + scale_<color/fill>_gradient2()
: A gradient from one color to another, with another color in the middle
# Specify a custom gradient for each value of awake, a continuous variable
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) + # Color is mapped to a continuous variable
geom_point() +
# Gradient goes low-->high values, blue-->orange
scale_color_gradient(low = "blue", high = "orange")
# Change the direction of your custom palette by switching low/high values
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) + # Color is mapped to a continuous variable
geom_point() +
# Gradient goes low-->high values, blue-->orange
scale_color_gradient(low = "orange", high = "blue")
# Specify a custom gradient2 for each value of awake, a continuous variable
# BUT! The default midpoint "switch" is 0, and all awake values are _above 0_, so we see no gradient2
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) + # Color is mapped to a continuous variable
geom_point() +
# Gradient goes low-->middle-->high values, blue-->black-->orange
scale_color_gradient2(low = "blue",
high = "orange",
mid = "black")
# Make the previous example "switch" the gradient2 at a midpoint of 13, for example
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) + # Color is mapped to a continuous variable
geom_point() +
# Gradient goes low-->middle-->high values, blue-->black-->orange
scale_color_gradient2(low = "blue",
high = "orange",
mid = "black",
# Make the gradient2 "switch" at a midpoint of 13
midpoint = 13)
# Example of a fill gradient, still using points but with pch = 21, which accepts color and fill
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
fill = awake) + # FILL is mapped to a continuous variable
geom_point(pch = 21,
# Size is increased here just so you can better see the filled in points
size = 2) +
scale_fill_gradient(low = "blue", high = "orange")
colorbrewer
scale
To use a colorbrewer
palette with continuous data, use the function scale_<color/fill>_distiller()
with the argument palette
to specify which palette you want to use. Again, always make sure to use the right function name for the aesthetic you are considering. In other words, use scale_color_distiller()
to customize a color mapping, not to customize a fill mapping.
# Specify custom _colors_ for each awake value
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) +
geom_point() +
scale_color_distiller(palette = "Reds")
# Specify custom _fills_ for each awake value, still using points but with pch = 21, which accepts color and fill
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
fill = awake) +
geom_point(pch = 21,
# Size is increased here just so you can better see the filled in points
size = 2) +
# blue/purple distiller
scale_fill_distiller(palette = "BuPu")
viridis
scale
To use a viridis
palette with continuous data, use the function scale_<color/fill>_viridis_c()
(c for continuous!) with the argument option
(not palette
) to specify which palette you want to use. Again, always make sure to use the right function name for the aesthetic you are considering. In other words, use scale_color_viridis_c()
to customize a color mapping, not to customize a fill mapping.
# Specify custom _colors_ for each awake value
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) +
geom_point() +
scale_color_viridis_c(option = "inferno")
# Specify custom _colors_ for each awake value
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) +
geom_point() +
# without `option`, the default viridis palette is used
scale_color_viridis_c()
# You can reverse the order of the palette with `direction = -1`
# This argument works with any viridis function
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
color = awake) +
geom_point() +
# reverse the order of the palette
scale_color_viridis_c(direction = -1)
# Specify custom _fills_ for each awake value, still using points but with pch = 21, which accepts color and fill
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
fill = awake) +
geom_point(pch = 21,
# Size is increased here just so you can better see the filled in points
size = 2) +
scale_fill_viridis_c(option = "magma")
NA
values
In the previous examples, we removed all NA
values from the columns we were plotting. However, if NA
values are represent, they will be colored/filled gray (specifically, “gray50”) by default (with any palette). For example,
# Example scatterplot with NAs
ggplot(msleep_clean) +
aes(x = awake,
y = sleep_rem,
# Color points by sleep_cycle, a continuous variable with NA's
color = sleep_cycle) +
geom_point() -> na_scatterplot
# Example boxplot with NAs
ggplot(msleep_clean) +
aes(x = conservation,
y = awake,
# Fill by conservation, a discrete variable with NA's
fill = conservation) +
geom_boxplot() -> na_boxplot
# Add plots together for display, which is allowed since `{patchwork}` has been loaded
na_scatterplot + na_boxplot
To override the default NA
color or fill, provide a scale_
function with the argument na.value = COLOR YOU WANT NA's TO BE
, as shown in examples below.
{ggplot2}
scales
If you want to change the NA
color/fill while using the default ggplot2 scales, you will need to use one of these functions: + scale_<color/fill>_discrete()
if the mapped variable is discrete/categorical + scale_<color/fill>_continuous()
if the mapped variable is continuous
# Example scatterplot with NAs using default ggplot2 palette
# The discrete variable conservation is mapped to color, so use scale_color_discrete()
# We force NA colors to be yellow
ggplot(msleep) +
aes(x = awake,
y = sleep_rem,
# Color points by conservation, a discrete variable with NA's
color = conservation) +
geom_point() +
scale_color_discrete(na.value = "yellow")
#> Warning: Removed 22 rows containing missing values (geom_point).
# Example scatterplot with NAs using default ggplot2 palette
# The continuous variable sleep_cycle is mapped to color, so use scale_color_continuous()
# We force NA colors to be yellow
ggplot(msleep) +
aes(x = awake,
y = sleep_rem,
# Color points by sleep_cycle, a continuous variable with NA's
color = sleep_cycle) +
geom_point() +
scale_color_continuous(na.value = "yellow")
#> Warning: Removed 22 rows containing missing values (geom_point).
# Example boxplot with NAs using default ggplot2 palette
# The discrete variable conservation is mapped to fill, so use scale_fill_discrete()
# We force NA fills to be yellow
ggplot(msleep) +
aes(x = conservation,
y = awake,
# Fill points by conservation, a discrete variable with NA's
fill = conservation) +
geom_boxplot() +
scale_fill_discrete(na.value = "yellow")
colorbrewer
, or viridis
scales
Simply add in the argument na.value = COLOR FOR THE NA VALUES
to any of the scale functions you have seen:
# Example scatterplot with NAs using a custom palette
# The continuous variable sleep_cycle is mapped to color, so use scale_color_gradient()
# We force NA colors to be yellow
ggplot(msleep) +
aes(x = awake,
y = sleep_rem,
# Color points by sleep_cycle, a continuous variable with NA's
color = sleep_cycle) +
geom_point() +
scale_color_gradient(low = "orange",
high = "brown",
na.value = "yellow")
#> Warning: Removed 22 rows containing missing values (geom_point).
# Example scatterplot with NAs using a colorbrewer palette
# The continuous variable sleep_cycle is mapped to color, so use scale_color_distiller()
# We force NA colors to be yellow
ggplot(msleep) +
aes(x = awake,
y = sleep_rem,
# Color points by sleep_cycle, a continuous variable with NA's
color = sleep_cycle) +
geom_point() +
scale_color_distiller(palette = "Purples",
na.value = "yellow")
#> Warning: Removed 22 rows containing missing values (geom_point).
# Example boxplot with NAs using a viridis palette
# The discrete variable vore is mapped to fill, so use scale_fill_viridis_d()
# We force NA fills to be yellow
ggplot(msleep) +
aes(x = vore,
y = awake,
# Fill points by vore, a discrete variable with NA's
fill = vore) +
geom_boxplot() +
scale_fill_viridis_d(option = "mako",
na.value = "yellow")