Census & demographics
Census boundaries and tables: joining them, turning counts into rates, carrying margins of error, and comparing years.
Census data is two things joined together: a table of counts and a set of boundaries. Both move. Tracts are redrawn every decade to keep their populations in range, codes change without the boundaries changing and boundaries change without the codes changing, and a join on the identifier succeeds in every one of those cases.
The second half of the topic is arithmetic. Counts are additive and almost nothing else is: rates, medians and margins of error do not sum or average into their parents, so a county figure rebuilt from its tracts disagrees with the published one. Margins of error combine by root sum of squares, not by addition, and survey estimates for small areas carry margins large enough to swallow the difference you are mapping.
Below: the concepts cover the geography hierarchy and what each level is for, the how-to guides do the joins and the rate calculations, and the fixes are the totals that will not reconcile.
🧭 Start with the concepts
The ideas the how-to guides below assume you already have.
- Census Geographies Explained: Blocks, Tracts, Output Areas and Why They Nest
- Census Identifiers Explained: GEOIDs, Codes and the Leading Zero Problem
- Counts, Rates and Densities: What a Demographic Map Should Show
- Margins of Error Explained: Why Survey Estimates Need Their Uncertainty
- Small Numbers Explained: Why Rates in Small Areas Jump Around
- Boundary Changes Over Time: Why Two Census Years Do Not Line Up
Show every concept in this topic
- Aggregation and suppression rules explained
- Differential privacy for spatial counts explained
- Hazard, exposure and vulnerability explained: what "risk" means in a GIS
- Exposure Assessment Explained
- Urban Extent Explained
- Gross vs Net Migration Explained
- The Ecological Fallacy Explained
- Age Standardisation Explained
⚙️ Then do the task
Step-by-step walkthroughs with code you can copy and adapt.
- How to Download Census Boundaries in Python
- How to Download Census Tables from an API in Python
- How to Join a Census Table to Its Boundaries Without Losing Rows
- How to Normalise Census Counts into Rates and Densities
- How to Aggregate Survey Estimates and Their Margins of Error
- How to Smooth Unstable Area Rates with Empirical Bayes in Python
Show every how-to guide in this topic
- How to Compare Census Years Across Changed Boundaries
- How to Redistribute Population with Dasymetric Mapping
- How to Calculate Population-Weighted Centroids
- How to Count the Population Within Reach of Each Facility
- How to Measure Access to Services with the Two-Step Floating Catchment Method
- How to Find the Areas Nobody Can Reach Within a Travel Time
- How to suppress small counts in a spatial table in Python
- How to add differentially private noise to spatial counts
- How to measure the population served by frequent transit
- How to read a USGS ShakeMap and find who was shaken
- How to count buildings and people exposed to a hazard zone
- How to Calculate Population-Weighted Pollution Exposure in Python
- How to Estimate Population Exposure to Heat in Python
- How to Read County-to-County Migration Flows in Python
- How to Map Net Migration by County in Python
- How to Map Commuting Flows from LEHD LODES in Python
- How to Build and Read an Origin–Destination Matrix in Python
- How to Aggregate Origin–Destination Flows to Larger Zones in Python
- How to Map CDC PLACES Health Estimates by Census Tract in Python
- How to Map Life Expectancy by Census Tract in Python
- How to Calculate Age-Adjusted Death Rates in Python
- How to Map County Drug Overdose Death Rates in Python
- How to Aggregate Tract Health Estimates to Neighbourhoods in Python
- How to Map Health Estimates by ZIP Code in Python
- How to Calculate Crime Rates per Resident in Python
- How to Map Road Casualty Rates by Local Authority in Python
- How to Use a Census Population Grid in Python
- How to Map Age Groups from a Census Population Grid in Python
🔧 When it breaks
The errors this topic produces, with the cause explained rather than just the command.
- Fixing Census Joins That Fail Because Leading Zeros Were Dropped
- Fixing Census API Values Like −666666666 and Other Sentinels
- Fixing a Rate Map Dominated by Tiny, Nearly Empty Areas
- Fixing Census Totals That Do Not Add Up After Aggregation
- Fixing Census Data That Does Not Match the Boundary File Year
- Suppressed cells can be recovered from the totals
Show every fix in this topic
- Exposure counts are double-counted or missed
- Density Depends on the Boundary
- Dot-Density Map Puts Dots in the Wrong Places: Deserts, Borders and Weights
- Why Do Small Migration Flows Jump Around Between Releases?
- Why Are My Flow Totals Bigger Than the Flows on My Map?
- Why Does My Health Map Look Like a Poverty Map?
- Why Do My Health Estimates Not Join to Current Census Tracts?
- Why Does My Death Rate Map Just Show Where Old People Live?
- Why Is Connecticut Missing From My County Map?
- Fixing a Census Grid Total That Comes Out Below the Official Population
Learning paths through this topic
A curated route rather than a list — the guides in the order that builds on itself.
Related topics
Subjects that keep coming up alongside this one, most overlap first.