Census Data for Political Geography

Campaign finance tells you who gave money. Census data tells you where they live, who their neighbors are, and how their district was drawn. Together, they reveal the demographic reality behind political donations.

This post covers the Census Bureau data sources that matter for political geography, how they connect to campaign finance data, and the pitfalls of joining the two.

Why Census Data Matters

FEC data has addresses. Every itemized individual contribution - hundreds of millions of records - includes the donor’s street, city, state, and ZIP. But addresses alone don’t tell you:

  • Which congressional district a donor lives in
  • The demographic composition of that district
  • How the district has changed due to redistricting
  • Per-capita donation rates adjusted for population

Census data provides the geographic and demographic context that transforms raw campaign finance records into political intelligence.

The Census Data Ecosystem

The Census Bureau maintains three primary data products relevant to political geography:

1. Decennial Census

The constitutional mandate. Every 10 years, the Census counts every person in the country. Results determine:

  • Congressional apportionment (how many seats each state gets)
  • Redistricting boundaries (how districts are drawn)
  • Federal funding allocation

Key tables for political analysis:

Table Description Use Case
P1 Race (P1_001N is total population) Per-capita calculations, demographic composition
P2 Hispanic or Latino, and Not Hispanic or Latino by Race Hispanic population analysis
P3 Race for the population 18 years and over Voting-age population estimates
P4 Hispanic or Latino by race, 18 years and over Voting-age population by origin

These are the 2020 redistricting (PL 94-171) tables. The 2020 Census is the basis for the congressional maps drawn in 2021-2022 - though, as below, several states have redrawn since.

2. American Community Survey (ACS)

Annual survey sampling ~3.5 million households. Provides detailed demographic data between decennial censuses.

5-Year ACS Estimates (the usual choice for small areas):

  • Released annually with 5 years of rolling data
  • Available at small geographies (tract, block group)
  • More reliable than 1-year estimates for small areas

Relevant variables:

B01001: Sex by Age
B02001: Race
B03002: Hispanic/Latino Origin by Race
B19013: Median Household Income
B15003: Educational Attainment
B23025: Employment Status

These enable demographic overlays on donor data: “What’s the median income of ZIP codes producing donations to Candidate X?”

3. TIGER/Line Shapefiles

The geographic boundaries that make everything else work.

TIGER = Topologically Integrated Geographic Encoding and Referencing

TIGER/Line provides shapefiles for:

Geography File Description
Congressional Districts cd119 119th Congress boundaries
State Legislative Districts sldl, sldu State house and senate districts
Counties county 3,000+ county boundaries
ZIP Code Tabulation Areas zcta520 Approximations of USPS ZIPs
Census Tracts tract ~4,000 person neighborhoods
Census Block Groups bg ~1,500 person sub-neighborhoods

Critical note: TIGER “ZCTAs” are not identical to USPS ZIP codes. ZCTAs are areal approximations; ZIP codes are delivery routes. They mostly match, but edge cases exist.

Congressional District Mapping

The core integration: matching donor addresses to congressional districts.

The Problem

FEC data includes donor addresses but not congressional districts. A single ZIP code can be split between two or three districts, so a donor’s district depends on exactly where in that ZIP they live.

The Solution

  1. Geocode addresses to latitude/longitude
  2. Point-in-polygon query against congressional district boundaries
  3. Store district assignment with donor record
-- PostGIS spatial join: donors to congressional districts
SELECT
    d.donor_id,
    d.name,
    d.address,
    cd.statefp,          -- state FIPS code, e.g. '48' for Texas
    cd.cd119fp as district
FROM donors d
JOIN congressional_districts cd
ON ST_Contains(cd.geom, ST_SetSRID(ST_MakePoint(d.lon, d.lat), 4326));

Redistricting Complications

Districts are redrawn after every census - and sometimes in between. A donor who gave in 2018 lived under a different district map than the same address in 2024. Courts regularly order new maps mid-decade, and in 2025 several states, including Texas, California, Missouri, and North Carolina, redrew their congressional maps ahead of the 2026 elections.

So a district assignment needs a date. The robust approach is to keep every map version with the dates it was in effect, and assign each contribution using the map that applied when it was made. “Once per decade” is a simplification that no longer holds.

Demographic Enrichment

Census demographics add context to campaign finance patterns.

ZIP-Level Demographics

Most accessible approach. Join donor ZIP codes to ACS data:

-- Median income by donor ZIP
SELECT
    d.zip,
    z.median_income,
    COUNT(*) as donor_count,
    SUM(d.amount) as total_donated
FROM contributions d
JOIN acs_zcta z ON d.zip = z.zcta5
GROUP BY d.zip, z.median_income
ORDER BY total_donated DESC;

This surfaces patterns such as how concentrated a candidate’s money is in high-income ZIPs. Two caveats: FEC ZIPs are often ZIP+4, so truncate to five digits before joining; and ZCTAs only approximate ZIP codes (see above).

District-Level Demographics

Aggregate Census data to congressional district level for competitive analysis:

-- District demographic profile
SELECT
    cd.district,
    SUM(t.population) as total_pop,
    SUM(t.pop_white)::numeric / SUM(t.population) as pct_white,
    SUM(t.pop_college)::numeric / SUM(t.pop_25plus) as pct_college,
    AVG(t.median_income) as mean_tract_median_income  -- not a true district median
