Assignment 1: Census Data Quality for Policy Decisions

Evaluating Data Reliability for Algorithmic Decision-Making

Author

Your Name Here

Published

September 22, 2025

Assignment Overview

Scenario

You are a data analyst for the [Your State] Department of Human Services. The department is considering implementing an algorithmic system to identify communities that should receive priority for social service funding and outreach programs. Your supervisor has asked you to evaluate the quality and reliability of available census data to inform this decision.

Drawing on our Week 2 discussion of algorithmic bias, you need to assess not just what the data shows, but how reliable it is and what communities might be affected by data quality issues.

Learning Objectives

  • Apply dplyr functions to real census data for policy analysis
  • Evaluate data quality using margins of error
  • Connect technical analysis to algorithmic decision-making
  • Identify potential equity implications of data reliability issues
  • Create professional documentation for policy stakeholders

Submission Instructions

Submit by posting your updated portfolio link on Canvas. Your assignment should be accessible at your-portfolio-url/assignments/assignment_1/

Make sure to update your _quarto.yml navigation to include this assignment under an “Assignments” menu.

Part 1: Portfolio Integration

Create this assignment in your portfolio repository under an assignments/assignment_1/ folder structure. Update your navigation menu to include:

- text: Assignments
  menu:
    - href: assignments/assignment_1/your_file_name.qmd
      text: "Assignment 1: Census Data Exploration"

If there is a special character like comma, you need use double quote mark so that the quarto can identify this as text

Setup

# Load required packages (hint: you need tidycensus, tidyverse, and knitr)
library(tidycensus)
library(tidyverse)
library(knitr)

# Set your Census API key
census_api_key("55588cff24a2b44b2f030ee1581c8d854c1839da", install = TRUE, overwrite = TRUE)
[1] "55588cff24a2b44b2f030ee1581c8d854c1839da"
readRenviron("~/.Renviron") 

# Choose your state for analysis - assign it to a variable called my_state
my_state <- "Pennsylvania"

State Selection: I have chosen [Pennsylvania] for this analysis because: [Because it’s where I am.]

Part 2: County-Level Resource Assessment

2.1 Data Retrieval

Your Task: Use get_acs() to retrieve county-level data for your chosen state.

Requirements: - Geography: county level - Variables: median household income (B19013_001) and total population (B01003_001)
- Year: 2022 - Survey: acs5 - Output format: wide

Hint: Remember to give your variables descriptive names using the variables = c(name = "code") syntax.

# Write your get_acs() code here
county_data <- get_acs(
  geography = "county", 
  variables = c(
    median_income = "B19013_001",   
    total_pop = "B01003_001"    
  ),
  year = 2022,
  survey = "acs5",
  state = my_state,
  output = "wide"
)

# Clean the county names to remove state name and "County"
county_data <- county_data %>%
  mutate(NAME = str_remove(NAME, " County, Pennsylvania"))

# Hint: use mutate() with str_remove()

# Display the first few rows
head(county_data)
# A tibble: 6 × 6
  GEOID NAME      median_incomeE median_incomeM total_popE total_popM
  <chr> <chr>              <dbl>          <dbl>      <dbl>      <dbl>
1 42001 Adams              78975           3334     104604         NA
2 42003 Allegheny          72537            869    1245310         NA
3 42005 Armstrong          61011           2202      65538         NA
4 42007 Beaver             67194           1531     167629         NA
5 42009 Bedford            58337           2606      47613         NA
6 42011 Berks              74617           1191     428483         NA

2.2 Data Quality Assessment

Your Task: Calculate margin of error percentages and create reliability categories.

Requirements: - Calculate MOE percentage: (margin of error / estimate) * 100 - Create reliability categories: - High Confidence: MOE < 5% - Moderate Confidence: MOE 5-10%
- Low Confidence: MOE > 10% - Create a flag for unreliable estimates (MOE > 10%)

Hint: Use mutate() with case_when() for the categories.

