Pull the slider left or right to switch between showing the borders of Rutherford County’s voting precincts and the borders of Rutherford County’s five Tennessee House districts. Among precincts, darker-shading indicates precincts with larger counts of minority voters. Click or tap a district or precinct for details.
Demographic data come from the 2020 Census. District and precinct borders come from the Tennessee Comptroller. The map was produced using R and various packages including the geomander.
# Required packages
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("mapview")) install.packages("mapview")
if (!require("sf")) install.packages("sf")
if (!require("leaflet")) install.packages("leaflet")
if (!require("leaflet.extras2")) install.packages("leaflet.extras2")
if (!require("geomander")) install.packages("geomander")
library(tidyverse)
library(mapview)
library(sf)
library(leaflet)
library(leafpop)
library(geomander)
# Data gathering
# Read TN 2024 precinct shapefile
my_sf <- read_sf("Voting_Precincts_5_31_24.shp")
RC_sf <- my_sf %>%
filter(COUNTY == 149)
# Create "sync" file for matching matches_id field
# to precinct label field
sync <- RC_sf
sync <- sync %>%
st_drop_geometry(sync) %>%
mutate(matches_id = row_number()) %>%
mutate(Precinct = NEWVOTINGP) %>%
select(matches_id, Precinct)
block <- create_block_table(state = 'TN', county = '149', year = 2020)
matches <- geo_match(from = block, to = RC_sf)
prec <- block2prec(block_table = block, matches = matches)
precgeo <- block2prec(block_table = block, matches = matches, geometry = TRUE)
precgeo <- merge(precgeo,sync,
by="matches_id",
all.x = TRUE)
precgeo <- precgeo %>%
mutate(Pct_Nonwhite = round(1-(precgeo$vap_white/precgeo$vap),2)) %>%
mutate(Voters = vap) %>%
mutate(Nonwhite = vap - vap_white) %>%
select(Precinct,
Voters,
Nonwhite,
Pct_Nonwhite,
geometry)
# Reading TN House districts map from
# https://tn-tnmap.opendata.arcgis.com/search?tags=boundaries
TNHouseDistricts <- st_read("TN_House_Districts.shp")
RCHoueDistricts <- TNHouseDistricts %>%
filter(DISTRICT == "13"|
DISTRICT == "49"|
DISTRICT == "37"|
DISTRICT == "34"|
DISTRICT == "48")
# Mapmaking
mypalette = colorRampPalette(c('lightgray', 'black'))
Precincts <- mapview(
precgeo,
zcol = "Nonwhite",
map.types = ("OpenStreetMap"),
legend = "FALSE",
col.regions = mypalette,
at = seq(0, 7000, 1),
alpha.regions = .5,
layer.name = "Precincts",
popup = popupTable(
precgeo,
feature.id = FALSE,
row.numbers = FALSE,
zcol = c("Precinct", "Voters", "Nonwhite", "Pct_Nonwhite")
)
)
Combined <- mapview(
precgeo,
zcol = "Nonwhite",
map.types = ("OpenStreetMap"),
legend = "FALSE",
col.regions = mypalette,
at = seq(0, 7000, 7),
alpha.regions = .5,
layer.name = "Nonwhite",
popup = popupTable(
precgeo,
feature.id = FALSE,
row.numbers = FALSE,
zcol = c("Precinct", "Voters", "Nonwhite", "Pct_Nonwhite")
)
) + mapview(
RCHoueDistricts,
zcol = "DISTRICT",
map.types = ("OpenStreetMap"),
layer.name = "District",
popup = popupTable(
RCHoueDistricts,
feature.id = FALSE,
row.numbers = FALSE,
zcol = c("DISTRICT", "NAME", "POPULATION")
)
)
Combined | Precincts
Same as above, but with block-level data in place of precinct-level data.