Scaling Statewide: An Article-Reported Case

The article reports an expansion from about 2,000 to 9,039 tracts to teach what scales directly and what requires adaptation. The counts, timings, and statewide findings have not been publicly reproduced.

The article reports a pilot covering 7 Bay Area and major metro counties and approximately 2,000 census tracts. 1 The article-reported statewide case includes all 58 counties, 9,039 residential tracts, and more than 200 transit agencies, a reported 4.5-fold increase in tract count. Those counts and the resulting findings have not been publicly reproduced.

The case is retained to teach what can scale directly, what may require adaptation, and what to validate before interpreting statewide output.


The Scale of Statewide Analysis

Article-reported pilot and statewide scale; not publicly reproduced
Metric 7-County Pilot Statewide
Census tracts ~2,000 9,039
Transit agencies 8 200+
Transit stops 24,421 64,060
Grocery stores ~6,600 24,850+
Origin-destination pairs ~13M ~225M

The article reports 9,039 residential tracts after exclusions. The Census vintage, statewide tract universe, and filtering record are under reconciliation, so that count should not yet be treated as a verified subset.


What Scaled Well

Census Data Acquisition

The article reports approximately linear scaling for its ACS downloads. The reusable point is that the same county-wildcard API pattern can request one county or all 58:

from census import Census

c = Census("YOUR_API_KEY")

# Get data for all California tracts
income = c.acs5.state_county_tract(
    fields=["B19013_001E"],  # Median household income
    state_fips="06",         # California
    county_fips="*",         # All counties
    tract="*"                # All tracts
)

The article reports processing time in minutes rather than hours. That timing has not been publicly reproduced and will vary with the API, hardware, caching, and selected variables.

Grocery Store Distance Calculations

The KD-tree spatial indexing approach handles large datasets efficiently, but distance calculations must use a projected coordinate reference system rather than raw latitude and longitude in degrees:

import numpy as np
from scipy.spatial import cKDTree

# Project both GeoDataFrames to California Albers (meters).
distance_crs = "EPSG:3310"
stores_projected = stores_gdf.to_crs(distance_crs)
tracts_projected = tract_centroids_gdf.to_crs(distance_crs)

# Build once, then query every tract centroid.
store_xy = np.column_stack([
    stores_projected.geometry.x,
    stores_projected.geometry.y,
])
tract_xy = np.column_stack([
    tracts_projected.geometry.x,
    tracts_projected.geometry.y,
])

tree = cKDTree(store_xy)
distances_m, indices = tree.query(tract_xy, k=1)
distances_miles = distances_m / 1609.344

The article reports finding the nearest store among 24,850 options for 9,039 tracts in under 30 seconds. That benchmark has not been publicly reproduced; the transferable lesson is that a KD-tree avoids a full pairwise search.

Vulnerability Index Calculation

The composite index calculation is pure arithmetic on DataFrames. It scales to any number of rows without special handling:

# Each component normalized 0-1, then weighted
df['vulnerability_index'] = (
    0.25 * df['food_access_score'] +
    0.25 * df['poverty_score'] +
    0.20 * df['renter_score'] +
    0.15 * df['minority_score'] +
    0.15 * df['sprawl_score']
)


What Required Adaptation

Transit Data Aggregation

Managing individual agency GTFS downloads becomes harder as agency count grows. The article reports more than 200 agencies and estimates that manual acquisition would take weeks; those counts and timing are not publicly reproduced.

Solution: Use a documented Cal-ITP statewide resource from the official California Open Data catalog. 2 The article describes this source as an aggregated route to statewide feed data. The catalog exposes individual downloadable resources, not a guaranteed /stops.csv suffix on a dataset landing page. Select the current stops resource in the catalog, record its resource URL, retrieval date, and checksum, then stage the downloaded file locally.

from pathlib import Path
import pandas as pd

# Download the current Cal-ITP `stops` CSV resource from the official
# catalog first. Preserve the source URL, retrieval date, and checksum
# in the input manifest rather than constructing a URL from the landing page.
stops_path = Path("data/raw/calitp_stops.csv")
if not stops_path.exists():
    raise FileNotFoundError(
        "Download the current Cal-ITP stops resource and update the input manifest."
    )

stops = pd.read_csv(stops_path)

