This table shows the population, land area, population density, and density category for each Tennessee county. The table allows you to compare how large the population is among counties. The findings show that counties in the High Density category have substantially more residents than counties in the Medium Density or Low Density categories. According to the data, Tennessee’s population is not evenly distributed since a few counties have significantly higher population densities than the majority of the state’s counties.
The data shown on this table came from the U.S. Census Bureau’s American Community Survey. For more information on this topic, please see the ACS Website.
Here’s a look at the content:
| County | CurrentPop | EarlierPop | Region | Change | Percent_change | Square_Miles | Density | Density_Category |
|---|---|---|---|---|---|---|---|---|
| Davidson | 715388 | 598184 | Davidson | 117204 | 0.1959330 | 504 | 1419.42 | High Density |
| Rutherford | 360646 | 292425 | Doughnut | 68221 | 0.2332940 | 620 | 581.69 | High Density |
| Williamson | 260351 | 208242 | Doughnut | 52109 | 0.2502329 | 583 | 446.57 | Medium Density |
| Sumner | 204424 | 174773 | Doughnut | 29651 | 0.1696544 | 529 | 386.43 | Medium Density |
| Wilson | 158805 | 129918 | Doughnut | 28887 | 0.2223479 | 571 | 278.12 | Medium Density |
| Maury | 107791 | 88738 | Non-doughnut | 19053 | 0.2147107 | 613 | 175.84 | Medium Density |
| Robertson | 75539 | 67517 | Doughnut | 8022 | 0.1188145 | 476 | 158.70 | Medium Density |
| Cheatham | 41829 | 39087 | Doughnut | 2742 | 0.0701512 | 302 | 138.51 | Medium Density |
| Dickson | 55983 | 51608 | Non-doughnut | 4375 | 0.0847737 | 490 | 114.25 | Medium Density |
| Trousdale | 11957 | 10131 | Non-doughnut | 1826 | 0.1802389 | 114 | 104.89 | Medium Density |
| Macon | 26240 | 23261 | Non-doughnut | 2979 | 0.1280684 | 307 | 85.47 | Low Density |
| Smith | 20389 | 19389 | Non-doughnut | 1000 | 0.0515756 | 314 | 64.93 | Low Density |
| Cannon | 14818 | 13958 | Non-doughnut | 860 | 0.0616134 | 266 | 55.71 | Low Density |
| Hickman | 25436 | 24561 | Non-doughnut | 875 | 0.0356256 | 612 | 41.56 | Low Density |
# ==================================================
# Step 1: Install (if necessary) and load the tidyverse package
# ==================================================
if (!requireNamespace("tidyverse", quietly = TRUE)) {
install.packages("tidyverse")
library(tidyverse)
}
if (!requireNamespace("knitr", quietly = TRUE)) {
install.packages("knitr")
}
if (!requireNamespace("kableExtra", quietly = TRUE)) {
install.packages("kableExtra")
}
library(tidyverse)
library(knitr)
library(kableExtra)
# ==================================================
# Step 2: Create a vector containing county names
# ==================================================
County <- c("Cannon", "Cheatham", "Davidson", "Dickson", "Hickman", "Macon",
"Maury", "Robertson", "Rutherford", "Smith", "Sumner", "Trousdale",
"Williamson", "Wilson")
# ==================================================
# Step 3: Create a vector containing current population values
# ==================================================
CurrentPop <- c(14818, 41829, 715388, 55983, 25436, 26240, 107791, 75539,
360646, 20389, 204424, 11957, 260351, 158805)
# ==================================================
# Step 4: Create a vector containing earlier population values
# ==================================================
EarlierPop <- c(13958, 39087, 598184, 51608, 24561, 23261, 88738, 67517,
292425, 19389, 174773, 10131, 208242, 129918)
# ==================================================
# Step 5: Create a vector identifying each county's region category
# ==================================================
Region <- c("Non-doughnut", "Doughnut", "Davidson", "Non-doughnut",
"Non-doughnut", "Non-doughnut", "Non-doughnut", "Doughnut",
"Doughnut", "Non-doughnut", "Doughnut", "Non-doughnut",
"Doughnut", "Doughnut")
# ==================================================
# Step 6: Combine all vectors into a data frame
# ==================================================
Population <- data.frame(
County,
CurrentPop,
EarlierPop,
Region
)
# ==================================================
# Step 7: Display the original Population data frame
# ==================================================
Population
# ==================================================
# Step 8: Sort the Population data frame by CurrentPop
# in descending order
# ==================================================
Population <- Population %>%
arrange(desc(CurrentPop))
# ==================================================
# Step 9: Display the sorted Population data frame
# ==================================================
Population
# ==================================================
# Step 10: Add a Change variable showing population growth
# ==================================================
Population <- Population %>%
mutate(Change = CurrentPop - EarlierPop)
# ==================================================
# Step 11: Display the updated Population data frame
# ==================================================
Population
# ==================================================
# Step 12: Create a data frame containing only
# the County and Change variables
# ==================================================
Change_only <- Population %>%
select(County, Change)
# ==================================================
# Step 13: Sort the Change_only data frame by
# Change in descending order
# ==================================================
Change_only <- Change_only %>%
arrange(desc(Change))
# ==================================================
# Step 14: Display the Change_only data frame
# ==================================================
Change_only
# ==================================================
# Step 15: Create a Doughnut data frame containing
# only Davidson and Doughnut region counties
# ==================================================
Doughnut <- Population %>%
filter(Region == "Davidson" | Region == "Doughnut")
# ==================================================
# Step 16: Sort the Doughnut data frame by Change
# in descending order
# ==================================================
Doughnut <- Doughnut %>%
arrange(desc(Change))
# ==================================================
# Step 17: Display the Doughnut data frame
# ==================================================
Doughnut
# ==================================================
# Step 18: Create a Summary data frame that totals
# population values by Region
# ==================================================
Summary <- Population %>%
group_by(Region) %>%
summarize(
CurrentPop = sum(CurrentPop),
EarlierPop = sum(EarlierPop),
Change = sum(Change)
)
# ==================================================
# Step 19: Display the Summary data frame
# ==================================================
Summary
# ==================================================
# Step 20: Copy the Population data frame into
# a new data frame called Population_v2
# ==================================================
Population_v2 <- Population
# ==================================================
# Step 21: Create a Percent_change variable
# ==================================================
Population_v2 <- Population_v2 %>%
mutate(Percent_change = Change / EarlierPop)
# ==================================================
# Step 22: Sort Population_v2 by Percent_change
# in descending order
# ==================================================
Population_v2 <- Population_v2 %>%
arrange(desc(Percent_change))
# ============================================================
# Step 23: Download Tennessee County Gazetteer File
# ============================================================
TN_Counties <- read_delim(
"https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_counties_47.txt",
delim = "|",
show_col_types = FALSE
)
# ============================================================
# Step 24: Create Land_Area Data Frame
# ============================================================
Land_Area <- TN_Counties %>%
transmute(
County = str_remove(NAME, " County"),
Square_Miles = round(ALAND_SQMI)
)
# ============================================================
# Step 25: Add Square_Miles to Population_v2
# ============================================================
Population_v2 <- Population_v2 %>%
left_join(Land_Area, by = "County")
# ============================================================
# Step 26: Create Density Variable
# ============================================================
Population_v2 <- Population_v2 %>%
mutate(Density = round(CurrentPop / Square_Miles, 2))
# ============================================================
# Step 27: Create Density_Category Variable
# ============================================================
Population_v2 <- Population_v2 %>%
mutate(
Density_Category = case_when(
Density >= 500 ~ "High Density",
Density >= 100 & Density < 500 ~ "Medium Density",
TRUE ~ "Low Density"
)
)
# ============================================================
# Step 28: Sort by Density
# ============================================================
Population_v2 <- Population_v2 %>%
arrange(desc(Density))
# ==================================================
# Step 29: Display the Population_v2 data frame
# ==================================================
Population_v2
# ==================================================
# Step 30: Create and display a formatted table
# for the Population_v2 data frame
# ==================================================
Population_v2_table <- kable(Population_v2) %>%
kable_styling(full_width = FALSE)
Population_v2_table
# ==================================================
# Step 31: Create and display a formatted table
# for the Change_only data frame
# ==================================================
Change_only_table <- kable(Change_only) %>%
kable_styling(full_width = FALSE)
Change_only_table
# ==================================================
# Step 32: Create and display a formatted table
# for the Doughnut data frame
# ==================================================
Doughnut_table <- kable(Doughnut) %>%
kable_styling(full_width = FALSE)
Doughnut_table
# ==================================================
# Step 33: Create and display a formatted table
# for the Summary data frame
# ==================================================
Summary_table <- kable(Summary) %>%
kable_styling(full_width = FALSE)
Summary_table
# ============================================================
# Step 34: Create and display a formatted table
# for the Population_v2 data frame
# ============================================================
Population_v2_table <- kable(Population_v2) %>%
kable_styling(full_width = FALSE)
Population_v2_table
# ============================================================
# Download Tennessee County Gazetteer File
# ============================================================
# Import county land-area data from the U.S. Census Bureau.
TN_Counties <- read_delim(
"https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2025_Gazetteer/2025_gaz_counties_47.txt",
delim = "|",
show_col_types = FALSE
)
# ============================================================
# Create Land_Area Data Frame
# ============================================================
# Keep county name and land area in square miles.
# Remove " County" from county names.
# Round land area to the nearest whole square mile.
Land_Area <- TN_Counties %>%
transmute(
County = str_remove(NAME, " County"),
Square_Miles = round(ALAND_SQMI)
)
# ============================================================
# Display Results
# ============================================================
# View the completed land-area data frame.
Land_Area