The American Community Survey (ACS) is an ongoing survey conducted by the U.S. Census Bureau that collects detailed information about the nation (U.S. Census Bureau, 2026). The series of maps and charts in this report show how ACS data can be accessed with R’s tidycensus package. This report focuses on Colorado’s percent of the population with graduate degrees in Part A and on the Denver metro area’s median home values in Part B.
The tidycensus package is designed to reduce the data preparation needed to analyze and visualize the Census data. In effect, the package fully prepares the data for exploration in the tidyverse (Walker and Herman, n.d.). Thus, the only preparation needed is to load the tidycensus library and other libraries for this report.
Prepare the work space by loading numerous packages.
library(tidycensus)
library(mapview)
library(tigris)
library(sf)
library(tidyverse)
library(RColorBrewer)
library(scales)
library(plotly)
library(ggiraph)
library(leaflet)
Part A focuses on Census data that delineates the percentage of Colorado’s population that has a graduate degree. This data is accessible via the “DP02_0066P” variable, according to the lab instructions (PSU, n.d.). Analyzing this data can answer questions such as “which Colorado counties have the largest and smallest percentages of graduate degree holders?”
# Acquire data for Colorado by county
CO_degrees <- get_acs(geography = "county",
variables = "DP02_0066P",
year = 2023,
state = "CO")
## Getting data from the 2019-2023 5-year ACS
## Using the ACS Data Profile
Sorting the ACS data in descending order reveals which Colorado counties have the largest percentages of graduate degree holders. Boulder, Pitkin, Clear Creek, Gilpin, and Broomfield counties have the largest percentages, according to the ACS 5-Year data.
# Arrange and view county estimates in descending order
arrange(CO_degrees, desc(estimate))
## # A tibble: 64 × 5
## GEOID NAME variable estimate moe
## <chr> <chr> <chr> <dbl> <dbl>
## 1 08013 Boulder County, Colorado DP02_0066P 29.4 0.9
## 2 08097 Pitkin County, Colorado DP02_0066P 26.5 4.3
## 3 08019 Clear Creek County, Colorado DP02_0066P 26.3 3.9
## 4 08047 Gilpin County, Colorado DP02_0066P 25.9 7.7
## 5 08014 Broomfield County, Colorado DP02_0066P 23.7 1.5
## 6 08035 Douglas County, Colorado DP02_0066P 22 0.8
## 7 08031 Denver County, Colorado DP02_0066P 21.9 0.6
## 8 08069 Larimer County, Colorado DP02_0066P 20.7 0.7
## 9 08117 Summit County, Colorado DP02_0066P 20 3.1
## 10 08091 Ouray County, Colorado DP02_0066P 19.5 3.2
## # ℹ 54 more rows
Whereas sorting the ACS data in ascending order reveals which Colorado counties have the smallest percentages of graduate degree holders. These counties are Lincoln, Crowley, Kit Carson, Bent, and Moffat, according to the ACS 5-Year data.
# Arrange and view county estimates in ascending order
arrange(CO_degrees, estimate)
## # A tibble: 64 × 5
## GEOID NAME variable estimate moe
## <chr> <chr> <chr> <dbl> <dbl>
## 1 08073 Lincoln County, Colorado DP02_0066P 4.5 1.4
## 2 08025 Crowley County, Colorado DP02_0066P 5.1 2.9
## 3 08063 Kit Carson County, Colorado DP02_0066P 5.3 1.7
## 4 08011 Bent County, Colorado DP02_0066P 5.4 2.1
## 5 08081 Moffat County, Colorado DP02_0066P 5.4 1.7
## 6 08071 Las Animas County, Colorado DP02_0066P 5.7 1.4
## 7 08043 Fremont County, Colorado DP02_0066P 6.1 0.9
## 8 08087 Morgan County, Colorado DP02_0066P 6.2 1.5
## 9 08009 Baca County, Colorado DP02_0066P 6.5 1.9
## 10 08033 Dolores County, Colorado DP02_0066P 6.8 4.2
## # ℹ 54 more rows
It is important to note that the information provided by the ACS are estimates that have associated margins of error. Thus, the actual counties that have the highest and lowest percentages of graduate-degree holders might be different than the counties listed above. The following plots show each county’s estimate and margin of error for its population with a graduate degree. The colors shown in the plots mimic the Colorado state flag (shown above).
A static margin-of-error plot for Colorado.
# Create the plot
CO_degrees_plot <- ggplot(CO_degrees, aes(x = estimate, y = reorder(NAME, estimate))) +
# Add error bars and symbology
geom_errorbar(aes(xmin = estimate - moe, xmax = estimate + moe),
width = 0.75,
linewidth = 0.75,
color = "blue4") +
# Change point symbology
geom_point(shape = 21,
fill = "gold1",
color = "brown3",
size = 2,
stroke = 1) +
# Clean up the y-axis by removing redunant text
scale_y_discrete(labels = function(x) str_remove(x, " County, Colorado")) +
# Add labels to the plot
labs(title = "Percent of Population with a Graduate Degree by Colorado County",
subtitle = "2019 - 2023 5-year ACS",
caption = "Figure 1: 2019-2023 5-year ACS census data acquired with R and tidycensus.
Error bars represent margin of error around estimates.",
x = "ACS Estimate with Margin of Error (%)",
y = "") +
# Use a minimal theme
theme_minimal(base_size = 10)
# View the plot
CO_degrees_plot
This margin-of-error plot can be converted to an interactive chart with the plotly package.
# Convert the margin-of-error plot to an interactive chart
ggplotly(CO_degrees_plot, tooltip = "x") %>%
# Overwrite title to include subtitle
layout(title = list(text = paste0("Percent of Population with a Graduate Degree by Colorado County",
"<br>",
"<sub>",
"<b>2019 - 2023 5-year ACS</b>")),
# Overwrite x-axis to include caption
xaxis = list(title = "ACS Estimate with Margin of Error (%)
<sub>Figure 2: 2019 - 2023 5-year ACS data acquired with R and
tidycensus. Error bars represent margin of error around estimates."),
# Increase margin to show longer x-axis
margin =list(b=80))
The static margin-of-error plot can be converted to an interactive chart with the ggiraph package as well.
# Create an interactive margin-of-error plot
CO_plot_ggiraph <- ggplot(CO_degrees, aes(x = estimate,
y = reorder(NAME, estimate),
tooltip = estimate,
data_id = GEOID)) +
# Add error bars and symbology
geom_errorbar(aes(xmin = estimate - moe, xmax = estimate + moe),
width = 0.75,
linewidth = 0.75,
color = "blue4") +
# Add interactive point and change symbology
geom_point_interactive(shape = 21,
fill = "gold1",
color = "brown3",
size = 1.5,
stroke = 0.75) +
# Clean up the y-axis by removing redunant text
scale_y_discrete(labels = function(x) str_remove(x, " County, Colorado")) +
# Add labels to the plot
labs(title = "Percent of Population with a Graduate Degree by Colorado County",
subtitle = "2019 - 2023 5-year ACS",
caption = "Figure 3: 2019 - 2023 5-year ACS data acquired with R and tidycensus.
Error bars represent margin of error around estimates.",
x = "ACS Estimate with Margin of Error (%)",
y = "") +
# Use a minimal theme
theme_minimal(base_size = 10)
# Plot the graph
girafe(ggobj = CO_plot_ggiraph,
# change size to improve legibility
width_svg = 6.5, height_svg = 7) %>%
# Label data point on hover
girafe_options(opts_hover(css = "fill:cyan;"))
Part B focuses on Census data that delineates the median home values in dollars of Colorado’s Denver metro area which comprises the counties of Adams, Arapahoe, Broomfield, Denver, Douglas, and Jefferson. This data is accessible via the “B25077_001” variable, according to the U.S. Census Bureau (2023). Mapping this data at the block group level can reveal where homes are the most and least expensive.
Interested in where the B25077_001 variable originated? Use the tidycensus load_variables() function to see.
# Load the available variables
vars <- load_variables(2023, "acs5")
# Show examples
vars
## # A tibble: 28,261 × 4
## name label concept geography
## <chr> <chr> <chr> <chr>
## 1 B01001A_001 Estimate!!Total: Sex by Age (W… tract
## 2 B01001A_002 Estimate!!Total:!!Male: Sex by Age (W… tract
## 3 B01001A_003 Estimate!!Total:!!Male:!!Under 5 years Sex by Age (W… tract
## 4 B01001A_004 Estimate!!Total:!!Male:!!5 to 9 years Sex by Age (W… tract
## 5 B01001A_005 Estimate!!Total:!!Male:!!10 to 14 years Sex by Age (W… tract
## 6 B01001A_006 Estimate!!Total:!!Male:!!15 to 17 years Sex by Age (W… tract
## 7 B01001A_007 Estimate!!Total:!!Male:!!18 and 19 years Sex by Age (W… tract
## 8 B01001A_008 Estimate!!Total:!!Male:!!20 to 24 years Sex by Age (W… tract
## 9 B01001A_009 Estimate!!Total:!!Male:!!25 to 29 years Sex by Age (W… tract
## 10 B01001A_010 Estimate!!Total:!!Male:!!30 to 34 years Sex by Age (W… tract
## # ℹ 28,251 more rows
Access this data for the Colorado counties listed above with the get_acs() function.
# Acquire 2023 ACS data for the counties comprising the Denver metro area
CO_med_home <- get_acs(geography = "block group",
variables = "B25077_001",
state = "CO",
year = 2023,
county = c("Denver", "Adams", "Arapahoe", "Jefferson", "Douglas", "Broomfield"),
geometry = TRUE) # Include for map
Quickly create an interactive map of the block groups’ median home values.
# Relocate the legend
mapviewOptions(legend.pos = "bottomright")
# Create a map showing the estimated median home value and rename the legend
mapview(CO_med_home,
zcol = "estimate",
layer.name = "Median Home Value ($)") @map %>%
# Add title and caption
addControl("<h4>Median home values in the Denver metro area", position = "topright") %>%
addControl("<h6>Figure 4: 2019-2023 ACS data <br>acquired with R and tidycensus.", position = "bottomright")
A static version of the map can be created with the ggplot package.
# Create a choropleth map with a continuous color palette
ggplot(CO_med_home, aes(fill = estimate)) +
geom_sf() +
# Add a simple gray background
theme_gray() +
# Customize the symbology
scale_fill_distiller(name = "Median Home \nValue (USD)",
palette = "RdYlBu",
# make the legend scale nicer looking (auto)
breaks = pretty_breaks(),
# Add commas and dollar sign to legend values
labels = scales::label_dollar(prefix = "$")) +
# Customize the labels
labs(title = "Median Home Value (USD)",
subtitle = "Denver Metro Area, Colorado",
fill = "ACS Estimate",
caption = "Figure 5: 2019-2023 ACS data acquired with R and tidycensus.
The counties comprising the metro area are: Adams, Arapahoe,
Broomfield, Denver, Douglas, and Jefferson")
Analyzing the map reveals that homes in the Cherry Hills Village and the Greenwood Village in south-central Denver have the highest median home values in the city. Additionally, homes along the mountainous Front Range in the west have higher prices than homes in the eastern plains. The large gray block groups in the central-north east are a combination of airports and a wildlife preserve.
PSU. (No date). GEOG588 Lab #5 Assignment. Retrieved April 1, 2026 from https://psu.instructure.com/courses/2451238/pages/lab-number-5-assignment?module_item_id=47591676.
U.S. Census Bureau. (2026). American Community Survey. U.S. Department of Commerce. Retrieved April 1, 2026 from https://www.census.gov/programs-surveys/acs.html.
U.S. Census Bureau. (2023). American Community Survey, ACS 5-Year Estimates. [Data]. U.S. Department of Commerce. Retrieved March 31, 2026 through tidycensus package.
Walker K. and Herman M. (No date). tidycensus. Retrieved April 1, 2026 from https://walker-data.com/tidycensus/.
Wikipedia. (2026). Flag of Colorado. [Image]. Retrieved April 1, 2026 from https://en.wikipedia.org/wiki/Flag_of_Colorado.