# Filter to California bounds
stops = stops[
    (stops['stop_lat'] >= 32) & (stops['stop_lat'] <= 42) &
    (stops['stop_lon'] >= -125) & (stops['stop_lon'] <= -114)
]

The shown extract contains stop locations only, so it can support a stop-proximity measure but cannot calculate scheduled travel time. That is a limitation of this extract, not of Cal-ITP's published data as a whole. Cal-ITP also publishes statewide schedule analytics tables for feeds, routes, stops, trips, and trip stops. Its official publication documentation says those aggregated tables are intended for statewide analytics and are not a trip-planner ingestion product. A routing workflow therefore needs a validated, routing-compatible set of GTFS schedule inputs or an explicit transformation from the analytics tables; a stops CSV alone is insufficient.

Memory Management

The article reports roughly 225 million origin-destination pairs, a scale likely to exceed typical laptop memory if materialized densely. That pair count is not publicly reproduced; the following strategies remain generally useful:

Chunked processing: Process tracts in batches of 500-1000, write results to disk, then concatenate.

Sparse representation: For binary classifications (is this tract a mobility desert?), store only the classification rather than all underlying data.

On-disk computation: Use Dask or similar tools for out-of-core DataFrames when necessary.

Sprawl Index Normalization

The article reports raw sprawl values from 0.005 to 27,942 in the pilot and says that scale dominated other 0-to-1 components. The exact range and effect have not been publicly reproduced; the general lesson is to inspect component scales before combining them.

Solution: Percentile rank normalization:

# Rank-based normalization to 0-1 scale
df['sprawl_score'] = df['sprawl_index'].rank(pct=True)

This preserves the ordering (more sprawl = higher score) while constraining values to the same 0-1 range as other components.


Article-Reported Statewide Findings

The findings in this section are article-reported and not publicly reproduced.

Finding 1: Reported Regional Clustering

The article describes geographic clusters in its statewide output:

Central Valley corridor: Merced, Madera, Fresno, Tulare, and Kern form a contiguous high-vulnerability band. This suggests regional factors (agricultural economy, transportation infrastructure, and historical investment patterns) that transcend county boundaries.

Coastal gradient: Vulnerability increases inland from the coast throughout California. This gradient is continuous, not county-bounded.

Bay Area exception: The Bay Area shows a reversed pattern, with higher vulnerability in some coastal areas (San Francisco's Tenderloin, Oakland's flatlands) than inland suburbs.

Finding 2: Reported County Averages Hide Tract Variation

The article reports a Los Angeles County mean of 0.38 and tract values from 0.15 to 0.72. It describes similar patterns in San Diego, Sacramento, and Fresno. These values are provisional; the methodological point is that an average can hide within-county variation.

Finding 3: Reported Small-County Rankings Are Unstable

The article reports the following small-county populations and tract counts:

  • Alpine: 1,200 residents, 2 tracts
  • Sierra: 3,200 residents, 3 tracts
  • Modoc: 8,700 residents, 5 tracts

With few tracts, county averages are heavily influenced by individual tract values. A single high-vulnerability tract in a 2-tract county pulls the county average dramatically.

Small denominators make means sensitive to individual tracts. The article's reported Alpine ranking is useful for teaching that issue, but it is not a publicly reproduced basis for comparing resident welfare across counties.

Finding 4: Article-Reported 12% Mobility-Desert Share

The article reports 1,086 mobility-desert tracts, or 12% of its residential-tract universe. 3 It attributes the difference from the pilot to broader Cal-ITP coverage. Neither the count nor that explanation is publicly reproduced.


Computational Architecture

The statewide analysis pipeline:

1. Data Acquisition (parallel)
   ├── Census demographics (ACS API)
   ├── Grocery stores (Google Places + USDA)
   ├── Transit stops (Cal-ITP)
   └── Tract geometries (Census TIGER)

2. Preprocessing
   ├── Filter to residential tracts
   ├── Calculate population-weighted centroids
   ├── Geocode and validate store locations
   └── Deduplicate transit stops

3. Spatial Analysis
   ├── KD-tree for grocery distances
   ├── KD-tree for transit stop distances
   └── Count stops within radius

4. Index Calculation
   ├── Normalize each component
   ├── Weight and combine
   └── Classify vulnerability levels

5. Aggregation
   ├── Tract-level output
   ├── County summaries
   └── Regional aggregations

