No description
Find a file
2026-05-07 12:35:57 -07:00
.gitignore Initial Commit 2026-05-07 12:35:57 -07:00
geo_heatmap.py Initial Commit 2026-05-07 12:35:57 -07:00
README.md Initial Commit 2026-05-07 12:35:57 -07:00
requirements.txt Initial Commit 2026-05-07 12:35:57 -07:00

geo-heatmap

Generate geographic visualizations from a CSV of street addresses.

Setup

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Usage

python geo_heatmap.py <csv> [options]

Quick examples

# Auto-detect address column, output hexbin heatmap
python geo_heatmap.py addresses.csv

# Multi-column address, specific output file
python geo_heatmap.py addresses.csv \
  --address-cols "Street,City,State,Zip" \
  --output heatmap.png

# ZIP code choropleth (no geocoding needed)
python geo_heatmap.py addresses.csv \
  --mode choropleth \
  --zip-col PostalCode \
  --output choropleth.png

# Lock viewport for side-by-side comparison of two years
python geo_heatmap.py 2025.csv --mode choropleth --zip-col PostalCode \
  --center "38.9,-77.0" --radius 100 --vmax 50 --output 2025.png

python geo_heatmap.py 2026.csv --mode choropleth --zip-col PostalCode \
  --center "38.9,-77.0" --radius 100 --vmax 50 --output 2026.png

Options

Address source (pick one, or omit to auto-detect)

Flag Description
--address-col COL Column containing full address strings
--address-cols COL1,COL2,... Columns to join into a full address (e.g. Street,City,State,Zip)
--lat-col COL Latitude column — skips geocoding entirely
--lon-col COL Longitude column — must be used with --lat-col
--country-col COL ISO country code column (e.g. US, CA) — improves geocoding accuracy
--zip-col COL ZIP code column for --mode choropleth (auto-detected if name contains zip/postal)
--zip-shapefile PATH Path to a local ZCTA .shp file — downloaded automatically on first run if omitted

Output

Flag Description
--mode hexbin Hexagonal bin density map (default)
--mode choropleth ZIP code choropleth — faster, no geocoding required
--output FILE, -o FILE Output file path (default: heatmap.png)
--title TEXT Map title
--dpi N Image resolution in DPI (default: 150)
--no-points Hide the white dot overlay on hexbin maps
--pin "LAT,LON,Label" Add a labeled pin; repeatable for multiple pins
--interactive Output an interactive HTML map (hexbin mode only)

Viewport

Flag Description
--center "LAT,LON" Fix the map center (e.g. "38.9,-77.0")
--radius KM Radius in km around --center (default: auto-fit to 95% of points)
--clip PCT Percentile trimmed from each edge when auto-fitting the viewport (default: 5)

Color scale

Flag Description
--vmin N Minimum count for the color scale (default: auto)
--vmax N Maximum count for the color scale (default: auto)
--gridsize N Hexbin grid resolution — higher = finer detail (default: 50)

Geocoding

Flag Description
--cache FILE Geocoding cache file (default: .geocache.json)

Geocoding notes

  • Uses Nominatim (OpenStreetMap) — free, no API key required
  • Rate-limited to ~1 request/second per Nominatim's usage policy
  • Results are cached to .geocache.json; re-runs skip already-geocoded addresses and the cache is saved every 25 lookups and on Ctrl+C
  • When a full address isn't found, falls back to city + state + ZIP
  • --country-col restricts Nominatim's search to the correct country, improving hit rate for international datasets

Choropleth notes

  • Uses Census TIGER ZCTA boundaries (2020 vintage)
  • The shapefile (~100 MB) is downloaded automatically on first run and cached to .zcta_cache/
  • Only US ZIP codes (5-digit) are supported; other formats are skipped with a warning
  • No geocoding is performed — ZIP codes are read directly from the CSV