This release is a pre-release and may not be stable for production use.
pycen
Lightweight Python package for exploring and acquiring U.S. Census data with intuitive spatial integration.
flowchart TD
A[Need Census data?]
A --> B & C
subgraph PYCEN["<i>pycen</i>"]
direction TB
B[<b>`explore`</b><br/>Intuitive metadata<br/>keyword search]
C[<b>`acquire`</b><br/>Data + boundaries<br/>in one call]
C --> D
C --> E
D[<b>`quick_check`</b><br/>Quality validation]
E[<b>`quick_viz`</b><br/>Instant maps]
end
B --> F
D & E --> F[Domain analysis]
style A fill:#94a3b8,stroke:#334155,stroke-width:2px,color:#000
style B fill:#3b82f6,stroke:#1e40af,stroke-width:2px,color:#fff
style C fill:#3b82f6,stroke:#1e40af,stroke-width:2px,color:#fff
style D fill:#22c55e,stroke:#15803d,stroke-width:2px,color:#fff
style E fill:#22c55e,stroke:#15803d,stroke-width:2px,color:#fff
style F fill:#94a3b8,stroke:#334155,stroke-width:2px,color:#000
style PYCEN fill:#1e293b,stroke:#64748b,stroke-width:2px,color:#fff
overview
pycen makes the exploration and acquisition of U.S. Census data accessible and intuitive for spatial workflows. The explore module presents browsable Census API metadata via topic-organized, interactive nested tables, with customizable themes to highlight curated variable recipes. It also supports natural‑language keyword searches for efficient variable discovery. The acquire module streamlines data processing: one function call returns both data and boundaries as a GeoDataFrame with built-in quality checks and rapid visualizations;simple tabular or boundaries-only downloads are separately callable. pycen pulls live data products with efficient local caches to keep iterations fast, smooth, and reproducible. The multi‑year fetch function enables longitudinal comparisons tracking change over time.
setup
pip install pycen # Python 3.10+
pip install -U pycen # upgrade an existing install
A free Census API key is required (since May 2026): get one at https://www.census.gov/data/developers.html, activate it from the email, then run pycen.set_api_key("YOUR_KEY").
sample use
basic workflow
import pycen
from pycen import explore, acquire
pycen.set_api_key("YOUR_KEY") # required, see setup
# 1. Explore variables
# `browse` and `search` return interactive tables
# `lookup` returns details
explore.browse(year=2023, dataset="acs5").show()
explore.search("vehicle", year=2023, dataset="acs5").show()
explore.lookup("B08201_002E", year=2021, dataset="acs5")
# 2. Acquire data
## continental US income gini map
gdf = acquire.get_censhp(
variables={"B19083_001E":"gini_index"},
geography="place", # if no state/county, gets nationwide
dataset="acs5",
year=2023,
)
acquire.quick_check(gdf) # returns N/A summary
acquire.quick_viz(gdf, "gini_index") # returns map + distribution histogram
acquire.quick_viz(gdf, "gini_index", palette="viridis") # optional customizable palette
acquire.quick_viz(gdf, "gini_index",save_path='gini_index.png') # optional save
## finer scale
## Cook County income gini at tract level
gdf = acquire.get_censhp(
variables={"B19083_001E":"gini_index"},
geography="tract",
county="Cook County",
state="IL",
dataset="acs5",
year=2023,
)
acquire.quick_viz(gdf, "gini_index")
## neighborhood analyses
## Chicago super commuters
gdf = acquire.get_censhp(
variables={"B08303_012E":"commute_over_60min", "B08303_001E":"total_commuters"},
geography="block group",
place="Chicago city",
#county="Cook County", # optional, add for clarity
state="IL",
dataset="acs5",
year=2023
)
gdf["pct_super_commuters"] = gdf["commute_over_60min"] / gdf["total_commuters"] * 100
acquire.quick_viz(gdf, "pct_super_commuters")
## decennial data supports block-scale (finest)
## Chicago housing vacancy rates at block level
select_var={
"H001003": "vacant_hh",
"H001001": "total_hh"
}
gdf = acquire.get_censhp(
variables=select_var,
geography="block",
county="Cook County",
state="IL",
dataset="dec_pl",
year=2010,
)
gdf['vacancy_rate'] = gdf['vacant_hh'] / gdf['total_hh'] * 100
acquire.quick_viz(gdf, "vacancy_rate")
tabular data workflow
# 3. Tabular data only
df = acquire.get_census(
variables=["B25032_022E"], # renter-occupied, mobile home
geography="tract",
state="CA",
year=2021,
)
# 4. Single-year, multivariable tabular data for comparative analysis
import pandas as pd
import matplotlib.pyplot as plt
from pycen import acquire
vars_race = {
'B03002_001E': 'total',
'B03002_003E': 'nh_white',
'B03002_004E': 'nh_black',
'B03002_006E': 'nh_asian',
'B03002_005E': 'nh_aian',
'B03002_007E': 'nh_nhpi',
'B03002_008E': 'nh_other',
'B03002_009E': 'nh_two_or_more',
'B03002_012E': 'hispanic',
}
df_race = acquire.get_census(
variables=vars_race,
geography='county',
state='CA',
county='Alameda',
dataset='acs5',
year=2023,
)
row = df_race.iloc[0]
other = row['nh_aian'] + row['nh_nhpi'] + row['nh_other'] + row['nh_two_or_more']
vals = {
'White (NH)': row['nh_white'],
'Black (NH)': row['nh_black'],
'Asian (NH)': row['nh_asian'],
'Other (NH)': other,
'Hispanic (any race)': row['hispanic'],
}
pct = {k: v / row['total'] * 100 for k, v in vals.items()}
plt.figure(figsize=(7, 4))
plt.bar(pct.keys(), pct.values(), color=['#4c78a8', '#f58518', '#54a24b', '#b279a2', '#e45756'])
plt.ylabel('Population %')
plt.title('Alameda County, CA -— Race/Ethnicity (ACS 2023)')
plt.xticks(rotation=25, ha='right')
plt.tight_layout()
plt.show()
# 5. Multi-year tabular data for trend analysis
# B08006_017E = worked from home
# census reference on using acs1 vs acs5:
# https://www.census.gov/content/dam/Census/library/publications/2018/acs/acs_general_handbook_2018_ch03.pdf
df_long = acquire.get_census(
variables={'B08006_017E': 'wfh_workers', 'B08101_001E': 'total_workers'},
geography='county',
state='CA',
years=[2019, 2021, 2022, 2023], # no 1-year data for 2020
dataset='acs1',
merge='long'
)
# calc WFH percentage
df_long['wfh_pct'] = (df_long['wfh_workers'] / df_long['total_workers']) * 100
# focus on major counties
major = df_long[df_long['NAME'].str.contains('San Francisco|Alameda|Santa Clara|Contra Costa|San Mateo')]
# plot
import matplotlib.pyplot as plt
for county in major['NAME'].unique():
county_data = major[major['NAME'] == county]
plt.plot(county_data['year'], county_data['wfh_pct'], marker='o', label=county)
plt.title('Remote Work: Bay Area Counties (ACS 1-year Estimate)')
plt.ylabel('Work From Home (%)')
plt.xlabel('Year')
plt.xticks(sorted(major['year'].unique()))
plt.legend()
plt.grid(alpha=0.3)
plt.tight_layout()
core functions
Explore
explore.search(query, year, dataset)- supports exact term match and fuzzy keyword searchexplore.browse(year, dataset)- view all variables via interactive tree table with theme variable highlightsexplore.lookup(code, year, dataset)- inspect variable details
Acquire
acquire.get_censhp(...)- data + boundaries --> GeoDataFrameacquire.get_census(...)- data only --> DataFrameacquire.get_boundaries(...)- boundaries only --> GeoDataFrameacquire.quick_check(gdf)- N/A values summaryacquire.quick_viz(gdf, column, palette, save_path)- exploratory map + distribution histogram for select variable
Info
pycen.get_product()- list datasets and yearspycen.get_geography()- list geography levels by dataset
Geo Helpers
from pycen import geography
geography.search('Oakland', state='CA') # most powerful, return all related info
# state and county lookup
geography.state('CA') # can also search by 'California' or fips code '06'
geography.county('Alameda', state='CA')
# list geographies
geography.list_places('CA', query='Oakland') # minimal search
pycen.geography.list_cbsa(query='new york',year=2023, limit=5) # specify year and return limit if multi-match
pycen.geography.list_csa(query='detroit',year=2023, limit=5) # look up csa name
geography.list_counties('CA')
Themes
pycen.set_theme(name_or_dict)- set active theme name or register a custom theme (dict)pycen.get_theme_settings()- get active theme name (defaults to a general curation of useful variables)pycen.explore.get_theme(name=None)- get theme details (dict); defaults to active themepycen.list_themes()- list available theme names (includes session custom themes)
Notes
- Datasets:
acs5,acs1,dec_pl,dec_sf1 - Spatial features require:
geopandas,pygris - Geographies are resolved per dataset/year from Census geography metadata (live/cache/static)
- Optional:
richenables prettier terminal tables forexplore.search().show() geography.search()uses a bundled 2020 snapshot by default; if a different vintage is requested, it attempts a live code-list fetch and falls back to 2020 if unavailable
Metadata
Release files for pycen 0.1.0a5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pycen-0.1.0a5.tar.gz | 609.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pycen-0.1.0a5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.2 MB
Release files / pycen-0.1.0a5.tar.gz
| Download URL | pycen-0.1.0a5.tar.gz |
|---|---|
| Size | 609.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99dcfbe63950a9769f9cde74eccd91263e8de6d9f8487e0af961a860f46232bf
|
|
BLAKE2b-256 checksum How to use checksums |
2014f29339c2d9202a4abc4aab883d5687be48b2c64cf6c9209ffb8e6e5ccc04
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / pycen-0.1.0a5-py3-none-any.whl
| Download URL | pycen-0.1.0a5-py3-none-any.whl |
|---|---|
| Size | 611.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7bd358d3b044889469940c48204859a234fdcdf35d902520d35e98d02c105a77
|
|
BLAKE2b-256 checksum How to use checksums |
7d46264afc15fa73e0e7e7a1a1cab84d9b0b9da1645db3c4be91a464f7c2d97b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|