The article reports a total runtime of approximately 45 minutes on an M1 MacBook Pro, with most time spent on downloads and preprocessing. This benchmark has not been publicly reproduced.


Validation Checks for Statewide Analysis

Scaling up increases error risk. These validation steps helped ensure quality:

1. Row Count Verification

After each merge operation, verify row counts against a documented tract universe. The example below uses the article-reported 9,039 count, which remains under reconciliation and should be replaced by the verified target for a real run:

assert len(merged_df) == 9039, f"Expected 9039 tracts, got {len(merged_df)}"

Unflagged row loss from failed joins is a common bug in scaled analysis.

2. Missing Value Audit

Check for unexpected nulls in key fields:

missing_report = df.isnull().sum()
assert missing_report['vulnerability_index'] == 0

3. Distribution Sanity Checks

Check impossible values and compare the distribution with a frozen benchmark from a validated run. A bounded composite index does not need to be normally distributed, and an arbitrary target mean should not be used as a pass condition:

index = df['vulnerability_index']
assert index.notna().all()
assert index.between(0, 1, inclusive='both').all()

# Review quantiles and compare them with a versioned, validated benchmark.
print(index.describe(percentiles=[0.01, 0.10, 0.50, 0.90, 0.99]))

4. Geographic Coverage Verification

Map the data to verify all counties are present:

assert df['county_fips'].nunique() == 58

5. External Benchmark Comparison

Compare key metrics against published data:

  • Total California population (Census)
  • Grocery store counts (USDA)
  • Transit agency counts (Cal-ITP documentation)

Remaining Limitations

Transit Time Routing Not Scaled

The article states that the statewide case uses stop proximity as a transit-accessibility proxy and that full r5py travel-time routing was limited to the 7-county pilot. No public run record currently reproduces either implementation.

Using the article-reported 9,039 tracts and approximately 25,000 stores, full transit-time routing would require:

  • Assembling and validating routing-compatible GTFS schedule inputs across the relevant agencies and service dates
  • Building routing networks for each region
  • Processing ~225 million origin-destination pairs
  • Article-estimated compute time: 50-100 hours, not benchmarked in a public run

This was outside the article's reported scope. Stop proximity is a different measure from travel time and should be validated for the intended classification before being treated as an adequate proxy. Availability of statewide analytics tables does not by itself make the stops-only extract a routable network.

Temporal Snapshot

The article states that most source snapshots date to November 2025 and that the ACS data cover 2019-2023. No frozen input manifest is public, so those vintages should be confirmed before reuse.

The analysis provides a snapshot rather than a longitudinal trend. Repeating the analysis annually would reveal trends.

Uneven Data Quality by Region

Data quality varies by county:

  • Urban counties have better grocery store coverage because Google Places has more data where there are more businesses and users.
  • Rural counties may have undercounted stores, particularly independent grocers and general stores not in commercial databases.
  • The article reports stop data from more than 200 agencies and incomplete coverage of some demand-responsive and small rural services. Current coverage should be checked directly against Cal-ITP.

These gaps can bias rural estimates systematically if missing stores or transit services are concentrated in rural counties. The direction and magnitude require validation, so rural comparisons should be treated as uncertain rather than assumed unbiased.


Public Materials

Article only. The repository cited in the original version no longer resolves. No matching public analysis script, frozen input manifest, run record, or saved output is currently linked for the pilot or statewide populations, counts, timings, classifications, or findings reported here.


Notes

[1] Seven-county pilot included San Francisco, San Mateo, Santa Clara, Alameda, Contra Costa, Sacramento, and San Diego. Analysis completed October 2025.

[2] Cal-ITP (California Integrated Travel Project) aggregates GTFS data from California transit agencies. Current resources are listed in the official California Open Data catalog; the Cal-ITP publication documentation describes the statewide schedule tables as analytics resources rather than trip-planner inputs.

[3] Mobility desert classification: tracts with grocery store within 1 mile but transit stop > 0.5 miles or < 2 stops within 0.5 miles.


Tags: #FoodSecurity #California #Scaling #DataPipeline #GTFS #CalITP #Methodology #BigData


Next in this series: Who gets left behind? Analyzing transit access disparities by race and ethnicity.

How to Cite This Research

Cholette, V. (2025, December 7). Scaling statewide: An article-reported case. Too Early To Say. https://tooearlytosay.com/research/methodology/scaling-statewide/
Copy citation