# Calculate MOE percentage and reliability categories using mutate()
county_data <- county_data %>%
  mutate(
    moe_pct_income = median_incomeM / median_incomeE * 100,
    reliability = case_when(
      moe_pct_income < 5 ~ "High Confidence",
      moe_pct_income >= 5 & moe_pct_income <= 10 ~ "Moderate Confidence",
      moe_pct_income > 10 ~ "Low Confidence"
    ),
    unreliable_flag = moe_pct_income > 10   # TRUE if MOE > 10%
  )

# Create a summary showing count of counties in each reliability category
reliability_summary <- county_data %>%
  count(reliability) %>%
  mutate(percentage = n / sum(n) * 100)
# Hint: use count() and mutate() to add percentages
reliability_summary
# A tibble: 2 × 3
  reliability             n percentage
  <chr>               <int>      <dbl>
1 High Confidence        57       85.1
2 Moderate Confidence    10       14.9

2.3 High Uncertainty Counties

Your Task: Identify the 5 counties with the highest MOE percentages.

Requirements: - Sort by MOE percentage (highest first) - Select the top 5 counties - Display: county name, median income, margin of error, MOE percentage, reliability category - Format as a professional table using kable()

Hint: Use arrange(), slice(), and select() functions.

# Create table of top 5 counties by MOE percentage
top5_uncertain <- county_data %>%
  arrange(desc(moe_pct_income)) %>%
  slice(1:5) %>%
  select(NAME, median_incomeE, median_incomeM, moe_pct_income, reliability)

# Format as table with kable() - include appropriate column names and caption
knitr::kable(
  top5_uncertain,
  digits = 2,
  caption = "Top 5 Counties with Highest Income Estimate Uncertainty"
)
Top 5 Counties with Highest Income Estimate Uncertainty
NAME median_incomeE median_incomeM moe_pct_income reliability
Forest 46188 4612 9.99 Moderate Confidence
Sullivan 62910 5821 9.25 Moderate Confidence
Union 64914 4753 7.32 Moderate Confidence
Montour 72626 5146 7.09 Moderate Confidence
Elk 61672 4091 6.63 Moderate Confidence

Data Quality Commentary:

[These results show that some counties face higher data uncertainty, meaning algorithms that rely heavily on these estimates may misallocate resources or services. Counties with smaller populations or more challenging survey conditions tend to have larger margins of error, making them more vulnerable to being misclassified or underserved by algorithms. Such areas require additional manual review or supplemental data in policy applications.]

Part 3: Neighborhood-Level Analysis

3.1 Focus Area Selection

Your Task: Select 2-3 counties from your reliability analysis for detailed tract-level study.

Strategy: Choose counties that represent different reliability levels (e.g., 1 high confidence, 1 moderate, 1 low confidence) to compare how data quality varies.

# Use filter() to select 2-3 counties from your county_reliability data
# Store the selected counties in a variable called selected_counties
selected_counties <- bind_rows(
  county_data %>% filter(moe_pct_income < 5) %>% slice(1),     # High
  county_data %>% filter(moe_pct_income >= 5 & moe_pct_income <= 10) %>% slice(1),  # Moderate
  county_data %>% filter(moe_pct_income > 10) %>% slice(1)     # Low
)

# Display the selected counties with their key characteristics
knitr::kable(
  selected_counties %>%
    select(NAME, median_incomeE, moe_pct_income, reliability),
  digits = 2,
  col.names = c("County", "Median Income", "MOE %", "Reliability"),
  caption = "Selected Counties by MOE Percentage (Different Confidence Levels)"
)
Selected Counties by MOE Percentage (Different Confidence Levels)
County Median Income MOE % Reliability
Adams 78975 4.22 High Confidence
Cameron 46186 5.64 Moderate Confidence
# Show: county name, median income, MOE percentage, reliability category

Comment on the output: [write something :)]

3.2 Tract-Level Demographics

Your Task: Get demographic data for census tracts in your selected counties.

Requirements: - Geography: tract level - Variables: white alone (B03002_003), Black/African American (B03002_004), Hispanic/Latino (B03002_012), total population (B03002_001) - Use the same state and year as before - Output format: wide - Challenge: You’ll need county codes, not names. Look at the GEOID patterns in your county data for hints.

