# data dictionary — where to be

Every indicator in the tool, its source, vintage, extraction method, true
geography, and known biases. If a number is in the UI, its lineage is here.

## the honest-geography preamble (MAUP)

Each region is a named center point. "Residence" indicators aggregate every
county whose boundary intersects a **10-mile circle** around that point;
"access" indicators (trails, protected areas) are computed directly on a
**50-mile circle**; the vegan overlay uses the 10-mile circle directly.

This is a deliberate compromise with the **Modifiable Areal Unit Problem
(MAUP)**: statistical results change with how you draw areas, and nothing
solves that — you can only disclose it. County-sourced numbers describe the
counties, not the circle. Where counties are huge (Coconino AZ ≈ the size of
five New Jerseys), county values dilute the local signal; the UI's per-region
drill-in lists the exact county basis so you can judge. Regions may overlap
(Boulder and Denver share Jefferson County) — overlap is allowed and shown,
not hidden.

Aggregation rule: **population-weighted mean** across counties (Census
Vintage-2024 population), except density (sum of population / sum of land
area) and the radius-based OSM indicators (no county step at all).

Standardization: **z-scores across the 40 regions** per indicator. So every
score answers "compared to the other places on this list," not "compared to
America." Missing values are skipped in category means, never silently
imputed; the drill-in marks them.

