Overview

Use this R script to specify a U.S. county and two mutually exclusive five-year time periods, then extract and map county-division-level variable estimates and error margins for the specified county and time periods from the U.S. Census Bureau API. The script will produce a “slider map” that allows a user to compare data from both time periods by dragging a horizontal slider bar across the map. Want to skip the explanations, copy the script in one chunk, and go? Scroll down to “The complete script.”

Loading required packages

Several packages are required, including TidyCensus and mapview. This code checks to see whether the required packages are installed already, installs them if they aren’t, and loads them into memory.

if (!require("tidyverse")) install.packages("tidyverse")
if (!require("tidycensus")) install.packages("tidycensus")
if (!require("sf")) install.packages("sf")
if (!require("mapview")) install.packages("mapview")
if (!require("leaflet.extras2")) install.packages("leaflet.extras2")
if (!require("scales")) install.packages("scales")


library(tidycensus)
library(tidyverse)
library(sf)
library(mapview)
library(leaflet.extras2)
library(scales)
library(leaflet)
library(leafpop)
options(tigris_use_cache = TRUE)

Census API authentication

The U.S. Census Bureau’s API requires an API key. You can get one for free at https://api.census.gov/data/key_signup.html. Once you get yours, replace PastYourAPIKeyBetwenTheseQuoteMarks with your API key. Also, delete the # from the front of the # census_api_key code.

# NOTE: Obtain a Census API key from 
# https://api.census.gov/data/key_signup.html
# and replace the census_api_key code line's 
# PastYourAPIKeyBetwenTheseQuoteMarks text with your
# API key. Also, delete the "#" from the front of the 
# census_api_key code.

#census_api_key("PasteYourAPIKeyBetwenTheseQuoteMarks")

Census API variable catalogs

Just about any variable available from the Census API can be plugged into the script. The code retrieves variable name catalogs for the Detailed, Subject, and Profile tables variables for a specified five-year American Community Survey dataset. You can search the tables to find variables of interest to you. The default year, 2021, will retrieve variables for the 2017-2021 five-year ACS dataset. You can change the year, if preferred.

DetailedTables <- load_variables(2021, "acs5", cache = TRUE)
SubjectTables <- load_variables(2021, "acs5/subject", cache = TRUE)
ProfileTables <- load_variables(2021, "acs5/profile", cache = TRUE)

Fetching the data

This code retrieves specified data for both of two specified years. The default years are 2016 and 2021. You may specify other years, if preferred. The median rent (B25064_001) estimates have been specified by default. You may edit these variable codes to specify other variables, if preferred. Two datasets are created - one for the earlier period (MapData1), and one for the later period (MapData2). Lines marked #Customizable can be customized to fetch data for other counties in other states and during other years.

MapData1 <- get_acs(geography = "county subdivision",
                    state = "TN", #Customizable
                    county = "Rutherford", #Customizable
                    variables = c(Variable1 = "B25064_001"), #Customizable
                    year = 2016, #Customizable
                    survey = "acs5",
                    output = "wide",
                    geometry = TRUE)
## Getting data from the 2012-2016 5-year ACS
MapData2 <- get_acs(geography = "county subdivision",
                   state = "TN", #Customizable
                   county = "Rutherford", #Customizable
                   variables = c(Variable2 = "B25064_001"), #Customizable
                   year = 2021,
                   survey = "acs5",
                   output = "wide",
                   geometry = TRUE)
## Getting data from the 2017-2021 5-year ACS
mapviewOptions(basemaps.color.shuffle = FALSE)

Calculating change and significance

This code merges the MapData1 and MapData2 datasets, then calculates the specified variable’s change from the first period to the second, and the significance of the change.

MapData1_nogeo <- st_drop_geometry(MapData1)
ChangeData <- merge(MapData2, MapData1_nogeo, by = "GEOID")
ChangeData$County <- ChangeData$NAME.x
ChangeData$Change <- ChangeData$Variable2E - ChangeData$Variable1E
ChangeData$Sig <- significance(ChangeData$Variable1E,
                               ChangeData$Variable2E,
                               ChangeData$Variable1M,
                               ChangeData$Variable2M,
                               clevel = 0.90)
ChangeData$Significance <- ifelse(ChangeData$"Sig" == "TRUE",
                                  "Significant",
                                  "Nonsignificant")

Producing the map

