Skip to main content

Anomalies

Playoff whistles, style changes, rare combinations, and outliers, all found by code rather than hand-picked

Who loses the whistle in the playoffs?

The cliché says referees “swallow their whistles” in the postseason. For every player with 3+ qualifying-season playoff runs (and 300+ playoff field-goal attempts), we compare shooting-foul free throws per shot in the playoffs with the same seasons’ regular seasons, net of the league-wide change that year.

Show code
pw_tbl <- function(d) d[, .(Player = player, `Playoff runs` = po_runs, `Playoff FGA` = po_fga,
                            `RS FTA/FGA` = rs_ftr, `PO FTA/FGA` = po_ftr, `Net change` = net_change, `% change` = pct_change / 100)] |>
  small_gt() |> fmt_number(c(`RS FTA/FGA`, `PO FTA/FGA`), decimals = 3) |>
  fmt_number(`Net change`, decimals = 3, force_sign = TRUE) |> fmt_percent(`% change`, decimals = 0, force_sign = TRUE) |>
  fmt_number(`Playoff FGA`, decimals = 0)
Show code
pw_tbl(pw[order(net_change)][1:10])
Player Playoff runs Playoff FGA RS FTA/FGA PO FTA/FGA Net change % change
Metta World Peace 5 683 0.276 0.190 −0.103 −37%
Arvydas Sabonis 5 374 0.308 0.219 −0.092 −30%
Allen Iverson 8 1,879 0.291 0.212 −0.090 −31%
Patrick Ewing 3 472 0.333 0.250 −0.088 −26%
Jimmy Butler 9 1,835 0.441 0.365 −0.081 −18%
Bam Adebayo 5 739 0.318 0.238 −0.075 −24%
Karl Malone 7 1,530 0.364 0.301 −0.069 −19%
Enes Freedom 4 332 0.274 0.211 −0.069 −25%
Jerry Stackhouse 7 822 0.270 0.212 −0.068 −25%
Stephon Marbury 4 354 0.235 0.184 −0.064 −27%
Show code
pw_tbl(pw[order(-net_change)][1:10])
Player Playoff runs Playoff FGA RS FTA/FGA PO FTA/FGA Net change % change
Anfernee Hardaway 3 312 0.258 0.397 +0.131 +51%
Tim Thomas 6 318 0.221 0.314 +0.078 +35%
Ben Gordon 4 461 0.179 0.265 +0.072 +40%
Bonzi Wells 7 434 0.232 0.304 +0.060 +26%
Corliss Williamson 6 394 0.285 0.348 +0.052 +18%
Paul George 10 1,846 0.210 0.263 +0.050 +24%
Kirk Hinrich 3 310 0.154 0.213 +0.049 +32%
Paul Millsap 8 925 0.289 0.341 +0.048 +17%
Amar'e Stoudemire 7 918 0.442 0.495 +0.047 +11%
Dillon Brooks 4 322 0.140 0.180 +0.046 +33%

Metta World Peace saw the steepest playoff drop: shooting-foul free throws per shot fell 37% relative to the league trend over 5 runs. Anfernee Hardaway went the other way (+51%).

Biggest whistle drop after the 2021-22 rule change

Players with 2+ qualifying seasons both before (2018-21) and after (2021-26) the “non-basketball move” crackdown, ranked by change in Whistle Score. A negative change means a cleaner, less whistle-reliant scorer after the rule.

Show code
prd[1:12, .(Player = player, `Whistle before` = whistle_pre, `Whistle after` = whistle_post, Change = whistle_change,
            `3PT fouls/100 before` = threefoul_pre, `3PT fouls/100 after` = threefoul_post)] |>
  small_gt() |> fmt_number(c(`Whistle before`, `Whistle after`, Change), decimals = 2, force_sign = TRUE) |>
  fmt_number(c(`3PT fouls/100 before`, `3PT fouls/100 after`), decimals = 2)
