Quick Start¶
Three runnable examples to get you productive with PyPUMS in under five minutes. Each example assumes you have already installed PyPUMS and configured your API key.
1. Get a table – County-level median household income¶
Fetch median household income (variable B19013_001) for every county in California from the 2023 ACS 5-year estimates.
import pypums
ca_income = pypums.get_acs(
geography="county", # (1)!
variables="B19013_001", # (2)!
state="CA", # (3)!
year=2023, # (4)!
survey="acs5", # (5)!
)
print(ca_income.head())
- geography – The level of geographic detail. Common values:
"state","county","tract","block group","place","zip code tabulation area". - variables – One or more Census variable codes.
B19013_001is median household income from table B19013. Pass a list for multiple variables:["B19013_001", "B01001_001"]. - state – Filter to a single state. Accepts FIPS codes (
"06"), abbreviations ("CA"), or full names ("California"). - year – The data year. Defaults to
2023. - survey –
"acs5"(5-year, default) or"acs1"(1-year). See Census 101 for guidance on which to choose.
GEOID NAME variable estimate moe 0 06001 Alameda County, California B19013_001 126240 1364 1 06003 Alpine County, California B19013_001 110781 18601 2 06005 Amador County, California B19013_001 81526 7398 3 06007 Butte County, California B19013_001 68574 2351 4 06009 Calaveras County, California B19013_001 79877 4638
| Column | Description |
|---|---|
GEOID |
FIPS code identifying the geography (state + county) |
NAME |
Human-readable place name from the Census Bureau |
variable |
The Census variable code you requested |
estimate |
The point estimate value |
moe |
Margin of error at 90% confidence (default) |
Wide format
Pass output="wide" to get one column per variable instead of the tidy
(long) layout. This is useful when you need to compute ratios across
variables in the same row.
What to try next: ACS Data guide for multi-variable queries, summary variables, and confidence level adjustment.
2. Make a map – Tract-level choropleth¶
Fetch tract-level poverty rates for Los Angeles County and plot a choropleth. This requires the spatial extras (uv add "pypums[spatial]").
import pypums
la_poverty = pypums.get_acs(
geography="tract", # (1)!
variables="B17001_002", # (2)!
state="CA", # (3)!
county="037", # (4)!
year=2023,
survey="acs5",
geometry=True, # (5)!
)
print(la_poverty.head())
print(type(la_poverty)) # <class 'geopandas.geodataframe.GeoDataFrame'>
- geography –
"tract"gives you Census tracts, small statistical areas with 1,200–8,000 people. - variables –
B17001_002is the count of people whose income is below the poverty level (from table B17001). - state – Required for tract-level queries so the API knows which state to pull tracts from.
- county –
"037"is the FIPS code for Los Angeles County. Usepypums.datasets.fips.lookup_fips(state="California", county="Los Angeles County")to look up codes. - geometry – When
True, PyPUMS downloads cartographic boundary shapefiles (via pygris, cached locally) and merges them with the data. The result is aGeoDataFramewith ageometrycolumn.
GEOID ... moe
0 06037101110 … 190 1 06037101122 … 214 2 06037101220 … 342 3 06037101221 … 286 4 06037101222 … 167
[5 rows x 6 columns]
Now plot it with Altair:
import altair as alt
alt.Chart(la_poverty).mark_geoshape(
stroke="white", strokeWidth=0.3,
).encode(
color=alt.Color(
"estimate:Q",
scale=alt.Scale(scheme="yelloworangered"),
legend=alt.Legend(title="Below Poverty Level"),
),
tooltip=["NAME:N", alt.Tooltip("estimate:Q", format=",")],
).project("albersUsa").properties(
width=600, height=500,
title="Poverty by Census Tract, Los Angeles County",
)
The resulting map shows poverty counts by Census tract across Los Angeles County, with darker shades indicating higher counts.
Interactive preview — state-level choropleth with ACS population data
The chart below shows a state-level choropleth to demonstrate what
geometry=True output looks like when plotted with Altair. Your actual
tract-level map will have much finer geographic detail.
How does geometry=True work?
The Census Bureau publishes free geographic boundary files called
TIGER/Line shapefiles. When you set geometry=True, PyPUMS uses
pygris to download the correct
shapefile for your geography level and year, then joins it to your data
on the GEOID column. Files are cached locally so subsequent calls are
fast.
What to try next: Spatial Data & Mapping guide for dot-density maps, population-weighted interpolation, and custom resolutions.
3. PUMS microdata – Age, sex, and wages for individuals¶
The Public Use Microdata Sample (PUMS) contains individual-level records, allowing custom tabulations that pre-made tables cannot provide. Fetch age, sex, and wage data for California.
import pypums
ca_pums = pypums.get_pums(
variables=["AGEP", "SEX", "WAGP"], # (1)!
state="CA", # (2)!
year=2023, # (3)!
survey="acs5", # (4)!
recode=True, # (5)!
)
print(ca_pums.head())
- variables – PUMS variable names (all caps).
AGEP= age,SEX= sex,WAGP= wage/salary income. These differ from ACS table variables likeB19013_001. - state – Required for PUMS queries. Accepts abbreviations, full names, or FIPS codes.
- year – The data year. Defaults to
2023. - survey –
"acs1"(1-year) or"acs5"(5-year, default). - recode – When
True, PyPUMS adds*_labelcolumns that translate numeric codes into human-readable values. For example,SEX=1getsSEX_label="Male".
```python exec=”on” session=”qs-pums”
markdown-exec: hide¶
import pypums ca_pums = pypums.get_pums( variables=[“AGEP”, “SEX”, “WAGP”], state=”CA”, year=2023, survey=”acs5”, recode=True, ) print(ca_pums.head()) ```
| Column | Description |
|---|---|
SERIALNO |
Unique housing unit serial number |
SPORDER |
Person number within the household |
PWGTP |
Person weight – use this when computing population totals |
ST |
State FIPS code |
PUMA |
Public Use Microdata Area code |
AGEP |
Age in years |
SEX |
Sex code (1 = Male, 2 = Female) |
WAGP |
Wage or salary income in dollars |
SEX_label |
Human-readable label (added by recode=True) |
Always use weights
PUMS records are a sample, not a full count. To estimate population totals
or averages, you must use the PWGTP (person weight) column:
Server-side filtering – You can filter records before they are downloaded to speed up large queries:
# Only employed people with wages over $0
employed = pypums.get_pums(
variables=["AGEP", "SEX", "WAGP"],
state="CA",
survey="acs1",
variables_filter={"WAGP": "1:999999"}, # wage range filter
)
What to try next: PUMS Microdata guide for replicate weights, standard error calculation, multi-state queries, and housing-unit variables.
Recap¶
| Task | Function | Key parameters |
|---|---|---|
| Pre-tabulated statistics | get_acs() |
geography, variables or table |
| Individual-level microdata | get_pums() |
variables, state, recode |
| Maps and spatial joins | any + geometry=True |
Requires pypums[spatial] |
Not sure which dataset to use? Read Census 101: Which Dataset? next.