This code produces two maps, one showing levels of the specified variable during the most recent time period, and a second showing the specified variables levels of change from the earlier time period. Finally, it combines the two maps into a single slider map. Lines marked #Customizable can be edited to customize the titles on the map’s keys.

CurrentMap <- mapview(MapData2, zcol = "Variable2E", 
                   col.regions = RColorBrewer::brewer.pal(9, "Blues"), alpha.regions = .5,
                   layer.name = "Median rent, 2017-21",#Customizable
                   popup = FALSE
)
## Warning: Found less unique colors (9) than unique zcol values (21)! 
## Interpolating color vector to match number of zcol values.
ChangeMap <- mapview(ChangeData,
        zcol = "Change",
        col.regions = RColorBrewer::brewer.pal(9, "Greys"), alpha.regions = .5,
        layer.name = "Change from 2012-16",#Customizable
        popup = popupTable(ChangeData,
                           zcol = c("Change",
                                    "Significance")))
## Warning: Found less unique colors (9) than unique zcol values (21)! 
## Interpolating color vector to match number of zcol values.
CurrentMap | ChangeMap

The complete script

Just here for the script? You’ll find it below, all in one chunk, ready to be copied and pasted.

# Installing required packages

if (!require("tidyverse")) install.packages("tidyverse")
if (!require("tidycensus")) install.packages("tidycensus")
if (!require("sf")) install.packages("sf")
if (!require("mapview")) install.packages("mapview")
if (!require("leaflet.extras2")) install.packages("leaflet.extras2")
if (!require("scales")) install.packages("scales")


library(tidycensus)
library(tidyverse)
library(sf)
library(mapview)
library(leaflet.extras2)
library(scales)
library(leaflet)
library(leafpop)
options(tigris_use_cache = TRUE)

# NOTE: Obtain a Census API key from 
# https://api.census.gov/data/key_signup.html
# and replace the census_api_key code line's 
# PastYourAPIKeyBetwenTheseQuoteMarks text with your
# API key. Also, delete the "#" from the front of the 
# census_api_key code.

#census_api_key("PasteYourAPIKeyBetwenTheseQuoteMarks")

# Getting ACS variable info
# Change "2021" to your preferred year.

DetailedTables <- load_variables(2021, "acs5", cache = TRUE)
SubjectTables <- load_variables(2021, "acs5/subject", cache = TRUE)
ProfileTables <- load_variables(2021, "acs5/profile", cache = TRUE)

# Getting the map data

MapData1 <- get_acs(geography = "county subdivision",
                    state = "TN", #Customizable
                    county = "Rutherford", #Customizable
                    variables = c(Variable1 = "B25064_001"), #Customizable
                    year = 2016, #Customizable
                    survey = "acs5",
                    output = "wide",
                    geometry = TRUE)

MapData2 <- get_acs(geography = "county subdivision",
                   state = "TN", #Customizable
                   county = "Rutherford", #Customizable
                   variables = c(Variable2 = "B25064_001"), #Customizable
                   year = 2021,
                   survey = "acs5",
                   output = "wide",
                   geometry = TRUE)

mapviewOptions(basemaps.color.shuffle = FALSE)

# Calculating change

MapData1_nogeo <- st_drop_geometry(MapData1)
ChangeData <- merge(MapData2, MapData1_nogeo, by = "GEOID")
ChangeData$County <- ChangeData$NAME.x
ChangeData$Change <- ChangeData$Variable2E - ChangeData$Variable1E
ChangeData$Sig <- significance(ChangeData$Variable1E,
                               ChangeData$Variable2E,
                               ChangeData$Variable1M,
                               ChangeData$Variable2M,
                               clevel = 0.90)
ChangeData$Significance <- ifelse(ChangeData$"Sig" == "TRUE",
                                  "Significant",
                                  "Nonsignificant")

CurrentMap <- mapview(MapData2, zcol = "Variable2E", 
                   col.regions = RColorBrewer::brewer.pal(9, "Blues"), alpha.regions = .5,
                   layer.name = "Median rent, 2017-21",#Customizable
                   popup = FALSE
)

ChangeMap <- mapview(ChangeData,
        zcol = "Change",
        col.regions = RColorBrewer::brewer.pal(9, "Greys"), alpha.regions = .5,
        layer.name = "Change from 2012-16",#Customizable
        popup = popupTable(ChangeData,
                           zcol = c("Change",
                                    "Significance")))
CurrentMap | ChangeMap