Producer: opponent_tiers.py (2026-09-04). 5v5, 2011-12 → 2025-26. Every constant-lineup segment credits each skater with seconds, xGF and xGA keyed by the mean PRIOR-season rating of the five opponents (EV defence for def, EV offence for off; dpair = the opposing defencemen's EV defence only). Tiers are season TOI-weighted quartiles: Q1 weakest opposition, Q4 strongest.
1. League gradient
| key | tier | opp quality (NG/82) | TOI share | xGF/60 | xGA/60 |
| def | Q1 | -1.04 | 26% | 2.583 | 2.458 |
| def | Q2 | -0.24 | 25% | 2.428 | 2.360 |
| def | Q3 | +0.27 | 25% | 2.313 | 2.338 |
| def | Q4 | +0.97 | 24% | 2.158 | 2.339 |
| dpair | Q1 | -1.33 | 26% | 2.531 | 2.394 |
| dpair | Q2 | -0.31 | 26% | 2.421 | 2.376 |
| dpair | Q3 | +0.36 | 24% | 2.337 | 2.362 |
| dpair | Q4 | +1.28 | 24% | 2.198 | 2.368 |
| off | Q1 | -0.95 | 26% | 2.322 | 2.039 |
| off | Q2 | -0.17 | 25% | 2.376 | 2.253 |
| off | Q3 | +0.45 | 24% | 2.391 | 2.465 |
| off | Q4 | +1.43 | 24% | 2.416 | 2.772 |
2. Is beating good defenders a skill? Year-over-year persistence
Player-seasons need ≥60 min in BOTH Q1 and Q4. slope_xgf = own xGF/60 vs Q4 − vs Q1 (offence against tough defence); slope_xga = own xGA/60 vs Q4 − vs Q1 (defence against tough offence). The _all rows are the ordinary season rates for comparison.
| key | pos | stat | n pairs | r (yoy) | SD |
| def | F | slope_xgf | 4410 | +0.006 | 0.454 |
| def | F | slope_xga | 4410 | +0.053 | 0.457 |
| def | F | slope_net | 4410 | +0.047 | 0.662 |
| def | F | xgf60_all | 4410 | +0.663 | 0.376 |
| def | F | xga60_all | 4410 | +0.529 | 0.301 |
| def | F | net60_all | 4410 | +0.533 | 0.435 |
| def | D | slope_xgf | 2513 | +0.027 | 0.410 |
| def | D | slope_xga | 2513 | +0.048 | 0.412 |
| def | D | slope_net | 2513 | +0.038 | 0.596 |
| def | D | xgf60_all | 2513 | +0.566 | 0.302 |
| def | D | xga60_all | 2513 | +0.546 | 0.285 |
| def | D | net60_all | 2513 | +0.468 | 0.384 |
| def | all | slope_xgf | 6923 | +0.014 | 0.437 |
| def | all | slope_xga | 6923 | +0.051 | 0.439 |
| def | all | slope_net | 6923 | +0.044 | 0.636 |
| def | all | xgf60_all | 6923 | +0.634 | 0.349 |
| def | all | xga60_all | 6923 | +0.536 | 0.294 |
| def | all | net60_all | 6923 | +0.511 | 0.415 |
| off | F | slope_xgf | 4601 | +0.044 | 0.459 |
| off | F | slope_xga | 4601 | +0.044 | 0.467 |
| off | F | slope_net | 4601 | +0.049 | 0.672 |
| off | F | xgf60_all | 4601 | +0.657 | 0.375 |
| off | F | xga60_all | 4601 | +0.526 | 0.303 |
| off | F | net60_all | 4601 | +0.529 | 0.436 |
| off | D | slope_xgf | 2533 | +0.083 | 0.428 |
| off | D | slope_xga | 2533 | +0.065 | 0.439 |
| off | D | slope_net | 2533 | +0.086 | 0.624 |
| off | D | xgf60_all | 2533 | +0.559 | 0.301 |
| off | D | xga60_all | 2533 | +0.545 | 0.286 |
| off | D | net60_all | 2533 | +0.461 | 0.384 |
| off | all | slope_xgf | 7134 | +0.062 | 0.448 |
| off | all | slope_xga | 7134 | +0.052 | 0.456 |
| off | all | slope_net | 7134 | +0.063 | 0.653 |
| off | all | xgf60_all | 7134 | +0.629 | 0.348 |
| off | all | xga60_all | 7134 | +0.533 | 0.296 |
| off | all | net60_all | 7134 | +0.507 | 0.416 |
| dpair | F | slope_xgf | 4620 | +0.003 | 0.460 |
| dpair | F | slope_xga | 4620 | +0.007 | 0.455 |
| dpair | F | slope_net | 4620 | +0.020 | 0.672 |
| dpair | F | xgf60_all | 4620 | +0.665 | 0.379 |
| dpair | F | xga60_all | 4620 | +0.529 | 0.303 |
| dpair | F | net60_all | 4620 | +0.535 | 0.437 |
| dpair | D | slope_xgf | 2594 | +0.025 | 0.413 |
| dpair | D | slope_xga | 2594 | -0.000 | 0.404 |
| dpair | D | slope_net | 2594 | +0.029 | 0.601 |
| dpair | D | xgf60_all | 2594 | +0.567 | 0.303 |
| dpair | D | xga60_all | 2594 | +0.546 | 0.286 |
| dpair | D | net60_all | 2594 | +0.469 | 0.385 |
| dpair | all | slope_xgf | 7214 | +0.011 | 0.441 |
| dpair | all | slope_xga | 7214 | +0.005 | 0.436 |
| dpair | all | slope_net | 7214 | +0.023 | 0.644 |
| dpair | all | xgf60_all | 7214 | +0.637 | 0.351 |
| dpair | all | xga60_all | 7214 | +0.536 | 0.296 |
| dpair | all | net60_all | 7214 | +0.513 | 0.417 |
Career split-half (odd vs even seasons, ≥3 qualifying seasons on each side)
| key | pos | stat | players | r |
| def | F | slope_xgf | 417 | +0.089 |
| def | F | slope_net | 417 | +0.111 |
| def | F | xgf60_all | 417 | +0.883 |
| off | D | slope_xga | 230 | +0.245 |
| off | D | slope_net | 230 | +0.262 |
| off | D | xga60_all | 230 | +0.719 |
| dpair | F | slope_xgf | 434 | +0.015 |
3. Leaderboards (shrunk toward league mean by the single-season persistence; ≥300 min in the thinner tier)
With r(yoy) ≈ 0.01–0.07 the shrinkage constant is enormous and every shrunk value collapses onto the league mean: the raw slope column is what a season-by-season fan would quote, and the shrunk column is what the evidence supports. The leaderboards are kept to make that point.
Forwards: xGF/60 vs Q4 defenders minus vs Q1 (top = holds up best; bottom = feasts on weak)
| Player | seasons | tier min | slope | shrunk |
| Leon Draisaitl | 12 | 2,962 | -0.049 | -0.312 |
| Adam Lowry | 12 | 2,256 | +0.020 | -0.315 |
| Matty Beniers | 4 | 1,095 | +0.196 | -0.335 |
| Kyle Okposo | 13 | 2,661 | -0.131 | -0.338 |
| Charlie Coyle | 14 | 2,847 | -0.159 | -0.342 |
| Blake Wheeler | 12 | 2,901 | -0.168 | -0.343 |
| Brandon Tanev | 10 | 1,474 | -0.023 | -0.347 |
| Jordan Eberle | 14 | 3,110 | -0.198 | -0.348 |
| David Perron | 15 | 2,942 | -0.204 | -0.352 |
| Eric Staal | 11 | 2,375 | -0.170 | -0.352 |
| Anthony Mantha | 9 | 1,754 | -0.113 | -0.353 |
| Nicolas Deslauriers | 9 | 1,143 | +0.011 | -0.354 |
| Jean-Gabriel Pageau | 12 | 2,328 | -0.175 | -0.354 |
| Frans Nielsen | 9 | 1,755 | -0.131 | -0.356 |
| Sidney Crosby | 14 | 3,309 | -0.243 | -0.358 |
| Mikko Rantanen | 10 | 2,426 | -0.203 | -0.358 |
| Nick Cousins | 10 | 1,752 | -0.143 | -0.358 |
| Nikolay Kulemin | 6 | 1,185 | -0.041 | -0.359 |
| Cal Clutterbuck | 13 | 1,979 | -0.171 | -0.359 |
| Tomas Plekanec | 7 | 1,544 | -0.120 | -0.359 |
| Alex Galchenyuk | 9 | 1,582 | -0.136 | -0.361 |
| Corey Perry | 14 | 2,705 | -0.229 | -0.361 |
| Gustav Nyquist | 12 | 2,517 | -0.221 | -0.361 |
| Anders Lee | 13 | 2,698 | -0.232 | -0.362 |
| Craig Smith | 14 | 2,652 | -0.230 | -0.362 |
| Robert Thomas | 7 | 1,522 | -0.948 | -0.483 |
| James van Riemsdyk | 15 | 2,872 | -0.668 | -0.468 |
| Zack Kassian | 11 | 1,650 | -0.799 | -0.465 |
| Jamie Benn | 15 | 3,489 | -0.600 | -0.459 |
| Brayden Schenn | 15 | 3,282 | -0.607 | -0.458 |
| Trevor Zegras | 4 | 983 | -0.948 | -0.457 |
| Alex Killorn | 14 | 2,732 | -0.634 | -0.457 |
| Lucas Raymond | 5 | 1,214 | -0.854 | -0.457 |
| Sebastian Aho | 10 | 2,057 | -0.684 | -0.456 |
| Trevor Moore | 7 | 1,203 | -0.843 | -0.456 |
| Ivan Barbashev | 9 | 1,880 | -0.704 | -0.455 |
| Pavel Buchnevich | 10 | 1,946 | -0.694 | -0.455 |
| Garnet Hathaway | 9 | 1,253 | -0.792 | -0.451 |
| Aleksander Barkov | 12 | 2,420 | -0.626 | -0.451 |
| Jason Pominville | 8 | 1,800 | -0.686 | -0.451 |
| Cam Atkinson | 11 | 2,129 | -0.648 | -0.450 |
| Andrei Svechnikov | 8 | 1,506 | -0.718 | -0.448 |
| Calle Jarnkrok | 11 | 2,074 | -0.638 | -0.447 |
| Travis Konecny | 10 | 2,111 | -0.633 | -0.447 |
| Tyler Bozak | 10 | 1,880 | -0.651 | -0.446 |
| Ryan Kesler | 7 | 1,631 | -0.678 | -0.446 |
| Timo Meier | 10 | 2,081 | -0.625 | -0.445 |
| Nick Bjugstad | 12 | 2,171 | -0.616 | -0.445 |
| Brad Boyes | 5 | 858 | -0.864 | -0.443 |
| Mika Zibanejad | 14 | 2,850 | -0.569 | -0.443 |
Defencemen: xGA/60 vs Q4 offence minus vs Q1 (top = most negative = best vs elite)
| Player | seasons | tier min | slope | shrunk |
| Ryan Ellis | 9 | 1,871 | +0.234 | +0.550 |
| TJ Brodie | 14 | 3,620 | +0.404 | +0.559 |
| Mark Giordano | 13 | 3,101 | +0.379 | +0.560 |
| Torey Krug | 11 | 2,571 | +0.417 | +0.594 |
| Aaron Ekblad | 12 | 2,826 | +0.447 | +0.601 |
| Jon Merrill | 12 | 2,031 | +0.390 | +0.602 |
| Justin Schultz | 12 | 2,601 | +0.439 | +0.603 |
| Brady Skjei | 10 | 2,956 | +0.466 | +0.607 |
| Shea Theodore | 10 | 2,260 | +0.430 | +0.610 |
| Jonathan Ericsson | 8 | 1,684 | +0.374 | +0.611 |
| Marc Methot | 7 | 1,615 | +0.366 | +0.612 |
| Hampus Lindholm | 12 | 3,183 | +0.519 | +0.628 |
| Brent Seabrook | 9 | 2,393 | +0.486 | +0.630 |
| Erik Karlsson | 15 | 4,613 | +0.556 | +0.630 |
| Alexei Emelin | 7 | 1,594 | +0.419 | +0.631 |
| Brent Burns | 15 | 4,252 | +0.563 | +0.638 |
| Haydn Fleury | 8 | 882 | +0.278 | +0.638 |
| Colin Miller | 10 | 1,634 | +0.449 | +0.640 |
| Dmitry Orlov | 13 | 3,758 | +0.561 | +0.643 |
| Jay Bouwmeester | 9 | 2,493 | +0.525 | +0.645 |
| Justin Holl | 6 | 1,231 | +0.410 | +0.647 |
| Nick Jensen | 10 | 2,532 | +0.532 | +0.647 |
| Calvin de Haan | 12 | 2,357 | +0.524 | +0.647 |
| Brandon Davidson | 3 | 444 | +0.014 | +0.650 |
| Johnny Oduya | 7 | 1,745 | +0.492 | +0.651 |
| Nikita Zadorov | 12 | 2,816 | +1.096 | +0.911 |
| Braden Schneider | 5 | 1,255 | +1.261 | +0.892 |
| Jani Hakanpää | 4 | 887 | +1.339 | +0.876 |
| Vladislav Gavrikov | 7 | 2,112 | +1.051 | +0.868 |
| Jackson LaCombe | 3 | 887 | +1.298 | +0.866 |
| Drew Helleson | 2 | 388 | +1.799 | +0.860 |
| Marcus Pettersson | 8 | 2,248 | +1.019 | +0.859 |
| Pavel Mintyukov | 3 | 654 | +1.404 | +0.858 |
| Jan Rutta | 8 | 1,426 | +1.096 | +0.854 |
| Patrick Wiercioch | 5 | 762 | +1.287 | +0.850 |
| Matt Bartkowski | 4 | 768 | +1.281 | +0.850 |
| Nicolas Hague | 6 | 1,305 | +1.102 | +0.849 |
| Mark Stuart | 6 | 1,055 | +1.156 | +0.848 |
| Neal Pionk | 9 | 2,308 | +0.987 | +0.847 |
| Nikita Zaitsev | 8 | 1,696 | +1.035 | +0.846 |
| Tyson Barrie | 12 | 2,789 | +0.958 | +0.844 |
| Adam Boqvist | 5 | 617 | +1.321 | +0.839 |
| Alexandre Carrier | 6 | 1,329 | +1.059 | +0.837 |
| Gustav Lindstrom | 3 | 407 | +1.560 | +0.837 |
| Noah Hanifin | 11 | 3,011 | +0.934 | +0.837 |
| Erik Brannstrom | 6 | 842 | +1.185 | +0.837 |
| Henri Jokiharju | 8 | 1,734 | +1.004 | +0.836 |
| Rasmus Dahlin | 8 | 2,476 | +0.954 | +0.836 |
| Jakob Chychrun | 10 | 2,446 | +0.950 | +0.834 |
| Bowen Byram | 6 | 1,375 | +1.040 | +0.834 |
Caveats
- Opponent quality is the prior season's rating (rookies = 0), so the tiering is independent of the shots being counted.
- Coaches match lines: a first-liner's Q4 minutes come against the other team's best, and his Q1 minutes are often garbage time or blowouts. The slope is a within-player contrast, so that selection is the same for everyone, but score effects are not removed here.
- xG only — finishing above expected is not in these numbers.