Census Data

dp_vars_expanded <- c(
  # DP02 - Social Characteristics
  "pct_bachelor_degree_plus_adults25plus" = "DP02_0068P",
  "pct_high_school_graduate_adults25plus" = "DP02_0067P",
  "pct_english_only_home_pop5plus" = "DP02_0113P",
  "pct_spanish_home_pop5plus" = "DP02_0116P",
  "pct_broadband_subscription_households" = "DP02_0154P",
  
  # DP03 - Economic Characteristics  
  "per_capita_income" = "DP03_0088",
  "median_household_income" = "DP03_0062",                
  "pct_below_poverty_all_people" = "DP03_0128P",          
  "pct_unemployed_labor_force" = "DP03_0009P",
  "pct_no_vehicle_households" = "DP03_0057P",
  "pct_gov_employment_employed16plus" = "DP03_0042P",        
  "pct_snap_benefits_households" = "DP03_0074P",
  
  # DP04 - Housing Characteristics
  "pct_owner_occupied_housing_units" = "DP04_0046P",
  
  # DP05 - Demographics 
  "pct_under_5_total_pop" = "DP05_0005P",                 
  "pct_under_18_total_pop" = "DP05_0019P",   
  "pct_over_65_total_pop" = "DP05_0024P",
  
  # Race/Ethnicity
  "pct_hispanic_any_race_total_pop" = "DP05_0076P",
  "pct_white_non_hispanic_total_pop" = "DP05_0082P",
  "pct_black_non_hispanic_total_pop" = "DP05_0083P", 
  "pct_asian_non_hispanic_total_pop" = "DP05_0085P",
  "pct_native_american_non_hispanic_total_pop" = "DP05_0084P"
)
# Pull data for all three geographies
nm_state <- tidycensus::get_acs(
  geography = "state",
  variables = dp_vars_expanded,
  year = 2023,
  survey = "acs5",
  state = "NM"
)

nm_senate <- tidycensus::get_acs(
  geography = "state legislative district (upper chamber)",
  variables = dp_vars_expanded,
  year = 2023,
  survey = "acs5", 
  state = "NM"
)

nm_house <- tidycensus::get_acs(
  geography = "state legislative district (lower chamber)",
  variables = dp_vars_expanded,
  year = 2023,
  survey = "acs5",
  state = "NM"
)

# Optional: Combine all into one dataset with geography type
all_nm_data <- bind_rows(
  nm_state |> mutate(geo_type = "State"),
  nm_senate |> mutate(geo_type = "Senate District"), 
  nm_house |> mutate(geo_type = "House District")
)
all_nm_data |> head(100) |> DT::datatable(rownames = F)
nm_house2 <- tidycensus::get_acs(
  geography = "state legislative district (lower chamber)",
  variables = dp_vars_expanded,
  year = 2023,
  survey = "acs5",
  state = "NM",
  geometry = TRUE
)
##   |                                                          |                                                  |   0%  |                                                          |=                                                 |   2%  |                                                          |=                                                 |   3%  |                                                          |==                                                |   3%  |                                                          |==                                                |   4%  |                                                          |==                                                |   5%  |                                                          |===                                               |   5%  |                                                          |===                                               |   6%  |                                                          |===                                               |   7%  |                                                          |====                                              |   7%  |                                                          |====                                              |   8%  |                                                          |====                                              |   9%  |                                                          |=====                                             |   9%  |                                                          |=====                                             |  10%  |                                                          |=====                                             |  11%  |                                                          |======                                            |  11%  |                                                          |======                                            |  12%  |                                                          |=======                                           |  13%  |                                                          |=======                                           |  14%  |                                                          |=======                                           |  15%  |                                                          |========                                          |  15%  |                                                          |========                                          |  16%  |                                                          |=========                                         |  18%  |                                                          |=========                                         |  19%  |                                                          |==========                                        |  20%  |                                                          |===========                                       |  22%  |                                                          |============                                      |  23%  |                                                          |============                                      |  24%  |                                                          |=============                                     |  26%  |                                                          |==============                                    |  27%  |                                                          |==============                                    |  28%  |                                                          |===============                                   |  30%  |                                                          |================                                  |  31%  |                                                          |================                                  |  32%  |                                                          |=================                                 |  33%  |                                                          |=================                                 |  35%  |                                                          |==================                                |  36%  |                                                          |===================                               |  37%  |                                                          |===================                               |  39%  |                                                          |====================                              |  40%  |                                                          |=====================                             |  41%  |                                                          |=====================                             |  43%  |                                                          |======================                            |  44%  |                                                          |======================                            |  45%  |                                                          |=======================                           |  46%  |                                                          |========================                          |  48%  |                                                          |========================                          |  49%  |                                                          |=========================                         |  50%  |                                                          |==========================                        |  52%  |                                                          |==========================                        |  53%  |                                                          |===========================                       |  54%  |                                                          |============================                      |  55%  |                                                          |============================                      |  57%  |                                                          |=============================                     |  58%  |                                                          |==============================                    |  59%  |                                                          |==============================                    |  61%  |                                                          |===============================                   |  62%  |                                                          |================================                  |  63%  |                                                          |================================                  |  64%  |                                                          |=================================                 |  66%  |                                                          |=================================                 |  67%  |                                                          |====================================              |  72%  |                                                          |=====================================             |  74%  |                                                          |========================================          |  80%  |                                                          |==========================================        |  85%  |                                                          |=============================================     |  90%  |                                                          |================================================  |  95%  |                                                          |==================================================| 100%
# Choose a good projection for NM — Albers Equal Area (NAD83)
# EPSG: 5070 works well for US-wide data, but NM-specific CRS is EPSG: 6423
nm_house2 <- sf::st_transform(nm_house2, crs = 6423)