Three heavy-tailed count-like indicators — protected features, population
density, vegan per 100k — are **log1p-transformed before z-scoring** (the
plan's sanctioned fallback for heavy tails). Without it, Boston's ~9,000
pocket nature reserves would swamp the Adirondacks' one giant park, and NYC
would own the entire density axis. Flagged per-indicator in the UI drill-in.

## indicators

### play
| | |
|---|---|
| **trail miles within 50 mi** | OpenStreetMap via keyless Overpass API. Sum of way lengths for `highway=path\|track\|bridleway`. **`footway` is excluded** to keep urban sidewalks from counting as trails; the cost is that some legitimate trails tagged `footway` are missed. OSM trail tagging is community-maintained — coverage is best near populated/outdoorsy areas. Queried live at build time (2026-07). |
| **protected areas within 50 mi** | OpenStreetMap: `leisure=nature_reserve`, `boundary=national_park`, `boundary=protected_area` (ways + relations). **This is a feature count, not acreage** — a substitute for the planned "% parkland" (PAD-US acreage needs GIS tooling beyond this pipeline's scope; documented substitution, not a silent drop). One giant wilderness counts once; ten pocket reserves count ten times. Interpret accordingly. |

### schools
| | |
|---|---|
| **test achievement (grades 3–8)** | Stanford Education Data Archive (SEDA) 5.0, county pooled cohort-standardized mean (`cs_mn_avg_eb`), 2009–2019. Units ≈ grade levels vs the US average. **High school is not covered by SEDA**, so the planned elem/middle/high composite is elem+middle only — documented limitation. Achievement levels correlate strongly with family income; see growth. |
| **learning growth per grade** | SEDA 5.0 grade slope (`cs_mn_grd_eb`) — how much students gain per year. Widely considered a better signal of school *effectiveness*, less confounded by demographics. |
| *rejected* | GreatSchools (licensing required — the plan bans it). |

### cost
| | |
|---|---|
| **typical home value** | Zillow ZHVI, county, all-homes 35th–65th percentile, smoothed & seasonally adjusted, latest available month (2026-05). **Per home, not per square foot** — Zillow no longer publishes $/sqft publicly; documented substitution. |
| **home price to income ratio** | ZHVI ÷ ACS median household income — how many years of gross income a typical home costs. Added after validation caught the original design making Pittsburgh look as costly as Boston: scoring raw income *rewards* rich-expensive places. The ratio is the actual affordability signal. |
| **median household income** | ACS 2019–2023 via County Health Rankings 2025 (v063). **Context only — displayed in the drill-in, never scored** (it already lives inside the ratio). |
| *dropped* | Cost per acre of land — no keyless source passed validation; dropped and documented per plan rule ("substitute and document — never silently drop" applies to categories, and the category survives on two indicators). |

### density
| | |
|---|---|
| **population density** | Census Vintage-2024 county population estimates ÷ 2023 Gazetteer land area. County-based (see MAUP preamble). **User-flippable direction** — the tool doesn't decide whether you want dense or quiet; default is prefer-low. |
| **distance to nearest major metro** | Great-circle miles from the region center to the nearest of 54 metro downtowns (MSAs ≥ ~1M). Static coordinate list in `pipeline/build.py`. Also user-flippable; default prefer-low (close = good). |

### health
| | |
|---|---|
| **primary care physicians per 100k** | HRSA Area Health Resources Files via County Health Rankings 2025 (v004), 2022 data. |
| **healthcare share of jobs** | Census County Business Patterns 2023, NAICS 62 employment ÷ total employment. CBP excludes government and self-employed workers. (And yes: this is Bureau-of-Labor-Statistics-adjacent Census business data — *not* Bureau of Land Management. The plan warned about exactly this confusion.) |

### safety
| | |
|---|---|
| **violent crime rate per 100k** | FBI UCR via County Health Rankings **2022** release (v043) — CHR dropped the measure after 2022, so the underlying vintage is a 2014 & 2016 average. **Old data, and UCR agency reporting coverage varies by state** — both are differential biases, disclosed here and in the drill-in. |
| **homicide rate per 100k** | CDC WONDER death records via CHR 2025 (v015), 2016–2022. Death certificates don't have police-reporting gaps, but rates are **suppressed in small counties** (the Adirondacks and Traverse City show missing — flagged in the UI, category falls back to violent crime alone there). |
| *gap* | Property crime: no keyless county-level source survived validation (FBI Crime Data Explorer bulk requires an API key as of 2025-06; the static NRI-style zips 403 non-browser clients). Documented gap. |

### climate hazards
| | |
|---|---|
| **flood / wildfire risk** | FEMA National Risk Index, county table, pulled from FEMA's official public ArcGIS feature service (the static ZIP on hazards.fema.gov blocks non-browser clients — same data, same agency). Flood = max(coastal, inland) risk score. **Caveat: NRI risk scores are population-relative national scores — they partially embed exposure/population, not just hazard frequency.** Wildfire *smoke* from distant fires is not captured (documented; a smoke-days dataset without keys wasn't found). |
| **heat wave risk** | **DEMOTED TO CONTEXT (2026-07-15 audit)** — displayed in the drill-in, no longer scored. NRI's heat measure is *heat-wave anomaly* risk times exposed population, which ranks Allentown above Santa Fe — technically defensible, but it contradicts how anyone reads "extreme heat." Baseline heat now lives in the weather category (summer daily high + july dew point), where the user controls what counts as too hot. Revisit if a better keyless chronic-heat dataset appears (CDC heat-days requires wonky access). |

### weather (added 2026-07-15)
| | |
|---|---|
| **annual rain, annual snowfall, winter daily high (DJF), summer daily high (JJA)** | NOAA NCEI **US Climate Normals 1991–2020**, annual/seasonal dataset, keyless per-station CSVs. Per region: nearest reporting station *per field* (a station missing snow falls through to the next nearest), searched outward to 60 mi; station ID and distance recorded in `weather_stations`. |
| **july dew point (mugginess)** | Same normals program, **hourly** dataset (july mean of HLY-DEWP-NORMAL). Only ~467 airport stations carry hourly normals, so this station is often farther from the center (cap 120 mi) — recorded per region. Dew point chosen over relative humidity because it's what people feel: 65°F+ is muggy, 55°F comfortable, 45°F dry. |
| **scoring** | Weather indicators have **no good/bad direction**. The user sets an ideal per aspect (defaults = 40-region medians) and each place scores by *closeness*: z of −\|value − ideal\|. The category weight says how much closeness matters. Single-station point measurements stand in for whole regions — mountains especially (the Adirondacks contain many microclimates; one Saranac Lake station speaks for all of them). |

### diversity
| | |
|---|---|
| **racial diversity (entropy)** | Shannon entropy over 6 ACS race/ethnicity shares (non-Hispanic White, non-Hispanic Black, Hispanic, Asian, AIAN, NHOPI) via CHR 2025. **Entropy chosen over Simpson/Herfindahl** for consistency with industry entropy — one concentration measure across the whole tool (plan's open question, resolved and documented). |
| **age balance (entropy)** | Shannon entropy over 3 age groups (<18, 18–64, 65+), same source. **Decision rationale** (plan's open question): median age isn't in any keyless county file we use; elderly-to-children ratio is directionally ambiguous (is old good?); entropy says "a place with kids, workers, and retirees all present" scores high, which matches the diversity framing and stays consistent with the category's other indicator. Elderly/children ratio can be derived from the same shares if wanted later. |

### economic character
| | |
|---|---|
| **industry diversity (entropy)** | Shannon entropy over 19 NAICS sector employment shares, County Business Patterns 2023. High = no single-industry town. |
| **industry of interest** (optional) | When flagged in the UI, that sector's establishments per 100k residents joins the category (z-scored across the 40 regions client-side). Establishment counts, not employment, to favor "many places to work" over "one giant employer." |

### vegan overlay (optional, default off)
| | |
|---|---|
| **vegan-friendly places (count)** | OpenStreetMap `diet:vegan=yes\|only` within 10 miles, scored on the **absolute count** (log-scaled). **Known differential bias, disclosed prominently**: OSM tagging is incomplete everywhere and sprawl hurts — downtown LA's 10-mile circle misses the West LA vegan belt, so LA reads low. HappyCow has no open API (rejected per keyless rule). Treat as a floor, not a census. Kept out of Health on purpose — it's a personal-preference overlay. |
| **vegan places per capita** | **DEMOTED TO CONTEXT (2026-07-15 audit)** — the per-100k denominator (everyone within 10 miles) punished big metros: NYC, with 580 tagged vegan places (the most anywhere), ranked below Madison. Displayed in the drill-in, not scored. Revisit if a coverage-corrected per-capita measure makes sense later. |

## statistics (what the tool actually computes)

- **Weights are distributions**: uniform (`lo–hi ×`) or normal (`mean ± sd`,
  truncated at 0) per category. This is Stochastic Multicriteria
  Acceptability Analysis (SMAA-2 family; Lahdelma & Salminen) in its simplest
  useful form.
- **Monte Carlo**: 4,000 weight vectors from a deterministic seeded PRNG
  (mulberry32, seed 42 — same inputs, same outputs). Each draw scores all 40
  regions: category score = mean of oriented indicator z-scores; overall =
  Σw·cat / Σw.
- **Outputs derived from draws** (never from means-of-weights — that would be
  weight-uncertainty theater): rank distributions, P(top 1), P(top 5), 90%
  credible intervals on scores, pairwise win probabilities for the top 10,
  and 90% intervals on pairwise score *differences* (computed per-draw, so
  correlation between regions is respected).
- **Clustering**: k-means (k-means++ init, deterministic seed), k ∈ 4–7
  chosen by silhouette. Pre-weight: on oriented indicator z-scores.
  Post-weight: on category scores scaled by mean user weights.
- **Compensability is accepted**: a great trails score can offset bad crime.
  That's a property of weighted sums, not a bug; per-category minimum
  thresholds are a listed future extension.
- The JS engine is fixture-tested against independently computed Python
  outputs (`data/fixtures.json`, `node test/stats.test.js`).

## sources at a glance

| source | file | vintage | keyless path |
|---|---|---|---|
| Census Gazetteer 2023 | `2023_Gaz_counties_national.zip` | 2023 | www2.census.gov |
| Census cartographic counties | `cb_2023_us_county_500k.zip` | 2023 | www2.census.gov |
| Census county pop estimates | `co-est2024-alldata.csv` | v2024 | www2.census.gov |
| County Business Patterns | `cbp23co.zip` | 2023 | www2.census.gov |
| Zillow ZHVI county | `zhvi_county.csv` | monthly → 2026-05 | files.zillowstatic.com |
| FEMA National Risk Index | `nri_counties.csv` | current release | FEMA ArcGIS feature service |
| County Health Rankings | `chr_2025.csv`, `chr_2022.csv` | 2025 / 2022 releases | countyhealthrankings.org |
| SEDA 5.0 | `seda_county_pool_cs_5.0.csv` | 2009–2019 | stacks.stanford.edu |
| OpenStreetMap | `overpass/*.json` | live at build | overpass-api.de |
| NOAA climate normals | `weather.json` + `noaa/` | 1991–2020 | ncei.noaa.gov |

Note: the Census **API** started requiring keys (discovered during this
build, 2026-07); all Census data here comes from bulk file downloads, which
remain keyless. If a source dies, `pipeline/download.py` is the single place
to point at a replacement.
