Mapping Census data

You can follow along with the 04_tidycensus_viz file in the nicar-2024-tidycensus project folder that you downloaded in the intro link.

The repo containing the data and scripts for this section is on Github. To install those files, run the lines of code below.

#install.packages("usethis")
usethis::use_course("https://github.com/r-journalism/nicar-2024-tidycensus/archive/master.zip")

# Run this in the console of RStudio
file.edit("04_tidycensusviz.R")

To follow along with this walkthrough, simply run the lines of code in the gray boxes in the R console. Be sure to run them in order. If you run into an error, it may be because you skipped running some preceding lines of code.

Load libraries

library(tidyverse)
library(tidycensus)
library(sf)
library(mapview)

“Spatial” ACS data

  • One of the best features of tidycensus is the argument geometry = TRUE, which gets you the correct Census geometries with no hassle

  • get_acs() with geometry = TRUE returns a spatial Census dataset containing simple feature geometries;

Downloading “Spatial” ACS data

  • geometry = TRUE does the hard work for you of acquiring and pre-joining spatial Census data
median_value_map <- get_acs(
  geography = "tract",
  state= "MD",
  county="Baltimore City",
  variables = "B25077_001", # median values of home
  year = 2022,
  geometry = TRUE
)
Getting data from the 2018-2022 5-year ACS
Downloading feature geometry from the Census website.  To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.

  • We get back a _simple features data frame
median_value_map
Simple feature collection with 199 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -76.71152 ymin: 39.19721 xmax: -76.52945 ymax: 39.3722
Geodetic CRS:  NAD83
First 10 features:
         GEOID estimate   moe                       geometry
1  24510151200    99400 51399 MULTIPOLYGON (((-76.66506 3...
2  24510270702   218000 17102 MULTIPOLYGON (((-76.57356 3...
3  24510271802   114800 40020 MULTIPOLYGON (((-76.68352 3...
4  24510272004   210600 76149 MULTIPOLYGON (((-76.69473 3...
5  24510090700    78700 27019 MULTIPOLYGON (((-76.60149 3...
6  24510180300   209900 18838 MULTIPOLYGON (((-76.63817 3...
7  24510270703   229600 35850 MULTIPOLYGON (((-76.56192 3...
8  24510010300   338900 21159 MULTIPOLYGON (((-76.58472 3...
9  24510060300   280700 21590 MULTIPOLYGON (((-76.58773 3...
10 24510260203   152800 11899 MULTIPOLYGON (((-76.55386 3...

Exploring Census data interactively

library(mapview)

mapview(median_value_map)

Creating a shaded map with zcol

mapview(median_value_map, zcol = "estimate")

Try all the code again in a different county

median_value_map <- get_acs(
  geography = "tract",
  state= "MD", # Changeme
  county="Baltimore County", # Change me
  variables = "B25077_001", # median values of home
  year = 2022,
  geometry = TRUE
)

mapview(median_value_map, zcol = "estimate")

Migration data

Let’s map some county-to-county migration data from the Census! [Link]

county_migration <- get_flows(
  geography = "county",
  county = "Baltimore City",
  state = "MD"
)
county_migration
# A tibble: 2,664 × 7
   GEOID1 GEOID2 FULL1_NAME               FULL2_NAME     variable estimate   moe
   <chr>  <chr>  <chr>                    <chr>          <chr>       <dbl> <dbl>
 1 24510  <NA>   Baltimore city, Maryland Africa         MOVEDIN       685   194
 2 24510  <NA>   Baltimore city, Maryland Africa         MOVEDOUT       NA    NA
 3 24510  <NA>   Baltimore city, Maryland Africa         MOVEDNET       NA    NA
 4 24510  <NA>   Baltimore city, Maryland Asia           MOVEDIN      1466   279
 5 24510  <NA>   Baltimore city, Maryland Asia           MOVEDOUT       NA    NA
 6 24510  <NA>   Baltimore city, Maryland Asia           MOVEDNET       NA    NA
 7 24510  <NA>   Baltimore city, Maryland Central Ameri… MOVEDIN       322   174
 8 24510  <NA>   Baltimore city, Maryland Central Ameri… MOVEDOUT       NA    NA
 9 24510  <NA>   Baltimore city, Maryland Central Ameri… MOVEDNET       NA    NA
10 24510  <NA>   Baltimore city, Maryland Caribbean      MOVEDIN       231    94
# ℹ 2,654 more rows

Downloading map data

county_map <- get_acs(
  geography = "county",
  variable = c("Population"="B03002_001"),
  geometry = TRUE
)
Getting data from the 2018-2022 5-year ACS
Downloading feature geometry from the Census website.  To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.
county_map
Simple feature collection with 3222 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -179.1467 ymin: 17.88328 xmax: 179.7785 ymax: 71.38782
Geodetic CRS:  NAD83
First 10 features:
   GEOID                           NAME   variable estimate moe
1  01069        Houston County, Alabama Population   107040  NA
2  01023        Choctaw County, Alabama Population    12669  NA
3  01005        Barbour County, Alabama Population    24877  NA
4  01107        Pickens County, Alabama Population    18925  NA
5  01033        Colbert County, Alabama Population    57270  NA
6  04012         La Paz County, Arizona Population    16681  NA
7  04001         Apache County, Arizona Population    66054  NA
8  05081  Little River County, Arkansas Population    12024  NA
9  05121      Randolph County, Arkansas Population    18619  NA
10 06037 Los Angeles County, California Population  9936690  NA
                         geometry
1  MULTIPOLYGON (((-85.71209 3...
2  MULTIPOLYGON (((-88.47323 3...
3  MULTIPOLYGON (((-85.74803 3...
4  MULTIPOLYGON (((-88.34043 3...
5  MULTIPOLYGON (((-88.13925 3...
6  MULTIPOLYGON (((-114.7312 3...
7  MULTIPOLYGON (((-110.0007 3...
8  MULTIPOLYGON (((-94.48558 3...
9  MULTIPOLYGON (((-91.40687 3...
10 MULTIPOLYGON (((-118.6044 3...

Prep the migration data

county_migration_moved <- county_migration |>
  filter(variable=="MOVEDIN") |>
  filter(!is.na(GEOID2)) |>
  select(GEOID=GEOID2, migration=estimate) 

Join the migration data with the shapefile

county_map_migration <- county_map %>%
  inner_join(county_migration_moved)

mapview(county_map_migration, zcol = "migration")

Can you map migration out?


county_migration_moved <- county_migration |>
  filter(variable=="MOVEDOUT") |>
  filter(!is.na(GEOID2)) |>
  select(GEOID=GEOID2, migration=estimate) 

county_map_migration <- county_map %>%
  inner_join(county_migration_moved)

mapview(county_map_migration, zcol = "migration")

More resources