| Estimates by County |
| (2019–2023 ACS 5-Year ACS) |
| County |
Percent (%) |
Percent MOE |
Count |
Count MOE |
| Williamson |
61.8 |
1.2 |
167,620 |
266 |
| Davidson |
47.3 |
0.7 |
493,272 |
113 |
| Wilson |
37.2 |
1.2 |
105,888 |
312 |
| Rutherford |
34.4 |
1.1 |
223,304 |
85 |
| Sumner |
32.6 |
1.2 |
138,609 |
121 |
| Maury |
26.5 |
1.5 |
73,091 |
272 |
| Cheatham |
25.1 |
2.3 |
29,614 |
147 |
| Dickson |
21.4 |
1.9 |
38,559 |
203 |
| Robertson |
21.1 |
1.6 |
50,891 |
165 |
| Smith |
17.9 |
2.3 |
14,180 |
77 |
| Cannon |
16.9 |
3.2 |
10,397 |
97 |
| Hickman |
13.6 |
2.2 |
18,044 |
107 |
| Macon |
11.8 |
2.3 |
17,135 |
251 |
| Trousdale |
10.1 |
2.7 |
8,490 |
285 |
# ============================================================
# 0. INSTALL AND LOAD REQUIRED PACKAGES
# ============================================================
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("tidycensus")) install.packages("tidycensus")
if (!require("sf")) install.packages("sf")
if (!require("leaflet")) install.packages("leaflet")
if (!require("leaflet.extras2")) install.packages("leaflet.extras2")
if (!require("gt")) install.packages("gt")
if (!require("gtExtras")) install.packages("gtExtras")
if (!require("plotly")) install.packages("plotly")
library(tidyverse)
library(tidycensus)
library(sf)
library(leaflet)
library(leaflet.extras2)
library(gt)
library(gtExtras)
library(plotly)
# ============================================================
# 1. CENSUS API KEY
# ============================================================
census_api_key("af51792d862d91d8384d3c1b52a2a16f42c4c441")
# ============================================================
# 2. LOAD ACS CODEBOOKS
# ============================================================
DetailedTables <- load_variables(2023, "acs5", cache = TRUE)
SubjectTables <- load_variables(2023, "acs5/subject", cache = TRUE)
ProfileTables <- load_variables(2023, "acs5/profile", cache = TRUE)
# ============================================================
# 3. DEFINE VARIABLES OF INTEREST
# ============================================================
VariableList <- c(
Count_ = "DP02_0059",
Percent_ = "DP02_0068P"
)
# ============================================================
# 4. FETCH COUNTY SUBDIVISION DATA (TENNESSEE)
# ============================================================
mydata <- get_acs(
geography = "county subdivision",
state = "TN",
variables = VariableList,
year = 2023,
survey = "acs5",
output = "wide",
geometry = TRUE
)
# ============================================================
# 5. CLEAN AND REFORMAT GEOGRAPHIC NAMES
# ============================================================
mydata <- mydata %>%
separate_wider_delim(
NAME,
delim = ", ",
names = c("Division", "County", "State")
) %>%
mutate(County = str_remove(County, " County"))
# ============================================================
# NOTE: Sections 6 through 8 of this script have been omitted.
# See "Practical R (Part 1)" for those sections.
# ============================================================
# ============================================================
# 9. FILTER DATA FOR MULTI-COUNTY AREA
# ============================================================
CountyNameList <- c(
"Cannon","Cheatham","Davidson","Dickson","Hickman",
"Macon","Maury","Robertson","Rutherford","Smith",
"Sumner","Trousdale","Williamson","Wilson"
)
filtereddata2 <- mydata %>%
filter(County %in% CountyNameList)
# ============================================================
# 10. MAP MULTI-COUNTY AREA (WITH COUNTY BORDERS)
# ============================================================
mapdata2 <- filtereddata2 %>%
rename(
Percent = Percent_E,
PercentEM = Percent_M,
Count = Count_E,
CountEM = Count_M
) %>%
st_as_sf() %>%
st_transform(4326)
# Get Tennessee county boundaries for overlay
county_borders <- get_acs(
geography = "county",
state = "TN",
variables = "B01001_001", # dummy population variable
year = 2023,
geometry = TRUE
) %>%
st_as_sf() %>%
st_transform(4326) %>%
mutate(County = str_remove(NAME, " County, Tennessee")) %>%
filter(County %in% CountyNameList)
# Viridis color palette
pal <- colorNumeric(
palette = "viridis",
domain = mapdata2$Percent
)
# Build leaflet map with county borders
DivisionMap2 <- leaflet(mapdata2) %>%
# Base maps
addProviderTiles("CartoDB.Positron", group = "Positron (Light)") %>%
addProviderTiles("Esri.WorldStreetMap", group = "ESRI Streets") %>%
addProviderTiles("Esri.WorldImagery", group = "ESRI Satellite") %>%
# Main polygons
addPolygons(
fillColor = ~pal(Percent),
fillOpacity = 0.7,
color = "#333333",
weight = 1,
group = "Data Layer",
popup = ~paste0(
"<b>", Division, "</b><br>",
"County: ", County, "<br>",
"Percent: ", Percent, "%<br>",
"Percent MOE: ±", PercentEM, "<br>",
"Count: ", Count, "<br>",
"Count MOE: ±", CountEM
)
) %>%
# County borders overlay
addPolylines(
data = county_borders,
color = "black",
weight = 1,
opacity = 0.8,
group = "County Borders"
) %>%
# Legend
addLegend(
pal = pal,
values = mapdata2$Percent,
position = "topright",
title = "Percent"
) %>%
addLayersControl(
baseGroups = c(
"Positron (Light)",
"ESRI Streets",
"ESRI Satellite"
),
overlayGroups = c("Data Layer", "County Borders"),
options = layersControlOptions(
collapsed = TRUE,
position = "bottomleft" # 👈 Control position
)
)
DivisionMap2
# ============================================================
# 11. COUNTY-LEVEL TABLE FOR SELECTED COUNTIES
# ============================================================
CountyLevelData <- get_acs(
geography = "county",
state = "TN",
variables = VariableList,
year = 2023,
survey = "acs5",
output = "wide",
geometry = FALSE
)
SelectedCounties <- CountyLevelData %>%
mutate(NAME = str_remove(NAME, " County, Tennessee")) %>%
filter(NAME %in% CountyNameList) %>%
select(NAME, Percent_E, Percent_M, Count_E, Count_M) %>%
rename(
County = NAME,
Percent = Percent_E,
PctMOE = Percent_M,
Count = Count_E,
CountMOE = Count_M
) %>%
arrange(desc(Percent))
CountyTable <- SelectedCounties %>%
gt() %>%
gt_theme_espn() %>%
cols_label(
Percent = "Percent (%)",
PctMOE = "Percent MOE",
Count = "Count",
CountMOE = "Count MOE"
) %>%
fmt_number(columns = c(Percent, PctMOE), decimals = 1) %>%
fmt_number(columns = c(Count), decimals = 0, use_seps = TRUE) %>%
tab_header(
title = "Estimates by County",
subtitle = "(2019–2023 ACS 5-Year ACS)"
)
CountyTable