--- sidebar_position: 5 --- # Census Bureau Shapefiles Geographic boundary data from the U.S. Census Bureau TIGER/Line program. ## Overview The Census Bureau provides comprehensive geographic boundary files (shapefiles) for all U.S. administrative divisions. These are essential for mapping, spatial analysis, and geographic visualization. **Data Source:** [U.S. Census Bureau TIGER/Line Files](https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html) **Update Frequency:** Annual (typically released in summer) **Latest Vintage:** 2023 ## Available Boundary Types ### 1. States - **File:** `cb_{year}_us_state_500k.zip` - **Features:** 50 states + DC + territories (56 total) - **Use Cases:** State-level aggregation, choropleth maps, jurisdiction lookup - **Size:** ~3 MB ### 2. Counties - **File:** `cb_{year}_us_county_500k.zip` - **Features:** 3,143 counties and county equivalents - **Use Cases:** County-level analysis, regional mapping, jurisdiction boundaries - **Size:** ~15 MB ### 3. ZIP Code Tabulation Areas (ZCTAs) - **File:** `cb_{year}_us_zcta520_500k.zip` - **Features:** ~33,000 ZIP Code Tabulation Areas - **Use Cases:** Postal code mapping, demographic analysis, service area definition - **Size:** ~350 MB - **Note:** ZCTAs are statistical approximations of ZIP codes, not exact postal routes ## Cartographic vs. Full TIGER Files We use **Cartographic Boundary Files** (cb_* prefix) instead of full TIGER/Line files because: | Feature | Cartographic (cb_) | Full TIGER (tl_) | |---------|-------------------|------------------| | **Detail** | Simplified 1:500k | High detail 1:100k | | **File Size** | Smaller (faster downloads) | Larger (slower) | | **Rendering** | Faster (optimized for maps) | Slower | | **Water Boundaries** | Clipped at shoreline | Include water features | | **Use Case** | Web mapping, visualization | Detailed GIS analysis | **Recommendation:** Use cartographic files for Open Navigator's web-based mapping. ## Installation & Setup ### Prerequisites ```bash # Shapefile processing requires geopandas pip install geopandas pyogrio ``` ### Download Script ```bash # Download all shapefiles for 2023 python scripts/datasources/census/download_shapefiles.py --year 2023 # Download only states and counties python scripts/datasources/census/download_shapefiles.py --year 2023 --types states counties # Download and extract automatically python scripts/datasources/census/download_shapefiles.py --year 2023 --extract # Download only ZIP codes python scripts/datasources/census/download_shapefiles.py --year 2023 --types zcta ``` ## Data Storage Downloaded shapefiles are cached in: ``` data/cache/census/shapefiles/{year}/ ├── cb_2023_us_state_500k.zip ├── cb_2023_us_county_500k.zip └── cb_2023_us_zcta520_500k.zip ``` Extracted files (if `--extract` used): ``` data/cache/census/shapefiles/{year}/ ├── cb_2023_us_state_500k/ │ ├── cb_2023_us_state_500k.shp # Geometry │ ├── cb_2023_us_state_500k.shx # Shape index │ ├── cb_2023_us_state_500k.dbf # Attributes │ ├── cb_2023_us_state_500k.prj # Projection │ └── cb_2023_us_state_500k.xml # Metadata ├── cb_2023_us_county_500k/ └── cb_2023_us_zcta520_500k/ ``` ## Loading Shapefiles ### GeoPandas (Recommended) ```python import geopandas as gpd from pathlib import Path # Load from ZIP (no extraction needed!) states = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_state_500k.zip") # Or from extracted directory states = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_state_500k/cb_2023_us_state_500k.shp") # View data print(states.head()) print(f"Total states: {len(states)}") print(f"CRS: {states.crs}") # Should be EPSG:4269 (NAD83) ``` ### Key Attributes #### States - `STATEFP` - State FIPS code (2 digits) - `STUSPS` - State postal abbreviation (2 letters) - `NAME` - State name - `ALAND` - Land area (square meters) - `AWATER` - Water area (square meters) #### Counties - `STATEFP` - State FIPS code - `COUNTYFP` - County FIPS code (3 digits) - `GEOID` - Combined state+county FIPS (5 digits) - `NAME` - County name - `NAMELSAD` - Full name with legal/statistical designation #### ZCTAs - `ZCTA5CE20` - 5-digit ZCTA code - `ALAND` - Land area (square meters) - `AWATER` - Water area (square meters) ## Conversion to Other Formats ### GeoJSON (for web mapping) ```python import geopandas as gpd # Load shapefile states = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_state_500k.zip") # Convert to Web Mercator for web maps states_web = states.to_crs("EPSG:3857") # Save as GeoJSON states_web.to_file("data/gold/boundaries/states.geojson", driver="GeoJSON") ``` ### GeoParquet (for efficient storage) ```python import geopandas as gpd # Load shapefile counties = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_county_500k.zip") # Save as GeoParquet (smaller, faster than GeoJSON) counties.to_parquet("data/gold/boundaries/counties.parquet") # Load back counties = gpd.read_parquet("data/gold/boundaries/counties.parquet") ``` ### Simplified Geometries (for faster rendering) ```python import geopandas as gpd # Load and simplify zcta = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_zcta520_500k.zip") # Simplify to 100m tolerance (reduces file size) zcta_simple = zcta.copy() zcta_simple['geometry'] = zcta_simple.geometry.simplify(tolerance=100) # Save simplified version zcta_simple.to_file("data/gold/boundaries/zcta_simplified.geojson", driver="GeoJSON") ``` ## Integration with Open Navigator ### 1. Jurisdiction Boundary Lookup Match jurisdiction names to their geographic boundaries: ```python import geopandas as gpd import pandas as pd # Load jurisdictions from Open Navigator jurisdictions = pd.read_parquet("data/gold/jurisdictions_deduplicated.parquet") # Load county boundaries counties = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_county_500k.zip") # Merge on name + state merged = jurisdictions.merge( counties[['GEOID', 'NAME', 'STATEFP', 'geometry']], left_on=['jurisdiction_name', 'state_code'], right_on=['NAME', 'STATEFP'], how='left' ) # Save with geometries merged_gdf = gpd.GeoDataFrame(merged, geometry='geometry') merged_gdf.to_parquet("data/gold/jurisdictions_with_boundaries.parquet") ``` ### 2. Choropleth Mapping Create interactive maps colored by data values: ```python import geopandas as gpd import folium # Load state boundaries states = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_state_500k.zip") # Example: Count of jurisdictions per state jurisdiction_counts = jurisdictions.groupby('state_code').size().reset_index(name='count') # Merge with geometries states_data = states.merge( jurisdiction_counts, left_on='STUSPS', right_on='state_code', how='left' ) # Create choropleth map m = folium.Map(location=[39.8, -98.5], zoom_start=4) folium.Choropleth( geo_data=states_data, data=states_data, columns=['STUSPS', 'count'], key_on='feature.properties.STUSPS', fill_color='YlOrRd', legend_name='Jurisdiction Count' ).add_to(m) m.save('jurisdiction_heatmap.html') ``` ### 3. Spatial Joins Find which jurisdictions overlap with which ZIP codes: ```python import geopandas as gpd # Load data counties = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_county_500k.zip") zcta = gpd.read_file("data/cache/census/shapefiles/2023/cb_2023_us_zcta520_500k.zip") # Spatial join (find which county each ZCTA is in) zcta_counties = gpd.sjoin( zcta[['ZCTA5CE20', 'geometry']], counties[['GEOID', 'NAME', 'geometry']], how='left', predicate='intersects' ) # Save mapping zcta_counties.to_parquet("data/gold/zcta_to_county_mapping.parquet") ``` ## Use Cases in Open Navigator ### 1. Policy Heatmap Enhancement - Add actual geographic boundaries to policy heatmap - Show exact county/state shapes instead of markers - Enable click-to-zoom on boundary ### 2. Geographic Search - "Find all nonprofits in ZIP code 35401" - "Show meetings within 50 miles of this location" - Point-in-polygon lookups for jurisdiction detection ### 3. Service Area Visualization - Display coverage areas for advocacy organizations - Show legislative district boundaries - Map nonprofit service regions ### 4. Data Validation - Verify jurisdiction names against official boundaries - Detect geocoding errors (city in wrong state) - Fill missing location data using boundaries ## File Size Considerations **Full Downloads:** - States: ~3 MB - Counties: ~15 MB - ZCTAs: ~350 MB - **Total: ~368 MB** **Recommendations:** - Store in `data/cache/` (excluded from git) - Convert to GeoParquet for 50-70% size reduction - Simplify geometries for web display - Consider only downloading needed regions (e.g., priority states) ## License & Attribution **License:** Public Domain (U.S. Government Work) **Attribution (recommended):** ``` Boundary data from U.S. Census Bureau TIGER/Line Shapefiles https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html ``` ## Troubleshooting ### Installation Issues If GeoPandas install fails: ```bash # Use conda (easier for spatial packages) conda install geopandas # Or use pyogrio instead of fiona pip install geopandas pyogrio ``` ### CRS/Projection Issues TIGER files use NAD83 (EPSG:4269). For web maps, convert to Web Mercator (EPSG:3857): ```python gdf_web = gdf.to_crs("EPSG:3857") ``` ### Large File Handling For ZCTAs (350 MB), consider: ```python # Load only needed columns zcta = gpd.read_file("cb_2023_us_zcta520_500k.zip", columns=['ZCTA5CE20', 'geometry']) # Filter to specific states zcta_al = zcta[zcta['ZCTA5CE20'].str.startswith('35')] # Alabama ZCTAs ``` ## Related Data Sources - [Census ACS Data](./census-acs.md) - Demographic data for these boundaries - [Jurisdiction Discovery](./jurisdiction-discovery.md) - Finding local governments - [NCES Data](./census-data.md) - School district boundaries (separate) ## Next Steps After downloading shapefiles: 1. Convert to GeoParquet for efficient storage 2. Join with Open Navigator jurisdiction data 3. Integrate into PolicyMap component for boundary display 4. Add spatial search capabilities to API