Practical Guides & Ecosystem Workflows

End-to-end recipes for evaluating transit networks from raw GTFS schedules, spatial aggregation to Uber H3 hex grids, Federal Title VI compliance reporting, and GPU choropleth rendering in Kepler.gl.

Transit Routing Pipeline

1. Compute Transit Access Equity from GTFS via r5py

This recipe demonstrates how to calculate origin-destination transit travel time matrices using r5py (the Python wrapper for Conway's R5 routing engine) and evaluate spatial inequality across neighborhood origins.

gtfs_r5py_equity.py Python 3.10+
import datetime
import geopandas as gpd
import r5py
from moveq import compute_gini, compute_palma_ratio, compute_concentration_index

# 1. Initialize R5 Transport Network (OSM road network + GTFS zip)
transport_network = r5py.TransportNetwork("osm_city.pbf", ["transit_feed.gtfs.zip"])

# 2. Load origin census centroids and destination employment opportunities
origins = gpd.read_file("census_tract_centroids.geojson")
destinations = gpd.read_file("job_centers.geojson")

# 3. Compute Travel Time Matrix for Tuesday morning peak (08:00 - 09:00)
travel_time_matrix = r5py.TravelTimeMatrixComputer(
    transport_network,
    origins=origins,
    destinations=destinations,
    departure=datetime.datetime(2026, 9, 15, 8, 0),
    transport_modes=[r5py.TransportMode.WALK, r5py.TransportMode.TRANSIT],
).compute_travel_times()

# 4. Calculate cumulative jobs accessible within 45 minutes per origin zone
access_45 = travel_time_matrix[travel_time_matrix["travel_time"] <= 45]
jobs_per_origin = access_45.groupby("from_id")["jobs_count"].sum().values
population = origins["population"].values
deprivation_rank = origins["deprivation_decile"].values

# 5. Evaluate Equity Metrics
gini = compute_gini(jobs_per_origin, population)
palma = compute_palma_ratio(jobs_per_origin, population)
ci = compute_concentration_index(jobs_per_origin, deprivation_rank, population)

print(f"45-Min Job Access Gini: {gini:.4f}")
print(f"Palma Ratio (Top 10% / Bottom 40%): {palma:.2f}")
print(f"Concentration Index: {ci:.4f} ({'Pro-Poor' if ci < 0 else 'Pro-Rich'})")
Spatial Hexagonal Indexing

2. Mitigate MAUP via Uber H3 Hexagonal Resampling

The Modifiable Areal Unit Problem (MAUP) distorts equity metrics when census boundaries have arbitrary irregular shapes. Resampling stop frequencies and population density to Uber H3 hexagons (Resolution 8 / ~460m edge) yields uniform spatial cells.

h3_equity_resampling.py h3 + moveq
import h3
import pandas as pd
from moveq import compute_gini

# 1. Map transit stops and population points to H3 Resolution 8 index
df["h3_res8"] = df.apply(lambda r: h3.latlng_to_cell(r["lat"], r["lng"], res=8), axis=1)

# 2. Group by hexagonal cell to obtain uniform spatial bins
hex_df = df.groupby("h3_res8").agg({
    "hourly_departures": "sum",
    "estimated_population": "sum"
}).reset_index()

# 3. Compute H3-standardized Gini coefficient
h3_gini = compute_gini(hex_df["hourly_departures"].values, hex_df["estimated_population"].values)
print(f"H3 Standardized Gini: {h3_gini:.4f}")
Federal Compliance Auditing

3. Audit Title VI Disparate Impact & Environmental Justice

Federal Title VI audits require transit agencies to demonstrate that major service reductions or fare changes do not create statistically significant disparate impacts on protected minority or low-income populations.

title_vi_audit.py Federal Reporting
from moveq import compute_concentration_index

# Rank 1 = Highest minority concentration / Highest poverty tracts
minority_rank = tract_df["minority_percentage_rank"].values
baseline_service = tract_df["trips_2025"].values
proposed_service = tract_df["trips_2026_proposed"].values
population = tract_df["population"].values

ci_baseline = compute_concentration_index(baseline_service, minority_rank, population)
ci_proposed = compute_concentration_index(proposed_service, minority_rank, population)

delta_ci = ci_proposed - ci_baseline
print(f"Baseline CI: {ci_baseline:+.4f}")
print(f"Proposed CI: {ci_proposed:+.4f}")
print(f"Disparity Delta: {delta_ci:+.4f}")

if delta_ci > 0.05:
    print("⚠ WARNING: Proposed service changes increase pro-rich disparity by > 5%. Title VI review required.")