# Define your race/ethnicity variables with descriptive names
race_vars <- c(
  white = "B03002_003",
  black = "B03002_004",
  hispanic = "B03002_012",
  total_pop = "B03002_001"
)

# Use get_acs() to retrieve tract-level data
tract_demo <- get_acs(
  geography = "tract",
  variables = race_vars,
  year = 2022,
  survey = "acs5",
  state = my_state,
  county = c("001", "023"),  
  output = "wide"
)

# Hint: You may need to specify county codes in the county parameter

# Calculate percentage of each group using mutate()
# Create percentages for white, Black, and Hispanic populations
tract_demo <- tract_demo %>%
  mutate(
    pct_white = (whiteE / total_popE) * 100,
    pct_black = (blackE / total_popE) * 100,
    pct_hispanic = (hispanicE / total_popE) * 100
  )

# Add readable tract and county name columns using str_extract() or similar
library(stringr)

tract_demo <- tract_demo %>%
  mutate(
    county_code = str_extract(GEOID, "(?<=^..)..."),   # 前2位是州,后3位是县
    tract_code  = str_extract(GEOID, "(?<=^.....).*")  # 从第6位开始都是tract
  )

3.3 Demographic Analysis

Your Task: Analyze the demographic patterns in your selected areas.

# Find the tract with the highest percentage of Hispanic/Latino residents
# Hint: use arrange() and slice() to get the top tract
top_hispanic_tract <- tract_demo %>%
  arrange(desc(pct_hispanic)) %>%
  slice(1) %>%
  select(county_code, tract_code, pct_hispanic, pct_white, pct_black)

# Calculate average demographics by county using group_by() and summarize()
county_demographics <- tract_demo %>%
  group_by(county_code) %>%
  summarize(
    tracts = n(),
    avg_white = mean(pct_white, na.rm = TRUE),
    avg_black = mean(pct_black, na.rm = TRUE),
    avg_hispanic = mean(pct_hispanic, na.rm = TRUE)
  )

# Show: number of tracts, average percentage for each racial/ethnic group

# Create a nicely formatted table of your results using kable()
knitr::kable(
  county_demographics,
  digits = 1,
  col.names = c("County Code", "Tracts", "Avg % White", "Avg % Black", "Avg % Hispanic"),
  caption = "Average Demographics by County (Selected Counties)"
)
Average Demographics by County (Selected Counties)
County Code Tracts Avg % White Avg % Black Avg % Hispanic
001 27 88.3 1.3 7.1
023 2 93.2 0.0 2.1
top_hispanic_tract
# A tibble: 1 × 5
  county_code tract_code pct_hispanic pct_white pct_black
  <chr>       <chr>             <dbl>     <dbl>     <dbl>
1 001         031502             20.9      73.1      2.74

Part 4: Comprehensive Data Quality Evaluation

4.1 MOE Analysis for Demographic Variables

Your Task: Examine margins of error for demographic variables to see if some communities have less reliable data.

Requirements: - Calculate MOE percentages for each demographic variable - Flag tracts where any demographic variable has MOE > 15% - Create summary statistics

# Calculate MOE percentages for white, Black, and Hispanic variables
# Hint: use the same formula as before (margin/estimate * 100)
tract_demo <- tract_demo %>%
  mutate(
    moe_pct_white    = (whiteM / whiteE) * 100,
    moe_pct_black    = (blackM / blackE) * 100,
    moe_pct_hispanic = (hispanicM / hispanicE) * 100
  )

# Create a flag for tracts with high MOE on any demographic variable
# Use logical operators (| for OR) in an ifelse() statement
tract_demo <- tract_demo %>%
  mutate(
    high_moe_flag = ifelse(
      moe_pct_white > 15 | moe_pct_black > 15 | moe_pct_hispanic > 15,
      TRUE, FALSE
    )
  )

