You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This notebook extends our `leaflet` experience to include both multi-layer maps as well as thematic choropleth maps.
11
+
This notebook expands mapping to two new packages - `ggplot2` and `tmap`. We'll focus on thematic choropleth mapping today.
12
12
13
13
## Dependencies
14
14
This notebook requires a variety of packages for working with spatial data:
15
15
16
16
```{r load-packages}
17
17
# tidyverse packages
18
18
library(dplyr) # data wrangling
19
+
library(ggplot2) # plotting
19
20
20
21
# spatial packages
21
-
library(leaflet) # interactive maps
22
22
library(mapview) # preview spatial data
23
23
library(sf) # spatial data tools
24
-
library(tigris) # TIGER/Line data access
24
+
library(tigris) # access TIGER/Line shapefile data
25
+
library(tmap) # mapping
25
26
26
27
# other packages
27
28
library(here) # file path management
@@ -32,14 +33,6 @@ library(RColorBrewer) # color palettes
32
33
First, we need to load up our data. This is review from the first session, and so we've pre-filled the code for you. We'll automatically re-project the data as well (also review):
33
34
34
35
```{r load-data}
35
-
# point data 1 - Violent Crime in the Shaw Neighborhood
Now, take a few moments using your *console* and explore each of these data sets using the `mapview()` function!
52
-
53
44
## Download a Bit of Extra Data
54
-
We'll supplement the data we've loaded with some boundary data for a four county region in the St. Louis area (the City, the County, St. Charles County, and Jefferson County).
55
-
56
-
We'll use the `tigris` package to do this. Using `tigris`, you can download most of the common spatial data sets published by the U.S. Census Bureau that reflect both administrative boundaries as well as elements of our physical and human geography. However, this package cannot be used to download population data (that is the purpose of `tidycensus`).
57
-
58
-
The pipelines read as follows:
59
-
60
-
1. We'll assign to our new object `region` the result of the following pipeline.
61
-
2. First, we'll download county boundaries for Missouri (FIPS Code 29), *then*
62
-
3. We'll select the `GEOID` and `NAMELSAD` columns using the `dplyr``select()` function, *then*
63
-
4. We'll keep only the observations that match the GEOID codes for the select counties using the `dplyr``filter()` function, *then*
64
-
5. We'll re-project our data.
45
+
We'll use the same process as last week to create boundary data for both the city and the region:
65
46
66
47
```{r load-counties}
67
48
region <- counties(state = 29) %>%
@@ -72,136 +53,129 @@ region <- counties(state = 29) %>%
72
53
city <- filter(region, GEOID == "29510")
73
54
```
74
55
75
-
## More with Point Data
76
-
Last session, we made some simple point maps. Today, we want to extend those skills by mapping multiple point layers. We're going to start with the Shaw crime data and build a map together. First, we need to separate out two categories of crimes - homicides and aggravated assaults. We'll use the `dplyr``filter()` function to do this:
56
+
## Simple Maps with `ggplot2`
57
+
### Basic Mapping of Geometric Objects
58
+
`ggplot2` is the premier graphics package for `R`. It is an incredibly powerful visualization tool that increasingly supports spatial work and mapping. The basic `ggplot2` workflow requires chaining together functions with the `+` sign.
59
+
60
+
We'll start by creating a `ggplot2` object with the `ggplot()` function, and then adding a "geom", which provides `ggplot2` instructions on how our data should be visualized. We can read these like paragraphs:
61
+
62
+
1. First, we create an empty `ggplot2` object, **then**
63
+
2. we add the `nhood` data and visualize its geometry.
64
+
65
+
```{r ggplot2-nhoodSimple}
66
+
ggplot() +
67
+
geom_sf(data = nhood, fill = "#bababa")
68
+
```
69
+
70
+
You can see empty spaces where there are major parks - if we wanted to give these a background color, we could add the `city` layer under our `nhood` layer. We can also add the `city` layer again on top to give the city border a pronounced outline. `ggplot2` relies on layering different geoms to produce complicated plots. We can assign each geom a specific set of aesthetic characteristics and use data from different objects.
If we wanted to start to map data instead of just the geometric properties, we would specify an "aesthetic mapping" using `mapping= aes()` in the geom of interest. Here, we create a fill that is the product of taking the population in 2017 and normalizing it by square kilometers as we did in the `leaflet` section above. We provide additional instructions about how our data should be colored with the `scale_fill_distiller()` function, which gives us access to the `RColorBrewer` palettes.
89
+
90
+
```{r ggplot2-nhoodFull}
91
+
ggplot() +
92
+
geom_sf(data = city, fill = "#ffffff", color = NA) +
geom_sf(data = city, fill = NA, color = "#000000", size = .75) +
95
+
scale_fill_distiller(palette = "Greens", trans = "reverse", name = "Population per\nSquare Kilometer") +
96
+
labs(
97
+
title = "Population Density (2017)",
98
+
subtitle = "Neighborhoods in St. Louis, MO",
99
+
caption = "Map by Christopher Prener, Ph.D."
100
+
) +
101
+
theme_minimal()
140
102
```
141
103
142
-
## Making Choropleth Maps
143
-
We can also create thematic choropleth maps that map quantities using `leaflet`. We'll use this as a way to demonstrate how to overlay polygons on top of each other as well.
144
-
145
-
Instead of `addCircleMarkers()` or `addMarkers()`, we'll use `addPolygons()` with some of the following options:
146
-
147
-
*`color` - outline ("stroke") color for each polygon
148
-
*`weight` - stroke width
149
-
*`opacity` - stroke opacity
150
-
*`smoothFactor` - allows `leaflet` to simplify polygons depending on zoom
151
-
*`fillOpacity` - fill opacity
152
-
*`fillColor` - creates the fill itself
153
-
*`highlightOptions` - creates effect when mouse drags over specific polygons
`tmap` uses a similar logic to `ggplot2` - it layers elements on top of each other to produce maps. It is dedicated to working with spatial data, however, and has some features that `ggplot2` does not.
122
+
123
+
### Basic Mapping of Geometric Objects
124
+
We'll start with a basic map that, like we have previously, just display the geometry of the city's neighborhoods. Similar to `ggplot2`, functions are chained together with the `+` sign. We can read these like paragraphs:
125
+
126
+
1. First, we take the `nhood` data, **then**
127
+
2. we create our `tmap` layer out of its shape, **then**
128
+
3. we add a fill using our layer, **then**
129
+
4. we add borders using our layer.
130
+
131
+
```{r tmap-simple}
132
+
nhood %>%
133
+
tm_shape() +
134
+
tm_fill() +
135
+
tm_borders()
207
136
```
137
+
138
+
### Mapping Quantities with `tmap`
139
+
Like `ggplot2`, we can plot quantities using the `tm_polygons()` function. The `palette` argument accepts names of both `RColorBrewer` and `viridis` palettes. `tmap` also contains a number of tools for creating map layouts that "feel" more like desktop GIS outputs.
140
+
141
+
```{r tmap-nhoodFull}
142
+
tm_shape(city) +
143
+
tm_fill(fill = "#ebebeb") +
144
+
tm_shape(nhood) +
145
+
tm_polygons(col = "pop17",
146
+
palette = "viridis",
147
+
style = "jenks",
148
+
convert2density = TRUE,
149
+
title = "Population per\nSquare Kilometer") +
150
+
tm_shape(city) +
151
+
tm_borders(lwd = 2) +
152
+
tm_scale_bar() +
153
+
tm_layout(
154
+
title = "Population Density (2017)",
155
+
frame = FALSE,
156
+
legend.outside = TRUE,
157
+
legend.position = c("left", "bottom"))
158
+
```
159
+
Now, it is your turn to repeat this process. Create a map layout for the `covid` data, mapping `case_rate` again. (Hint: you won't need to set `convert2density` to `TRUE`)
160
+
161
+
```{r tmap-covidFull}
162
+
tm_shape(region) +
163
+
tm_fill(fill = "#ebebeb") +
164
+
tm_shape(covid) +
165
+
tm_polygons(col = "case_rate",
166
+
palette = "RdPu",
167
+
style = "jenks",
168
+
convert2density = FALSE,
169
+
title = "Cases per 1,000 Per Residents") +
170
+
tm_shape(region) +
171
+
tm_borders(lwd = 2) +
172
+
tm_scale_bar() +
173
+
tm_layout(
174
+
title = "Reported COVID-19 Cases\nby ZIP Code",
175
+
frame = FALSE,
176
+
legend.outside = TRUE,
177
+
legend.position = c("left", "bottom"))
178
+
```
179
+
180
+
## Saving Maps
181
+
There are two processes for saving maps, one for `ggplot2` and one for `tmap`. `ggplot2` uses `ggsave()` while `tmap` uses `tmap_save()`.
0 commit comments