One of the important aspects of
cartography and data visualization is color choice. This vignette
illustrates the palettes included with biscale
, provides an
overview of palette manipulation tools, and describes the revised
approach to utilizing custom palettes.
Palette Manipulations
In order to facilitate even greater flexibility with palettes,
biscale
functions include two additional arguments to
manipulate their arrangement.
“Flipping axes” will invert the colors assigned to the x and y axes.
Flipping axes is accomplished with the flip_axes
argument:
bi_pal(pal = "PurpleOr", dim = 3, flip_axes = TRUE)
“Rotating” the palette (with the rotate_pal
argument)
will rotate the colors 180 degrees, resulting in a palette that
highlights low values as opposed to high values. Rotating the palette
rotates the entire color scale 180 degrees. For example:
bi_pal(pal = "PurpleOr", dim = 3, rotate_pal = TRUE)
These manipulations can be combined as well, producing a palette that
has been both flipped and rotated:
bi_pal(pal = "PurpleOr", dim = 3, flip_axes = TRUE, rotate_pal = TRUE)
Together, these changes to bi_pal()
result in the
following shifts to the "PurpleOr"
palette:
When applied to real world data, these transformations result in
subtle (in the case of flipping) or more dramatic (in the case of
rotating) differences in maps:
Utilizing both flipping axes and palette rotations also yields a
considerable change from the original:
Be careful to ensure that your use of flip_axes
and/or
rotate_pal
is consistent across
bi_scale_fill()
/bi_scale_color()
as well as
bi_legend()
.
Custom Palettes
In addition the built-in palettes described above,
biscale
supports custom palettes. As of v1.0.0, the
workflow for using custom palettes is different than prior releases and
the old approach, using bi_pal_manual()
, has been
deprecated. We plan to remove bi_pal_manual()
in late 2022.
Please update your workflows accordingly.
To create a custom palette, users must create a named vector and
supply associated hex values. We recommend checking out Benjamin Brooke’s Bivariate
Choropleth Color Generator if you want to experiment with creating
your own palettes. Joshua
Steves’ blogpost from 2015 also contains tips for creating
palettes.
The first example below is a named vector for a two-by-two
(dim = 2
) map. The pairs correspond to x,y
coordinates on the legend where the first value is the x
value and the second is the y
value. The 1-1
pair is therefore the lower left corner of the legend and, in the
example, the 2-2
pair is the upper right corner. The named
vector should have 4 values in total.
custom_pal2 <- c(
"1-1" = "#d3d3d3", # low x, low y
"2-1" = "#9e3547", # high x, low y
"1-2" = "#4279b0", # low x, high y
"2-2" = "#311e3b" # high x, high y
)
If you are creating a custom palette for a three-by-three
(dim = 3
) map, you need to extend each row and column by 1
so that 3-1
and 3-2
are included in the vector
along with 1-3
, 2-3
, and 3-3
. The
named vector should have 9 values in total.
custom_pal3 <- c(
"1-1" = "#d3d3d3", # low x, low y
"2-1" = "#ba8890",
"3-1" = "#9e3547", # high x, low y
"1-2" = "#8aa6c2",
"2-2" = "#7a6b84", # medium x, medium y
"3-2" = "#682a41",
"1-3" = "#4279b0", # low x, high y
"2-3" = "#3a4e78",
"3-3" = "#311e3b" # high x, high y
)
Finally, for a four-by-four (dim = 4
), should be further
extended by 1 so that 4-1
, 4-2
, and
4-3
are included in the vector along with 1-4
,
2-4
, 3-4
, and 4-4
. The named
vector should have 16 values in total.
custom_pal4 <- c(
"1-1" = "#d3d3d3", # low x, low y
"2-1" = "#c2a0a6",
"3-1" = "#b16d79",
"4-1" = "#9e3547", # high x, low y
"1-2" = "#a3b5c7",
"2-2" = "#96899d",
"3-2" = "#895e72",
"4-2" = "#7a2d43",
"1-3" = "#7397bb",
"2-3" = "#697394",
"3-3" = "#604e6b",
"4-3" = "#56263f",
"1-4" = "#4279b0", # low x, high y
"2-4" = "#3c5c8b",
"3-4" = "#373f65",
"4-4" = "#311e3b" # high x, high y
)
You can preview and validate your named vector using
bi_pal()
. For example, we can preview the
custom_pal3
vector created above:
# load dependencies
library(biscale)
# preview palette
bi_pal(pal = custom_pal3, dim = 3)
Once you have created your named vector, you can use it any place
where you would ordinarily provide a quoted palette name in
biscale
functions. In this example, the
custom_pal3
vector created above is passed to
bi_scale_fill()
and bi_legend()
:
# prep data
data <- stl_race_income
data <- bi_class(data, x = pctWhite, y = medInc, dim = 3, style = "quantile", keep_factors = TRUE)
# draw map
map <- ggplot() +
geom_sf(data = data, aes(fill = bi_class), color = "white", size = 0.1, show.legend = FALSE) +
bi_scale_fill(pal = custom_pal3, dim = 3) +
labs(
title = "Race and Income in St. Louis, MO",
subtitle = "Custom Palette"
) +
bi_theme()
# draw legend
legend <- bi_legend(pal = custom_pal3,
xlab = "Higher % White ",
ylab = "Higher Income ",
size = 12)
When custom palettes are passed to biscale
functions,
they will be validated to ensure they have the correct number of
entries, have the correct names, and have properly formatted hex
values.
For custom palettes that are two-by-two (dim = 2
),
three-by-three (dim = 3
), or four-by-four
(dim = 4
), the palette manipulations described above can
also be applied:
bi_pal(pal = custom_pal3, dim = 3, flip_axes = TRUE, rotate_pal = TRUE)
High Dimensional Palettes
The custom palette workflow not only enables users to bring whatever
color scheme they wish to biscale
, but it provides support
for higher dimensional maps (dim = 5
and beyond). Users
should carefully consider the readability of these maps, however, and a
warning to this effect will be generated when using
bi_class()
. Users creating high dimensional maps should
also note that flipping and rotating palettes is not supported beyond
dim = 5
, and any modifications to the palette must be made
manually.
To create a named vector for a five-by-five (dim = 5
)
map, for example, the following named vector could be used:
custom_pal <- c(
"1-1" = "#d3d3d3", # low x, low y
"2-1" = "#b6cdcd",
"3-1" = "#97c5c5",
"4-1" = "#75bebe",
"5-1" = "#52b6b6", # high x, low y
"1-2" = "#cab6c5",
"2-2" = "#aeb0bf",
"3-2" = "#91aab9",
"4-2" = "#70a4b2",
"5-2" = "#4e9daa",
"1-3" = "#c098b9",
"2-3" = "#a593b3",
"3-3" = "#898ead",
"4-3" = "#6b89a6",
"5-3" = "#4a839f",
"1-4" = "#b77aab",
"2-4" = "#9e76a6",
"3-4" = "#8372a0",
"4-4" = "#666e9a",
"5-4" = "#476993",
"1-5" = "#ad5b9c", # low x, high y
"2-5" = "#955898",
"3-5" = "#7c5592",
"4-5" = "#60528d",
"5-5" = "#434e87" # high x, high y
)