Player Whistle before Whistle after Change 3PT fouls/100 before 3PT fouls/100 after
Spencer Dinwiddie +2.79 +1.59 −1.20 4.45 1.48
De'Aaron Fox +1.31 +0.15 −1.16 1.31 0.91
Trae Young +1.99 +0.93 −1.06 5.18 2.42
Rui Hachimura +0.11 −0.79 −0.90 0.00 0.24
Jordan Poole +1.23 +0.38 −0.86 4.62 2.09
Marvin Bagley III +0.33 −0.47 −0.79 0.00 0.00
Brandon Ingram +1.37 +0.64 −0.72 3.38 1.74
Anthony Davis +0.80 +0.11 −0.69 2.33 0.84
Terrence Ross +1.66 +1.06 −0.60 6.52 3.27
Reggie Jackson −0.70 −1.28 −0.57 0.53 0.59
Anfernee Simons −0.18 −0.69 −0.51 0.76 1.08
Bradley Beal +0.32 −0.18 −0.50 2.08 1.28

Spencer Dinwiddie shows the largest drop in Whistle Score (-1.20 SD). Among the heaviest pre-rule three-point foul-drawers (top quartile), the steepest decline belonged to Terrence Ross, from 6.52 to 3.27 three-point fouls per 100 attempts. The single heaviest pre-rule drawer, James Harden, actually rose from 7.61 to 7.96. These are descriptive changes; the Rule Change page tests whether they are larger than the drift we’d expect without a rule.

Archetype switchers

Among players with 6+ qualifying seasons: how far did they travel across the map between their first three and last three qualifying seasons, and how often did their season-to-season archetype flip?

Show code
sw[order(-shift)][1:10, .(Player = player, Seasons = seasons, `First archetype` = first, `Last archetype` = last,
                         `Shift (SD)` = shift, `Season-to-season switches` = switches)] |>
  small_gt() |> fmt_number(`Shift (SD)`, decimals = 2)
Player Seasons First archetype Last archetype Shift (SD) Season-to-season switches
Dirk Nowitzki 20 Downhill Bully Ethical Hooper 3.52 2
Norman Powell 10 Downhill Bully Whistle Artist 3.02 3
DeMar DeRozan 16 Downhill Bully Whistle Artist 2.67 3
Terrence Ross 10 Grinder Ethical Hooper 2.64 6
Damian Lillard 13 Ethical Hooper Whistle Artist 2.58 2
Carmelo Anthony 18 Grinder Whistle Artist 2.39 8
Kevin Durant 17 Grinder Whistle Artist 2.21 4
Jerry Stackhouse 11 Downhill Bully Downhill Bully 2.01 2
Allan Houston 8 Ethical Hooper Whistle Artist 1.99 3
Anthony Edwards 6 Grinder Whistle Artist 1.97 1
Show code
sw[order(-switches, -seasons)][1:10, .(Player = player, Seasons = seasons, `Season-to-season switches` = switches,
                                      `First archetype` = first, `Last archetype` = last)] |> small_gt()
Player Seasons Season-to-season switches First archetype Last archetype
LeBron James 23 12 Grinder Whistle Artist
Rudy Gay 16 12 Grinder Downhill Bully
Vince Carter 19 11 Downhill Bully Grinder
Shaquille O'Neal 13 10 Whistle Artist Downhill Bully
Paul Pierce 17 9 Grinder Downhill Bully
LaMarcus Aldridge 15 9 Ethical Hooper Whistle Artist
Carmelo Anthony 18 8 Grinder Whistle Artist
Allen Iverson 13 8 Downhill Bully Downhill Bully
Brook Lopez 12 8 Grinder Grinder
John Wall 10 8 Downhill Bully Grinder

Dirk Nowitzki made the longest journey: from Downhill Bully early to Ethical Hooper late in the career, a shift of 3.52 standard deviations.

Ethical despite the volume

High-usage scorers usually draw more fouls, because the ball is in their hands more often. These seasons combine top-10% usage (scoring attempts per 36 minutes, within season) with EHI ≥ 65.

Show code
ev[1:15, .(Season = season, Player = player, EHI = ehi, `Usage (scoring att./36)` = usage36, Skill = skill, Whistle = whistle)] |>
  small_gt() |> fmt_number(c(Skill, Whistle), decimals = 2, force_sign = TRUE) |> fmt_number(EHI, decimals = 1)