# Simple choropleth example — median household income
ggplot(
  nm_house2 |>
    subset(variable == "pct_spanish_home_pop5plus") |>
    sf::st_transform(32113)
) +
  geom_sf(aes(fill = estimate), color = "grey60", linewidth = 0.2) +
  scale_fill_distiller(palette = "Greens", direction = 1, na.value = "grey85") +
  theme_minimal(base_size = 12) +
  labs(
    title = "Spanish Spoken at Home (Population 5+)",
    subtitle = "New Mexico House Districts — ACS 2019–2023",
    fill = "%"
  )

library(tigris)
options(tigris_use_cache = TRUE)

# Spanish spoken at home, reprojected
abq_data <- nm_house2 |>
  subset(variable == "pct_spanish_home_pop5plus") |>
  sf::st_transform(32113)

# Bernalillo County for zoom extent
bernalillo <- tigris::counties(state = "NM", year = 2023) |>
  subset(NAME == "Bernalillo") |>
  sf::st_transform(32113)
abq_bbox <- sf::st_bbox(bernalillo)

# Statewide primary roads, clipped to NM
nm_boundary <- tigris::states(year = 2023) |>
  subset(STUSPS == "NM") |>
  sf::st_transform(32113)

major_roads_nm <- tigris::primary_roads(year = 2023) |>
  sf::st_transform(32113) |>
  sf::st_intersection(nm_boundary)

# Centroids for labeling
label_points <- sf::st_centroid(abq_data)
# Plot ABQ zoom with labels
ggplot() +
  geom_sf(data = abq_data, aes(fill = estimate), color = "grey60", linewidth = 0.2) +
  geom_sf(data = major_roads_nm, color = "grey30", linewidth = 0.5, alpha = 0.9) +
  geom_sf_text(
    data = label_points,
    aes(label = sub(".*District (\\d+).*", "\\1", NAME)),
    size = 2,
    color = "black",
    fontface = "bold"
  ) +
  scale_fill_distiller(palette = "Greens", direction = 1, na.value = "grey85") +
  coord_sf(
    xlim = c(abq_bbox["xmin"], abq_bbox["xmax"]),
    ylim = c(abq_bbox["ymin"], abq_bbox["ymax"]),
    expand = FALSE
  ) +
  theme_minimal(base_size = 12) +
  labs(
    title = "Spanish Spoken at Home (Population 5+)",
    subtitle = "Albuquerque Area — ACS 2019–2023",
    fill = "%",
    caption = "Labels show House District numbers"
  )