FROM census_tracts t
JOIN congressional_districts cd
ON ST_Contains(cd.geom, ST_Centroid(t.geom))
GROUP BY cd.district;

Tract centroids are an approximation: tracts don’t always nest inside congressional districts. For exact district totals, build from census blocks using block assignment files.

Per-Capita Donation Rates

Population normalization reveals giving intensity:

-- Donations per capita by district
SELECT
    cd.district,
    cd.population,
    SUM(c.amount) as total_raised,
    SUM(c.amount) / cd.population as per_capita
FROM contributions c
JOIN congressional_districts cd ON c.district = cd.district
GROUP BY cd.district, cd.population
ORDER BY per_capita DESC;

Normalizing by population separates districts that give a lot because they’re large from districts that give a lot because they’re wealthy.

Data Access

Census Bureau APIs

The Census Bureau provides free API access to all data products.

API Base URL: https://api.census.gov/data/

Example: 2023 ACS 5-Year Median Income by State

https://api.census.gov/data/2023/acs/acs5?get=NAME,B19013_001E&for=state:*

API Key: Free, request at api.census.gov/data/key_signup.html

TIGER/Line Downloads

Shapefiles available at:

https://www2.census.gov/geo/tiger/TIGER{YEAR}/

Congressional districts (119th Congress) are published per state, by FIPS code - Texas, for example:

https://www2.census.gov/geo/tiger/TIGER2025/CD/tl_2025_48_cd119.zip

Each TIGER vintage reflects the boundaries in place at the start of its year, so a mid-decade redraw shows up a year or more later.

Data Formats

Format Use Case
Shapefile (.shp) GIS software, legacy systems
GeoJSON Web mapping, JavaScript
GeoPackage (.gpkg) Modern GIS, single-file convenience

For search and maps, GeoJSON works well (for example, OpenSearch geo_shape fields); for spatial joins, load the boundaries into PostGIS.

Integration Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Census API     │────▶│  Bronze Layer   │────▶│  PostGIS        │
│  (demographics) │     │  (raw tables)   │     │  (spatial)      │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                                                        │
┌─────────────────┐                                     │
│  TIGER/Line     │────▶│  Shapefiles     │────▶────────┤
│  (boundaries)   │     │  (geometries)   │             │
└─────────────────┘     └─────────────────┘             ▼
                                                ┌─────────────────┐
                                                │  Gold Layer     │
                                                │  (enriched      │
                                                │   donor data)   │
                                                └─────────────────┘

Pipeline Steps

  1. Acquire boundaries: Download TIGER/Line shapefiles for congressional districts, ZCTAs
  2. Load to PostGIS: Import shapefiles with shp2pgsql or ogr2ogr
  3. Fetch demographics: Query Census API for ACS tables by geography
  4. Join to boundaries: Link demographic data to geographic entities
  5. Geocode donors: Convert donor addresses to lat/lon coordinates
  6. Spatial join: Match donors to districts and ZCTAs
  7. Enrich gold layer: Add district and demographic columns to donor entities

Challenges

Address Quality

FEC addresses are self-reported. Issues include:

  • Typos and misspellings
  • Incomplete addresses (no street number)
  • PO boxes (can’t geocode precisely)
  • Outdated addresses (people move)

A practical approach: geocode what you can and fall back to the ZIP centroid for failures - and record which method placed each address.

Geocoding at Scale

Tens of millions of distinct donor addresses require bulk geocoding. The options trade cost against accuracy:

  • Census Geocoder - free, with a batch interface; slower, and less forgiving of messy addresses
  • Nominatim (OpenStreetMap) - free if self-hosted; throughput is limited only by your hardware, but match rates on ambiguous addresses are lower
  • Commercial geocoders (Google, Smarty, and others) - fast and accurate, priced per lookup, which adds up at this scale

Check current pricing and terms of use before committing; both change.

Boundary Versioning

Redistricting creates temporal complexity. The same address maps to different districts depending on when you ask.

The approach:

  • Keep the contribution date with each record
  • Keep every boundary version with its effective dates
  • Join using the boundaries in effect on that date

Privacy Considerations

Census data is published only in aggregate. Individual responses are never released, and the 2020 Census applied differential privacy - deliberately added statistical noise - to protect respondents, which makes very small geographies like blocks less precise.

When combining Census demographics with FEC donor data (which includes names and addresses), aggregate to ZIP or district level. Individual-level demographic inference would be ethically questionable and statistically unreliable.

Use Cases

The questions below are the kind this combination can answer; they are illustrations, not findings.

Competitive District Analysis

Identify which competitive districts are seeing the most donor activity:

How much out-of-district money flows into House seats rated toss-ups, compared with safe seats?

Demographic Donor Profiling

Understand the demographic composition of a candidate’s donor base:

How does the median income of a candidate’s donor ZIPs compare with the district they want to represent?

Redistricting Impact

Track how redistricting affected donor geography:

After a redraw, what share of an incumbent’s previous donors now live outside the new district?

Urban/Rural Giving Patterns

Analyze political donations through a geographic lens:

How does rural areas’ share of contributed dollars compare with their share of the population?

What’s Next

Census data provides the foundation for geographic political analysis. Future posts will cover more detailed sources for current and historical district boundaries, and mapping donation patterns.

The Census Bureau has been counting the country since 1790. The political map is redrawn at least once a decade, and lately more often. Understanding that geography is essential to understanding American politics.


Related: Understanding FEC Bulk Data Files - the campaign finance data that census geography enriches.