# Create summary statistics showing how many tracts have data quality issues
moe_summary <- tract_demo %>%
  summarize(
    total_tracts = n(),
    tracts_high_moe = sum(high_moe_flag, na.rm = TRUE),
    pct_high_moe = (tracts_high_moe / total_tracts) * 100
  )

moe_summary
# A tibble: 1 × 3
  total_tracts tracts_high_moe pct_high_moe
         <int>           <int>        <dbl>
1           29              29          100

4.2 Pattern Analysis

Your Task: Investigate whether data quality problems are randomly distributed or concentrated in certain types of communities.

# Group tracts by whether they have high MOE issues
# Calculate average characteristics for each group:
# - population size, demographic percentages
# Use group_by() and summarize() to create this comparison
pattern_summary <- tract_demo %>%
  group_by(high_moe_flag) %>%

  summarize(
    tracts = n(),
    avg_pop = mean(total_popE, na.rm = TRUE),
    avg_white = mean(pct_white, na.rm = TRUE),
    avg_black = mean(pct_black, na.rm = TRUE),
    avg_hispanic = mean(pct_hispanic, na.rm = TRUE)
  )

# Create a professional table showing the patterns
knitr::kable(
  pattern_summary,
  digits = 1,
  col.names = c("High MOE?", "Tracts", "Avg Population", "Avg % White", "Avg % Black", "Avg % Hispanic"),
  caption = "Community Characteristics by Data Reliability"
)
Community Characteristics by Data Reliability
High MOE? Tracts Avg Population Avg % White Avg % Black Avg % Hispanic
TRUE 29 3763.4 88.7 1.2 6.8

Pattern Analysis: [Describe any patterns you observe. Do certain types of communities have less reliable data? What might explain this?]

Part 5: Policy Recommendations

5.1 Analysis Integration and Professional Summary

Your Task: Write an executive summary that integrates findings from all four analyses.

Executive Summary Requirements: 1. Overall Pattern Identification: What are the systematic patterns across all your analyses? 2. Equity Assessment: Which communities face the greatest risk of algorithmic bias based on your findings? 3. Root Cause Analysis: What underlying factors drive both data quality issues and bias risk? 4. Strategic Recommendations: What should the Department implement to address these systematic issues?

Executive Summary:

[Your integrated 4-paragraph summary here]

6.3 Specific Recommendations

Your Task: Create a decision framework for algorithm implementation.

# Create a summary table using your county reliability data
# Include: county name, median income, MOE percentage, reliability category

# Add a new column with algorithm recommendations using case_when():
# - High Confidence: "Safe for algorithmic decisions"
# - Moderate Confidence: "Use with caution - monitor outcomes"  
# - Low Confidence: "Requires manual review or additional data"

# Format as a professional table with kable()

Key Recommendations:

Your Task: Use your analysis results to provide specific guidance to the department.

  1. Counties suitable for immediate algorithmic implementation: [List counties with high confidence data and explain why they’re appropriate]

  2. Counties requiring additional oversight: [List counties with moderate confidence data and describe what kind of monitoring would be needed]

  3. Counties needing alternative approaches: [List counties with low confidence data and suggest specific alternatives - manual review, additional surveys, etc.]

Questions for Further Investigation

[List 2-3 questions that your analysis raised that you’d like to explore further in future assignments. Consider questions about spatial patterns, time trends, or other demographic factors.]

Technical Notes

Data Sources: - U.S. Census Bureau, American Community Survey 2018-2022 5-Year Estimates - Retrieved via tidycensus R package on [date]

Reproducibility: - All analysis conducted in R version [your version] - Census API key required for replication - Complete code and documentation available at: [your portfolio URL]

Methodology Notes: [Describe any decisions you made about data processing, county selection, or analytical choices that might affect reproducibility]

Limitations: [Note any limitations in your analysis - sample size issues, geographic scope, temporal factors, etc.]


Submission Checklist

Before submitting your portfolio link on Canvas:

Remember: Submit your portfolio URL on Canvas, not the file itself. Your assignment should be accessible at your-portfolio-url/assignments/assignment_1/your_file_name.html