/
bivariate_palettes.Rmd
211 lines (169 loc) · 8.96 KB
/
bivariate_palettes.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
---
title: "Bivariate Palettes"
author: "Christopher Prener, Ph.D. and Branson Fox"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Bivariate Palettes}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
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.
## Included Palettes
*As of v1.0.0, `biscale` supports a dozen built-in palettes and expanded ability to utilize custom palettes. For five of these palettes, there are both "primary" versions and "legacy versions."*
### Primary Palettes
All of the primary palettes listed here can be used with two-by-two (`dim = 2`), three-by-three (`dim = 3`), and four-by-four (`dim = 4`) maps. The palettes that contain a `2` at the end of their name are visually similar to the original, "legacy" palettes (see below) but utilize slightly different hex values for colors.
```{r echo=FALSE, out.width='100%'}
knitr::include_graphics('../man/figures/pals_primary.jpeg')
```
Most of the newly added palettes not based on legacy designs were adapted from earlier work by Branson Fox.
### Legacy Palettes
To ensure compatibility with scripts written with older versions of `biscale`, the original five palettes included in the package are still available. They can be used only for two-by-two (`dim = 2`) and three-by-three (`dim = 3`) maps.
```{r echo=FALSE, out.width='100%'}
knitr::include_graphics('../man/figures/pals_legacy.jpeg')
```
The `"DkViolet"` palette was created by [Timo Grossenbacher and Angelo Zehr](https://timogrossenbacher.ch/2019/04/bivariate-maps-with-ggplot2-and-sf/), and the other four palettes were created by [Joshua Stevens](https://www.joshuastevens.net/cartography/make-a-bivariate-choropleth-map/).
## 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:
```r
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:
```r
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:
```r
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:
```{r echo=FALSE, out.width='100%'}
knitr::include_graphics('../man/figures/manipulated_pal.jpeg')
```
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:
```{r echo=FALSE, out.width='100%'}
knitr::include_graphics('../man/figures/biscale.005.jpeg')
```
Utilizing both flipping axes and palette rotations also yields a considerable change from the original:
```{r echo=FALSE, out.width='100%'}
knitr::include_graphics('../man/figures/biscale.006.jpeg')
```
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](https://bvgsoftware.com) [Bivariate Choropleth Color Generator](https://observablehq.com/@benjaminadk/bivariate-choropleth-color-generator) if you want to experiment with creating your own palettes. [Joshua Steves' blogpost from 2015](https://www.joshuastevens.net/cartography/make-a-bivariate-choropleth-map/) 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.
```r
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.
```r
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.
```r
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:
```r
# 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()`:
```r
# 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:
```r
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:
```r
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
)
```