This is a high-level overview of some color schemes in R and how to use them in ggplot2.
There are three ways we can assign colors to values, depending on the kind of variable we are representing. For categorical variables, we can use “discrete” color schemes. To assign colors to qualitative variables, we can use “continuous” color schemes (which continuously vary the color with the value) or “binned” color schemes (which use a fixed number of colors, assigning the values into “bins” to choose the color).
Here we’ll focus on discrete color schemes. Continuous and binned color schemes are used for more advanced graphics, such as heat maps and density plots, which we won’t cover in the course.
When using discrete color schemes, the variable we are representing with the color has a fixed set of values (it is categorical, or a factor), and the color scheme assigns a color to each level (each possible value) of the variable.
Load up the mouse metabolic data set:
library(tidyverse)
met <- read_csv("https://denvirlab.marshall.edu/BMR617-2023/data/TH-B6-metabolic.csv") %>%
separate(MouseID, sep='-', into=c("Strain", "Diet", "Id"))
We previously plot these data with boxplots and column scatter plots, overlaid on each other. We can also plot these separately:
ggplot(met, aes(x=Strain, y=Cholesterol)) +
geom_boxplot(aes(fill=Diet))
ggplot(met, aes(x=Strain, y=Cholesterol)) +
geom_point(aes(color=Diet), position=position_jitterdodge(jitter.width = 0.1, dodge.width = 0.75))
Notice that
geom_boxplot() uses fill=... and
geom_point() uses color=.... What happens if
you use color for geom_boxplot()? What happens
if you use fill for geom_point().
The important thing to notice here is that we can assign colors to be
used for two different aesthetics, color and
fill.
In ggplot2, color schemes are specified by adding a
“layer” to the plot. The schemes are referred to as “color scales”.
Open the “Help” tab in RStudio, and in the search field type
scale_color and press Enter. You should see a long list of
functions related to color schemes.
(Note the function names are preceded by the package they are in. So
functions starting colorspace:: are from a package called
colorspace, and functions starting ggplot2::
are from the ggplot2 package. We’ll focus on the latter
package today.)
The scale_color_manual and related functions allow us to
manually specify colors.
Since our box plot uses fill, we can use
scale_fill_manual to specify colors for it. Try the
following:
ggplot(met, aes(x=Strain, y=Cholesterol)) + geom_boxplot(aes(fill=Diet)) + scale_fill_manual(values=c("lavender", "orange", "beige"))
Notice here we’re using some color names that R recognizes. To see a list of all recognized names, use:
colors()
There are 657 recognized color names. You can also use hexadecimal color codes (which I will let you Google).
You can control which color is which by naming the
values:
ggplot(met, aes(x=Strain, y=Cholesterol)) + geom_boxplot(aes(fill=Diet)) + scale_fill_manual(values=c(LF="lavender", HF="orange", Chow="beige"))
If you want to use color instead of fill,
you can use scale_color_manual:
ggplot(met, aes(x=Strain, y=Cholesterol)) + geom_boxplot(aes(color=Diet)) + scale_color_manual(values=c(LF="purple", HF="orange", Chow="brown"))
There is also a generic scale_discrete_manual function
in which you specify which aesthetics the scale applies to.
This is useful if you want to apply it to both color and fill. (This is
not a particularly good example, for reasons you will see if you run
it.)
ggplot(met, aes(x=Strain, y=Cholesterol)) + geom_boxplot(aes(fill=Diet, color=Diet)) + scale_discrete_manual(values=c(LF="purple", HF="orange", Chow="brown"), aesthetics=c("fill", "color"))
Choosing a color scheme is a complicated task. You need to ensure the colors convey the information needed, in an unbiased way, and you should choose colors that are distinguishable by as large a proportion of the population as possible (accounting for colorblindness). You might also need to think about how the colors are rendered in non-standard situations (e.g. what happens if someone prints your plot on a black-and-white printer?).
There are several predefined schemes supported by R. The
scale_color_discrete and scale_fill_discrete
functions will give you the defaults:
ggplot(met, aes(x=Strain, y=Cholesterol)) + geom_boxplot(aes(fill=Diet)) + scale_fill_discrete()
Be aware that these are not colorblind-friendly!
There are two externally-support color schemes. Color Brewer was
originally designed for discrete colors on maps. It also works fairly
well for continuous color schemes. To see the color schemes from Color
Brewer, load the RColorBrewer package and use the
display.brewer.all() function:
library(RColorBrewer)
display.brewer.all()
There are three types of color scheme in color brewer. “Sequential”
(seq) is for a continuous scale. “Diverging”
(div) is for a diverging continuous scale, where there is a
scale with a “direction”. This is useful for fold changes, for example.
“Qualitative” (qual) is for discrete/categorical data. To
display only the qualitative scales, use
display.brewer.all(type="qual")
and to limit it to colorblind-friendly palettes, use
display.brewer.all(type="qual", colorblindFriendly = TRUE)
To use color brewer in ggplot, we can use the
scale_color_brewer and scale_fill_brewer
functions. To specify a chosen palette, use palette="..."
with the name of the palette you want. For example:
ggplot(met, aes(x=Strain, y=Cholesterol, fill=Diet)) +
geom_boxplot() +
scale_fill_brewer(palette="Dark2")
The Viridis color schemes are designed to be uniform in both color
and black-and-white, and are friendly to various forms of
colorblindness. Search in Help for scale_color_viridis. The
variants _b, _c, and _d are for
“binned”, “continuous”, and “discrete”, so in our example we want
scale_fill_viridis_d.
Try
ggplot(met, aes(x=Strain, y=Cholesterol, fill=Diet)) +
geom_boxplot() +
scale_fill_viridis_d()
Read the help menu for option under “Arguments”.
Experiment with the different options. (How many options does the help
say there are? How many are there?)
Experiment with the column scatter plots. Remember you need to use
the color functions, not the fill functions.
Note that to make experimenting quicker you can do this:
sp <- ggplot(met, aes(x=Strain, y=Cholesterol)) + geom_point(aes(color=Diet), position=position_jitterdodge(jitter.width=0.1))
and then experiment with things like:
sp + scale_color_brewer(palette="Dark2")
Beware: you can end up spending a lot of time playing with this! Don’t end up down too many rabbit holes.
Investigate other ways of customizing your plots. Google for something like “themes in ggplot2” or “background colors in ggplot2”, etc.