# Scores v5 — Partisan EAI (neutral-year), Partisan Edge, Hidden Lean (2026-10-18)

The ratings on every place page of mainepoliticaldata.com. Version 5 is version 4 (the methodology audit of 2026-10-17,
`claude/scores-methodology-audit-2026-10-17.md`; the plan `claude/scores-v4-plan-2026-10-17.md`) with the changes Matt decided on
2026-10-18 (PENDING-WORK P-202): the **Partisan EAI now means the neutral-year expectation** (the place's lean relative to Maine plus
Maine's own baseline), the U.S. House reference is repaired so every unit has the same zero, the registration tile ("Partisan Edge")
comes from the latest Secretary of State file, and the Performance Gap is renamed Hidden Lean. **No estimation model: every figure is
arithmetic on the public record**, and the whole calculation runs in about a minute (`scripts/`). `scores_v3/`, `scores_v3.1/` and
`scores_v4/` stay as reference.

Live on the site since 2026-10-18 (`site-design/versions.json` "scores": "v5"). The public explanation is the Methodology page
(`site-design/methodology_partisan_evaluation.html`); this README is the data dictionary. The code and tables are published at
https://mainepoliticaldata.com/data/scores/ (site_export.py copies this folder there).

## Inputs
- Election results v3.14 (`election-results/maine_election_results_v3.14_data.zip`): `results_town_long.csv` — town rows, General elections
  1990–2024, President / Governor / U.S. Senate / U.S. House; State House 2008–2024 for the threshold check; President 1980–2024 town +
  UOCAVA lines for the Maine baseline (`scripts/president_maine_1980_2024.csv`, equal to the official statewide totals).
- National presidential totals (the other half of the baseline): FEC "Federal Elections" official results, Democratic and Republican
  votes 1980–2024, typed into `v5_scores.py` (`US_PRES`).
- Registration v7.2 (`registration-data/maine_registration_master_v7.2.zip`, `out/`): the 2024-11-05 file (Hidden Lean, district vote weights)
  and the latest file, 2026-03-07 (Partisan Edge, unenrolled and inactive shares, precinct table).
- Voter file aggregates: `model-data/voterfile/aggregates/statewide_turnout_by_town_party.csv` (town × party × election counts; **no names**;
  the voter file itself is private and never leaves `model-data/voterfile/`).
- `geography/regions.csv` (Regions of Maine v1.0).

## Definitions (positive = Democratic unless it is a share or a count)
**Races.** General elections for President, Governor, U.S. Senate, U.S. House. A race qualifies when both major parties had a candidate and
non-major candidates took ≤ 15% of the vote (`races.csv`). Declared write-ins never count as a nominee. RCV races: first-choice votes.
Window: 2022 (Governor, U.S. House) and 2024 (President, U.S. House).

**Margin** of a race in a place = 100 × (D − R) / (D + R). **Cycle value** = ⅔ × mean(statewide races) + ⅓ × U.S. House race (no House race:
the statewide races; only a House race: the House race). Two cycles weighted 0.7 (2024) / 0.3 (2022); a place with one cycle: that cycle.

**Raw vote margin** (`raw_vote_margin`; v4 called this the Partisan EAI) = the cycle values of the race margins, so weighted. What happened in
2022–2024, with those years' political weather in it.

**Relative lean** (`relative_lean`; v4 "Natural Lean") = the same with every race margin replaced by (margin − Maine's margin in that race).
The U.S. House race is measured against its **district's** result, which removes the House candidates' district-wide pull, **and the district's
own lean against Maine in that cycle's statewide races is added back** (`checks/district_lean_addback.csv`: CD 1 +15.0, CD 2 −16.3 in 2024), so
the zero is Maine for every unit (v4 lacked the add-back and gave the two districts different zeros: Windham voted D+5 and read R+9).
A House-only cycle (1992, 1998, 2010) uses the mean of the adjacent cycles' district lean. `statewide_environment` = raw vote − relative lean.

**Maine baseline** (`maine_baseline`, `checks/maine_baseline.txt`) = mean over the last **three** presidential elections (2016, 2020, 2024) of
(Maine's two-party presidential margin − the nation's) = **D+4.8**. The estimate of how Maine votes in a national year that is tied, with the
same two candidates on every ballot; it is the one number a relative measure (Cook PVI, v4's Natural Lean) sets to zero by convention.
Series since 2000: +5.0, +11.7, +10.3, +11.8, +1.0, +4.8, +8.6; sd 4.1; standard error of a three-election mean 2.4. Alternatives:
last two +6.7, last four +6.5, last five +7.3, all seven +7.6. Three elections: the rule, applied mechanically, normally spans two nominees of
each party and stays inside twelve years (the trade-off against drift in the lean is discussed on the Methodology page). Re-estimated after
each presidential election. (2016–2024 all had Trump as the Republican nominee; the mean is what the state did facing him three times.)

**Partisan EAI** (`partisan_eai`) = relative lean + Maine baseline: the expected two-party margin in a neutral national year with average
Maine candidates. Rankings are the relative lean's. **Maine's own Partisan EAI is the baseline, D+4.8** (its relative lean is 0.0 by
construction; the cycle values are within ±0.2 because the House add-back is contest-averaged).

**Partisan Edge** (`partisan_edge`) = 100 × (DEM − REP) / (DEM + REP), **active** voters, the **latest** SOS file (`partisan_edge_snapshot` =
2026-03-07; `dem_active_latest` … `inactive_voters_latest`). `unenrolled_share_pct` = UNE / active and `inactive_share_pct` = inactive /
(active + inactive), same file. The Nov 5, 2024 file is kept as `registration_margin_2024` and `dem_active` … `inactive_voters`
(`registration_2024_snapshot`) because the Hidden Lean compares the 2022–2024 vote with the rolls in force at the vote. Why active: the list
maintenance of 2022 and 2025 moved voters to inactive unevenly; active-only and all-voters margins rank towns at r ≥ 0.987
(`checks/registration_active_vs_all.csv`).

**Hidden Lean** (`hidden_lean`; v4 "Performance Gap", same number) = raw vote margin − expected raw vote margin, expected = −6.37 + 150.96 ×
(active D share) − 116.49 × (active R share), shares of active voters Nov 5, 2024; weighted least squares across the 504 towns, weights = 2024
President two-party votes, weighted R² 0.944, residual sd 6.8 (`checks/hidden_lean_regression.txt`). The same line at every level
(`hidden_lean_expected`). Maine's own value is −0.7 (near zero by construction). It is the part of a place's politics the voter rolls do not
show: unenrolled voters' lean, crossover and differential turnout together; it cannot separate them.

**Turnout 2024** (`turnout_2024_pct`) = voters in the state voter file who cast a ballot in Nov 2024 / active registrants (Nov 2024 file).
Statewide 78.9% (voter-file coverage of official ballots 98%).

**Who voted** (voter file): `voted_YYYY_D/R/U/O` (O = Green + Libertarian), `voted_YYYY`, `voters_YYYY_*_pct` for 2022 and 2024.
**Turnout headroom**: `headroom_votes_YYYY` = (registered Democrats who did not vote) − (registered Republicans who did not vote), registrants as of
the 2026 file; `turnout_headroom_YYYY_pts` = that as a share of the mean two-party vote in the cycle.

**Competitive outlook** (`campaign_class`, `campaign_reading`; rules in `v5_scores.py campaign_class()`): on the Partisan EAI (E), each window
race's margin adjusted the same way (`best_dem_margin_adj` / `worst_dem_margin_adj` = race relative lean + baseline) and the headroom:
`safe_D/R` |E| ≥ 15 and the other side never within 5 adjusted points in a window race; `lean_D/R` 7 ≤ |E| < 15, or ≥ 15 with the other side
within 5; `battleground` |E| < 7. (Until 2026-10-19 the battlegrounds were split into `battleground_turnout`, when in BOTH 2022 and 2024
the trailing side's headroom (points) exceeded that cycle's margin, and `battleground_persuasion`; the turnout rule fired for no town and two
State House districts, so the two were merged — the headroom figures stay in the tables and in the page panel.) Calibration against 227 contested 2022/2024 State House races on the current lines (`checks/CHECKS.txt`): safe 100%
held, lean D 96%, lean R 88%, battlegrounds 46% D (v4's battlegrounds, centred on Maine's result, were 67% D); mean |State House margin −
Partisan EAI| 6.5 points vs 8.0 for the raw vote. Maine itself has no reading.

**Office profile**: `margin_president_2024`, `margin_governor_2022`, `margin_senate_2024/2022` (empty: no qualifying race), `margin_house_2024/2022`,
`office_spread`, `best_dem_margin`, `worst_dem_margin` (raw). **Drift** = `natural_lean_cycle_2024` − `natural_lean_cycle_2018` (relative lean; the
per-cycle columns keep the v4 names `eai_cycle_*` = raw vote and `natural_lean_cycle_*` = relative lean). **Size**: `two_party_votes_2024`,
`size_class`, `cycle_change_sd` (20.5 / 9.6 / 5.4 / 3.7 points for under 100 / 100–300 / 300–1,000 / 1,000+ votes).

**Implied unenrolled lean** (data only): unchanged from v4 (2024 President; partisans who voted assumed loyal at 93%, range 90–97%).

**Ranks**: `partisan_eai`, `raw_vote_margin`, `partisan_edge`, `hidden_lean` `_rank_most_D` / `_most_R` (method min; `units_in_ranking`); towns
and commissioner districts also `_rank_in_county_most_D`. `n_cycles`, `n_races`, `races_in_window`, `shared_results_line`.

## Files
| File | Rows | Keys / notes |
|---|---|---|
| `scores_towns.csv` | 504 | `unit_id`; registration units with a Nov 2024 registration line and a window race |
| `scores_counties.csv` | 16 | `county` (abbr), `county_name` |
| `scores_regions.csv` | 12 | `region_id`, `region` |
| `scores_statewide.csv` | 1 | `state` = ME; Partisan EAI = the baseline; no competitive outlook |
| `scores_congressional_districts.csv` | 2 | `congressional_district`; + `towns`, `n_split_towns` |
| `scores_state_senate_districts.csv` | 35 | `senate_district` |
| `scores_state_house_districts.csv` | 151 | `house_district` |
| `scores_county_commissioner_districts.csv` | 60 | `county`, `commissioner_district` |
| `scores_precincts.csv` | 194 | `unit_id`, `ward_precinct`: the latest file's **active** registration by precinct (towns with ≥ 2 precincts) and its Partisan Edge |
| `scores_history_towns.csv` | 9,114 | `unit_id` × `year` 1990–2024: `raw_vote_cycle`, `relative_lean_cycle`, `maine_baseline` (the three presidential elections up to that year), `partisan_eai_cycle`, `registration_margin_cycle` (Nov file; 2008+ active + inactive, before 2007 "registered"), `hidden_lean_cycle` (line fitted to that year's towns, `checks/history_gap_coefficients.csv`), `*_rolling_70_30` (2024 = the tile), `two_party_votes_mean`, `registration_snapshot`, `registration_basis` |
| `scores_history_counties.csv` | 288 | `county` × `year` |
| `scores_history_cd_state.csv` | 54 | `unit` = ME, CD1, CD2 (towns on the **current** CD lines in every year) × `year` |
| `races.csv` | 83 | every top-ticket general race 1990–2024: votes, non-major share, qualifies, reason |
| `forecast_2026-11-03/` | | the pre-registered Governor forecast (first freeze 2026-10-17 on v4's relative lean; refreeze by Oct 30 on v5's) |
| `checks/` | | `CHECKS.txt`, `maine_baseline.txt/.csv`, `district_lean_addback.csv`, `state_house_vs_thresholds.csv`, `registration_active_vs_all.csv`, `relative_lean_nonoverlapping.csv`, `rule15_edges.csv`, `eai_weighting_grid.csv`, `hidden_lean_regression.txt`, `history_gap_coefficients.csv` |
| `scripts/` | | `v5_prep.py`, `v5_scores.py`, `v5_checks.py`, `v5_forecast.py`, `scoring.py` (race table, unit→results-line matching; from v3.1, unchanged), `president_maine_1980_2024.csv` |

Districts: towns split between districts are divided by their precincts' registration: votes and the Nov 2024 registration by the Nov 2024
precinct file (D vote by the precinct share of DEM + ½ UNE + ½ minor, R vote by REP + ½ UNE + ½ minor, each registration group by its own share);
the latest registration by the latest precinct file's shares.

## Statewide
Partisan EAI D+4.8 (= the baseline); raw vote D+10.1 (cycle 2022 D+14.1, 2024 D+8.3); Partisan Edge D+5.5 (2026-03-07; D+7.0 on the Nov 2024
file), 31.4% unenrolled, 13.1% inactive; Hidden Lean −0.7; turnout 2024 78.9%; electorate Nov 2024 D 34.6 / R 31.1 / U 30.7 / other 3.6.
Towns: safe R 288, lean R 65, battleground 51, lean D 25, safe D 75. Site colors (2026-10-19): safe D dark blue, lean D light blue, battleground gold, lean R light red, safe R dark red.

## How to rebuild
```
cd scripts
SCORES_RES=<results v3.14 unzipped> python3 v5_prep.py
SCORES_REG=<registration v7.2 out/> SCORES_RES=<results> SCORES_VF=<voterfile aggregates csv> SCORES_REGIONS=<geography/regions.csv> SCORES_OUT=<out> python3 v5_scores.py
SCORES_REG=... SCORES_RES=... SCORES_OUT=<out> python3 v5_checks.py
```
Deterministic; about a minute. A new registration file: the Partisan Edge picks up the latest snapshot automatically. After 2028: add the
FEC totals to `US_PRES`, re-run. Then `site-design/versions.json` "scores" and `python3 site-design/rebuild_all.py ...`.

## Validation (details in `checks/` and on the Methodology page)
- State House 2022/2024 (227 races): margin vs Partisan EAI r 0.954; mean |margin − Partisan EAI| 6.5 (raw vote 8.0); classes as above.
- Relative lean 2010–16 vs 2018–24 (towns 1,000+): r 0.918, rank r 0.909, 13/199 moved > 50 ranks, mean |change| 9.1.
- v4 Natural Lean vs v5 relative lean: r 0.990; the district add-back moves CD 1 towns +5.0 and CD 2 towns −5.4 (the House third of the
  district leans), nothing else changes.
- Weighting grid (audit b5), active vs all registration, 15% rule edges: unchanged from v4.

## Parking list (not done; revisit once, after the Nov 2026 results are scored)
Threshold or wording changes to the competitive outlook; the baseline window (three elections) and the national anchor; a third cycle
(60/30/10); a town-level survey of unenrolled voters; a permanent name for Hidden Lean. See FLAGS.md.
