D.4 Using color packages
Most packages that primarily deal with visualizations — like ggplot2, lattice, or plotly — provide their own color palettes. To reach beyond the 657 predefined colors of R and the color palettes included in grDevices, the primary resource are packages that provide additional — and typically more specialized — color support.
There is a large number of R packages that provide dedicated color support (i.e., define colors and color scales, and corresponding functions) for all means and purposes. As a consequence, many users of R never define a new color palette, but use the color palettes provided by others. However, to choose nice colors, we have to know which options exist and how they can be chosen and compared. As choosing colors is not just an art, but also a matter of taste, we merely mention some personal preferences in this section.
D.4.1 RColorBrewer
The colors at http://colorbrewer2.org (Brewer, 2019) were primarily designed to color maps. Beyond cartography, the vibrant color palettes are widely used in the R community, thanks to the popular RColorBrewer package (Neuwirth, 2014) and their integration into the ggplot2 package (Wickham et al., 2021).
Actually, unless you happen to need very special colors, RColorBrewer provides nice and useful color palettes that are sufficient for most purposes.
library(RColorBrewer) # load package
The following command prints all color palettes included in RColorBrewer:
display.brewer.all()
D.4.2 viridis/viridisLite
The color scales of the viridis package (Garnier, 2018a) were specifically designed to be perceptually-uniform, both in regular form and when converted to black-and-white.
Its color palettes viridis
, magma
, plasma
, and inferno
can also be perceived by readers with the most common form of color blindness, and the cividis
scale is even suited for people with color vision deficiency.
library(viridis) # load package
<- y <- seq(-8*pi, 8*pi, len = 40)
x <- sqrt(outer(x^2, y^2, "+"))
r filled.contour(cos(r^2) * exp(-r/(2*pi)),
axes = FALSE,
color.palette = viridis,
asp = 1)
<- y <- seq(-6*pi, 6*pi, len = 36)
x <- sqrt(outer(x^2, y^2, "+"))
r filled.contour(cos(r^2) * exp(-r/(2*pi)),
axes = FALSE,
color.palette = inferno,
asp = 1)
In recent versions of ggplot2, the viridis scales are integrated and can be used by specifying scale_color_viridis_c()
and scale_color_viridis_c()
(for continuous color scales) and scale_fill_viridis_d()
and scale_fill_viridis_d()
(for discrete color scales).
(See also Chapter 12.3 Using a Colorblind-Friendly Palette in the R Graphics Cookbook.)
The viridisLite package (Garnier, 2018b) is a simpler version of the viridis package and sufficient for most purposes:
library(viridisLite) # load package
<- viridis(n = 10)
vir_10 seecol(vir_10, col_brd = "white", lwd_brd = 4,
title = "Example of a viridis color palette (n = 10)",
pal_names = paste0("viridis_", 1:10))
The following functions each define a color scale of n
colors:
<- 20 # number of colors
n
# define 5 different color scales (n colors each):
<- viridis(n)
v1 <- magma(n)
v2 <- inferno(n)
v3 <- plasma(n)
v4 <- cividis(n)
v5
# See and compare color scales:
seecol(list(v1, v2, v3, v4, v5),
col_brd = "white", lwd_brd = 4,
title = "Various viridis color palettes (n = 20)",
pal_names = c("v1: viridis", "v2: magma", "v3: inferno", "v4: plasma", "v5: cividis"))
Check out ?viridisLite::viridis
for additional information.
Another option for obtaining perceptually ordered and uniform color palettes are the Scientific colour maps by Fabio Crameri (F. Crameri, 2018). They are provided in many different formats — implemented by the scico package in R — friendly to people with color vision deficiency, and still readable in black-and-white print.
Finally, the dichromat package focuses on palettes for color-impaired viewers and allows simulating the effects of different types of color-blindness.
D.4.3 unikn
The unikn package (Neth & Gradwohl, 2021) implements the color schemes of the University of Konstanz and is used throughout this book.
Please note: As one of the authors of the unikn package, I cannot help thinking that it is indispensable for working with colors. However, many people appear to live quite happy and colorful lives without ever needing this package.
Besides providing a range of pre-defined color palettes, the package provides some color functions that are generally useful:
The
seecol()
function allows a quick and easy inspections of color palettes. It has two distint modes, depending on the type of its first argumentpal
:When called with a (single) color palette, it allows seeing (or printing the details of) a particular color palette;
When called with a list of (several) color palettes or a recognized keyword, it allows comparing multiple color palettes.
Here are examples for seeing a single color palette:
library(unikn) # load package
seecol(pal = pal_unikn) # see/print details of a particular color palette
and for comparing several color palettes:
seecol(pal = "all") # compare all available color palettes
- The
usecol()
function makes creating new and modifying existing color palettes very easy:
<- usecol(pal = c(Karpfenblau, "white", Peach), n = 15) # define color palette from 3 colors
mix_1 <- usecol(pal = c(rev(pal_seeblau), "white", pal_pinky)) # combining 2 color palettes
mix_2 <- usecol(pal = c(rev(pal_bordeaux), "white", pal_petrol), n = 15) # mix and extend color palettes
mix_3
# Show and compare custom color palettes:
seecol(list(mix_1, mix_2, mix_3),
col_brd = "white", lwd_brd = 4,
title = "Comparing palettes mixed from unikn colors",
pal_names = c("mix_1", "mix_2", "mix_3"))
The usecol()
function also provides a wrapper for using and modifying (pre-defined or newly created) color palettes in graphs:
<- y <- seq(-8*pi, 8*pi, len = 40)
x <- sqrt(outer(x^2, y^2, "+"))
r filled.contour(cos(r^2) * exp(-r/(2*pi)),
axes = FALSE,
col = usecol(mix_2, n = 20),
asp = 1)
Even when not using the color palettes of the University of Konstanz, the usecol()
and seecol()
functions are often useful, as they also work with the color palettes provided by other packages.
For instance, we can use the seecol()
function to compare (and modify) sets of color palettes from different packages.
In the following example, we first create 12 color palettes from three packages:
four color palettes from hcl.pals()
of grDevices (R Core Team, 2021),
four color palettes from RColorBrewer (Neuwirth, 2014), and
four color palettes from yarrr (Phillips, 2017).
We then uses the seecol()
function to view and compare all 12 color palettes:
# (a) get some HCL palettes (assuming R version 3.6.0+):
# hcl.pals() shows the names of all HCL palettes
<- hcl.colors(n = 10, palette = "Fall")
hcl_1 <- hcl.colors(n = 10, palette = "Geyser")
hcl_2 <- hcl.colors(n = 10, palette = "Berlin")
hcl_3 <- hcl.colors(n = 10, palette = "Zissou 1")
hcl_4
# (b) get some palettes from RColorBrewer:
library(RColorBrewer)
# display.brewer.all() # shows all Brewer palettes
<- brewer.pal(n = 11, name = "BrBG")
brew_1 <- brewer.pal(n = 11, name = "PRGn")
brew_2 <- brewer.pal(n = 11, name = "Spectral")
brew_3 <- brewer.pal(n = 8, name = "Pastel1")
brew_4
# (c) get some palettes from yarrr:
library(yarrr)
# yarrr::piratepal() # shows all pirate palettes
<- yarrr::piratepal(palette = "basel")
yarrr_1 <- yarrr::piratepal(palette = "appletv")
yarrr_2 <- yarrr::piratepal(palette = "espresso")
yarrr_3 <- yarrr::piratepal(palette = "info")
yarrr_4
<- list(hcl_1, hcl_2, hcl_3, hcl_4,
my_pals
brew_1, brew_2, brew_3, brew_4,
yarrr_1, yarrr_2, yarrr_3, yarrr_4)<- c("hcl_1", "hcl_2", "hcl_3", "hcl_4",
my_names "brew_1", "brew_2", "brew_3", "brew_4",
"yarrr_1", "yarrr_2", "yarrr_3", "yarrr_4")
# Show and compare color palettes:
library(unikn)
seecol(pal = my_pals,
col_brd = "white", lwd_brd = 2,
title = "Comparing HCL, RColorBrewer and yarrr color palettes",
pal_names = my_names)
Similarly, we can use the usecol()
function to mix and modify color palettes from various sources. Again, it makes sense to inspect the results with seecol()
:
# Mix, extend and modify some palettes (from other packages):
<- usecol(c(rev( brewer.pal(n = 4, name = "Reds")),
brew_mix "white", brewer.pal(n = 4, name = "Blues")), n = 13)
<- usecol(brewer.pal(n = 11, name = "Spectral"), n = 12)
brew_ext
<- usecol(c(piratepal("nemo"), piratepal("bugs")))
yarrr_mix <- usecol(c(piratepal("ipod")), n = 9)
yarrr_mod
<- list(brew_mix, brew_ext,
my_pals
yarrr_mix, yarrr_mod)<- c("brew_mix", "brew_ext",
my_names "yarrr_mix", "yarrr_mod")
# Show and compare new color palettes:
seecol(pal = my_pals,
col_brd = "white", lwd_brd = 2,
title = "Using usecol() and seecol() to mix and modify palettes",
pal_names = my_names)
Additionally, the unikn package provides two functions that help with defining new named color palettes or finding colors with specific names:
- The
newpal()
function makes it easy to define new named color palettes:
# (1) Source: <https://www.schemecolor.com/germany-flag-colors.php>
<- c("#000000", "#dd0000", "#ffce00")
col_flag <- c("Black", "Electric red", "Tangerine yellow")
names_de
# (2) Source: <https://en.wikipedia.org/wiki/Flag_of_Germany#Design>
<- c("#000000", "#FF0000", "#FFCC00")
col_flag <- c("Jet black", "Traffic red", "Rapeseed yellow")
names_de
# Decision: Simplify names:
<- c("de_black", "de_red", "de_gold")
simple_names
# Define color palette:
<- newpal(col = col_flag,
flag_de names = simple_names)
seecol(flag_de,
title = "Defining a flag_de color palette",
mar_note = "Colors based on <https://en.wikipedia.org/wiki/Flag_of_Germany>" # credit source
)
Note that different sources often provide different colors (and certainly different names) for the same color schemes. Thus, it always makes sense to double-check definitions and acknowledge one’s sources.
- The
grepal()
function addresses a common problem: We typically know that we want some shade of some color (e.g., orange), but do not know which corresponding colors exist in our environment. Thegrepal()
function searches color names for a pattern:
grepal(pattern = "orange") # returns colors() with "orange" in their name
#> [1] "darkorange" "darkorange1" "darkorange2" "darkorange3" "darkorange4"
#> [6] "orange" "orange1" "orange2" "orange3" "orange4"
#> [11] "orangered" "orangered1" "orangered2" "orangered3" "orangered4"
seecol(pal = grepal("orange"),
title = "See all colors() with 'orange' in their name")
By default, grepal(pattern, x)
searches x = colors()
(i.e., the 657 named colors provided by the grDevices package), but x
can be set to other named color palettes (including data frames). As pattern
can be a regular expression (see Appendix E now provides a primer on using regular expressions), we can easily answer more complex questions:
Which color names end on
pink
,purple
, orviolet
? How do these colors look?How many shades of gray or grey are there (in R)?
Both these questions can easily be answered by combining two calls to the grepal()
and the seecol()
functions:
- Which color names end on
pink
,purple
, orviolet
? How do these colors look?
<- grepal(pattern = "pink$|purple$|violet$")
cols_ppv
seecol(pal = cols_ppv,
title = "See all colors() with names ending on 'pink', 'purple' or 'violet'")
- How many shades of gray or grey are there (in R)?
length(grepal("gr(a|e)y")) # shades of "gray" or "grey"
#> [1] 224
length(grepal("^gr(a|e)y")) # shades starting with "gray" or "grey"
#> [1] 204
length(grepal("^gr(a|e)y$")) # shades starting and ending with "gray" or "grey"
#> [1] 2
Finally, combining grepal()
with seecol()
also allows comparing long color palettes containing certain keywords:
<- grepal("red")
pal_r <- grepal("green")
pal_g <- grepal("blue")
pal_b
seecol(list(pal_r, pal_g, pal_b),
title = "See all colors() with 'red', 'green', 'blue' in their name")
- When using the pipe operator
%>%
from the magrittr package (Bache & Wickham, 2022), we can use multiple unikn functions to create and evaluate colorful chains of commands:
library(magrittr)
<- c("#FAAB18", "#1380A1","#990000", "#588300")
cols
%>%
cols newpal(names = c("orangy", "bluish", "redish", "greeny")) %>%
# usecol(n = 10) %>%
seecol(title = "My new custom color palette")
This concludes our overview of selected color packages in R. See Resources on color packages (in Section D.7.3) for links to many additional color packages.