Season Player EHI Usage (scoring att./36) Skill Whistle
2018-19 D'Angelo Russell 88.0 27.3 +1.52 −2.00
2013-14 Al Jefferson 82.2 22.8 +2.26 −0.95
2015-16 Stephen Curry 82.1 26.9 +2.85 −0.79
2019-20 Derrick Rose 80.4 26.0 +1.96 −0.94
2025-26 LaMelo Ball 79.8 27.2 +0.51 −1.79
1997-98 Glenn Robinson 76.9 22.8 +2.09 −0.77
1997-98 Rik Smits 76.3 22.1 +1.32 −1.24
2021-22 Nikola Jokić 73.6 26.1 +2.15 −0.47
2008-09 Tony Parker 73.5 23.6 +1.41 −1.03
2024-25 Cade Cunningham 73.4 28.3 +1.27 −0.87
2014-15 Stephen Curry 73.1 23.8 +2.41 −0.27
2008-09 Al Jefferson 73.0 23.0 +1.72 −0.78
2020-21 Zach LaVine 72.9 25.8 +0.91 −1.07
2022-23 LaMelo Ball 72.6 25.6 +0.07 −1.60
2013-14 Stephen Curry 71.9 23.0 +2.81 +0.21

Only 55 player-seasons in thirty years clear both bars.

Statistical outliers

Any qualifying season where a component sits more than 3 SD from its season mean (component z-scores are capped at ±4 in the index). Each was checked for data bugs before being kept.

Show code
ol[, .N, component][, .(Component = COMP_LABELS[component], `Seasons with |z| > 3` = N)][order(-`Seasons with |z| > 3`)] |> small_gt()
Component Seasons with |z| > 3
3PT shooting-foul rate 82
Perimeter and-one rate 63
Clean footwork (travels + offensive fouls, reversed) 46
Shot difficulty 26
Excess free-throw rate 21
Free-throw share of points 14
Shot-making above expected 10
Show code
reactable(ol[, .(Season = season, Player = player, Component = COMP_LABELS[component], z, `Raw value` = raw,
                 `After shrinkage` = shrunk, FGA = fga)],
          searchable = TRUE, defaultPageSize = 10, theme = rt_theme, compact = TRUE, striped = TRUE)

Checked, and explained:

  • An early version of the shrinkage produced |z| > 8 for a handful of seasons. Tracing it showed that tiny samples (e.g. a big man with a couple of three-shot fouls on a handful of three-point attempts) were inflating the estimated spread of true talent. The priors are now fit only on players with reliable samples. The remaining outliers are large-sample seasons, genuine extremes rather than noise.
  • Very low shot difficulty belongs to lob-and-dunk centers whose attempts are almost all at the rim. That is a real shot diet, not an error.
  • High three-point foul rates belong to famously effective three-point foul-drawers.

Team effects (exploratory)

Do some franchises make players more or less “ethical”? A regression of EHI on player fixed effects + franchise fixed effects asks how a player’s EHI shifts when on one franchise versus elsewhere in their career. Relocated franchises are merged (e.g. SEA → OKC).

Show code
te_tbl <- function(d) d[, .(Franchise = franchise, `EHI shift vs. own career` = effect, `Player-seasons` = player_seasons)] |>
  small_gt() |> fmt_number(2, decimals = 1, force_sign = TRUE)
Show code
te_tbl(te[order(-effect)][1:6])
Franchise EHI shift vs. own career Player-seasons
WAS +3.7 143
HOU +2.2 132
LAC +1.8 133
PHO +1.5 146
LAL +1.4 129
CHI +1.3 140
Show code
te_tbl(te[order(effect)][1:6])
Franchise EHI shift vs. own career Player-seasons
CLE −5.4 123
ORL −2.9 153
CHO −2.6 94
BRK −2.4 140
DEN −1.9 150
DET −1.7 138

The spread is modest. The largest franchise effect (+5.4 EHI points) is smaller than the 9.6-point gap between a median and a top-quartile qualifying season, and coaching, roster construction and officiating aren’t separated. Treat this as a conversation starter, not a finding.