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%  |                                                                              |=                                                                     |   1%  |                                                                              |==                                                                    |   3%  |                                                                              |===                                                                   |   4%  |                                                                              |===                                                                   |   5%  |                                                                              |====                                                                  |   5%  |                                                                              |====                                                                  |   6%  |                                                                              |=====                                                                 |   7%  |                                                                              |=====                                                                 |   8%  |                                                                              |======                                                                |   8%  |                                                                              |======                                                                |   9%  |                                                                              |=======                                                               |   9%  |                                                                              |=======                                                               |  10%  |                                                                              |=======                                                               |  11%  |                                                                              |========                                                              |  11%  |                                                                              |========                                                              |  12%  |                                                                              |=========                                                             |  12%  |                                                                              |=========                                                             |  13%  |                                                                              |==========                                                            |  14%  |                                                                              |==========                                                            |  15%  |                                                                              |===========                                                           |  16%  |                                                                              |============                                                          |  17%  |                                                                              |=============                                                         |  18%  |                                                                              |==============                                                        |  19%  |                                                                              |==============                                                        |  21%  |                                                                              |===============                                                       |  22%  |                                                                              |=================                                                     |  25%  |                                                                              |==================                                                    |  26%  |                                                                              |=======================                                               |  32%  |                                                                              |====================================                                  |  52%  |                                                                              |=====================================                                 |  53%  |                                                                              |======================================                                |  54%  |                                                                              |=======================================                               |  56%  |                                                                              |========================================                              |  57%  |                                                                              |===========================================                           |  61%  |                                                                              |============================================                          |  62%  |                                                                              |============================================                          |  63%  |                                                                              |=============================================                         |  65%  |                                                                              |==============================================                        |  66%  |                                                                              |===============================================                       |  67%  |                                                                              |===================================================                   |  72%  |                                                                              |===================================================                   |  74%  |                                                                              |=======================================================               |  79%  |                                                                              |==========================================================            |  83%  |                                                                              |=============================================================         |  88%  |                                                                              |=================================================================     |  93%  |                                                                              |===================================================================== |  98%  |                                                                              |======================================================================| 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"
  )