Skip to main content

Rankings

Every qualifying career and player-season, 1996-97 to 2025-26

A career qualifies with four or more qualifying regular seasons (1,000+ minutes and 12+ FGA per 36). Career EHI is the minutes-weighted average of those seasons; Peak is the best three-consecutive-season stretch. Skill and Whistle are in standard deviations versus season peers. For Whistle, negative is cleaner.

The 25 most ethical hoopers

Show code
gt_career <- function(d, title) {
  d |> gt() |>
    tab_header(title = title) |>
    fmt_number(c(EHI, `Peak 3-yr`), decimals = 1) |>
    fmt_number(c(Skill, Whistle), decimals = 2, force_sign = TRUE) |>
    fmt_number(Minutes, decimals = 0) |>
    data_color(columns = EHI, fn = scales::col_numeric(c("#f2a6a5", "#f0efec", "#86b6ef"), domain = c(0, 100))) |>
    cols_hide(Minutes) |>
    tab_options(table.width = gt::pct(100), data_row.padding = px(4), table.font.size = px(14))
}
gt_career(car_tbl[1:25], "All-time top 25 by career EHI")
All-time top 25 by career EHI
Rank Player Seasons Span EHI Peak 3-yr Skill Whistle Archetype
1 Steve Nash 8 1997-98 to 2009-10 87.7 93.6 +2.76 −1.17 Ethical Hooper
2 Payton Pritchard 4 2021-22 to 2025-26 79.3 80.6 +1.50 −1.16 Ethical Hooper
3 Ish Smith 6 2015-16 to 2021-22 75.8 80.4 +1.05 −1.35 Ethical Hooper
4 Nikola Vučević 15 2011-12 to 2025-26 75.8 82.3 +0.25 −1.83 Ethical Hooper
5 Chris Paul 17 2005-06 to 2022-23 75.3 86.7 +2.46 −0.37 Ethical Hooper
6 Gary Payton 8 1996-97 to 2003-04 75.1 77.4 +0.72 −1.49 Ethical Hooper
7 Jrue Holiday 14 2010-11 to 2025-26 74.0 81.7 +1.05 −1.17 Ethical Hooper
8 Buddy Hield 9 2016-17 to 2024-25 72.4 78.7 +0.38 −1.47 Ethical Hooper
9 Rik Smits 4 1996-97 to 1999-00 71.9 77.3 +1.37 −0.84 Ethical Hooper
10 Mookie Blaylock 5 1996-97 to 2000-01 71.6 74.2 +0.58 −1.33 Ethical Hooper
11 Nikola Jokić 11 2015-16 to 2025-26 71.5 74.5 +1.93 −0.34 Ethical Hooper
12 Al Jefferson 12 2004-05 to 2015-16 71.4 82.7 +1.64 −0.64 Ethical Hooper
13 Joe Johnson 14 2002-03 to 2016-17 71.2 78.2 +1.07 −0.97 Ethical Hooper
14 Terrell Brandon 5 1996-97 to 2000-01 71.2 72.3 +1.37 −0.78 Ethical Hooper
15 Bobby Portis 11 2015-16 to 2025-26 70.9 83.3 +0.04 −1.55 Ethical Hooper
16 CJ McCollum 11 2015-16 to 2025-26 70.9 76.2 +1.24 −0.79 Ethical Hooper
17 Tyus Jones 5 2019-20 to 2023-24 70.2 72.7 +1.03 −0.85 Ethical Hooper
18 Mo Williams 10 2005-06 to 2014-15 70.1 78.3 +1.27 −0.77 Ethical Hooper
19 Chucky Atkins 4 1999-00 to 2006-07 69.6 74.4 +0.43 −1.26 Ethical Hooper
20 Eddie House 7 2001-02 to 2009-10 69.6 74.3 +0.30 −1.35 Ethical Hooper
21 Malcolm Brogdon 7 2017-18 to 2023-24 69.5 73.4 +0.57 −1.11 Ethical Hooper
22 E'Twaun Moore 4 2012-13 to 2019-20 69.4 71.8 +0.52 −1.14 Ethical Hooper
23 Antoine Walker 11 1996-97 to 2006-07 69.2 72.7 −0.78 −2.03 Grinder
24 Klay Thompson 12 2011-12 to 2025-26 69.2 77.4 +0.46 −1.21 Ethical Hooper
25 Tony Parker 17 2002-03 to 2018-19 68.9 77.3 +1.28 −0.66 Ethical Hooper

The 25 most whistle-dependent

Show code
gt_career(car_tbl[order(EHI)][1:25], "All-time bottom 25 by career EHI")
All-time bottom 25 by career EHI
Rank Player Seasons Span EHI Peak 3-yr Skill Whistle Archetype
417 James Harden 13 2012-13 to 2025-26 10.7 17.5 +0.65 +3.60 Whistle Artist
416 Dwight Howard 5 2008-09 to 2017-18 11.4 14.5 −1.65 +2.09 Downhill Bully
415 Corey Maggette 11 1999-00 to 2011-12 13.8 22.7 −0.81 +2.35 Downhill Bully
414 Devin Harris 4 2007-08 to 2010-11 15.0 14.4 −0.88 +2.31 Downhill Bully
413 Jimmy Butler 12 2014-15 to 2025-26 15.8 21.8 +0.18 +2.76 Whistle Artist
412 Kevin Martin 10 2006-07 to 2015-16 20.6 38.3 −0.51 +2.06 Downhill Bully
411 Jerami Grant 7 2019-20 to 2025-26 21.1 29.9 −0.73 +1.65 Downhill Bully
410 Bennedict Mathurin 4 2022-23 to 2025-26 21.1 27.4 −0.88 +1.52 Downhill Bully
409 David Robinson 4 1997-98 to 2000-01 22.5 26.9 −0.41 +1.97 Downhill Bully
408 Reggie Miller 6 1996-97 to 2004-05 23.2 26.2 +0.60 +2.53 Whistle Artist
407 Spencer Dinwiddie 5 2017-18 to 2022-23 23.3 26.3 +0.04 +2.11 Whistle Artist
406 Shawn Kemp 5 1996-97 to 2000-01 23.8 27.1 −2.11 +0.67 Downhill Bully
405 Alonzo Mourning 5 1996-97 to 2001-02 24.0 27.0 −1.05 +1.33 Downhill Bully
404 Richard Jefferson 5 2003-04 to 2008-09 25.0 25.6 −1.25 +1.17 Downhill Bully
403 Lou Williams 14 2007-08 to 2020-21 25.5 35.7 +0.47 +2.31 Whistle Artist
402 Stromile Swift 5 2001-02 to 2006-07 26.0 27.2 −1.64 +0.76 Downhill Bully
401 Morris Peterson 6 2000-01 to 2006-07 26.2 29.6 −1.53 +0.81 Downhill Bully
400 Elden Campbell 4 1996-97 to 2001-02 26.6 28.4 −0.30 +1.66 Downhill Bully
399 Eddy Curry 5 2002-03 to 2007-08 27.5 29.2 −1.17 +0.98 Downhill Bully
398 Andre Drummond 8 2014-15 to 2023-24 28.1 32.0 −2.28 +0.22 Downhill Bully
397 Chauncey Billups 9 1997-98 to 2010-11 28.2 32.1 +0.57 +2.11 Whistle Artist
396 Paolo Banchero 4 2022-23 to 2025-26 28.5 31.5 −0.36 +1.33 Downhill Bully
395 Jerry Stackhouse 11 1996-97 to 2007-08 28.7 46.2 −1.18 +0.88 Downhill Bully
394 Paul Pierce 17 1998-99 to 2014-15 29.4 39.0 −0.17 +1.51 Downhill Bully
393 Ramon Sessions 5 2008-09 to 2015-16 29.5 34.3 −0.40 +1.36 Downhill Bully

All 417 careers

Search by name, or sort any column.

Show code
reactable(car_tbl, searchable = TRUE, striped = TRUE, highlight = TRUE, defaultPageSize = 15,
          theme = rt_theme, defaultSorted = "Rank",
          columns = list(
            Rank = colDef(width = 70), Player = colDef(minWidth = 150), Seasons = colDef(width = 90),
            Span = colDef(minWidth = 175),
            EHI = colDef(format = colFormat(digits = 1), style = ehi_color, width = 70),
            `Peak 3-yr` = colDef(format = colFormat(digits = 1), width = 80),
            Skill = colDef(format = colFormat(digits = 2), width = 70),
            Whistle = colDef(format = colFormat(digits = 2), width = 75),
            Archetype = colDef(minWidth = 130),
            Minutes = colDef(format = colFormat(separators = TRUE, digits = 0), width = 85)))

Every qualifying regular-season player-season

4,022 seasons. Expand the components to see what drove each rating. Raw values are shown (before shrinkage and standardization).

Show code
ps_tbl <- rs[, .(Season = season, Player = player, Team = primary_team, EHI = ehi, Skill = skill, Whistle = whistle,
                 Archetype = archetype, Min = mp, FGA = fga,
                 `SMAE (pts/FGA)` = smae_raw, `Unassisted %` = 100 * selfcreate_raw, `Difficulty` = difficulty_raw,
                 `Travels+OF /100` = footwork_raw, `Excess FTr` = excess_ftr_raw,
                 `3PT fouls /100 3PA` = threefoul_raw, `FT % of pts` = 100 * ftshare_raw,
                 `Perim. and-1 /100` = and1jump_raw)][order(-EHI)]
num2 <- colFormat(digits = 2); num1 <- colFormat(digits = 1)
reactable(ps_tbl, searchable = TRUE, filterable = FALSE, striped = TRUE, highlight = TRUE, defaultPageSize = 15,
          theme = rt_theme, compact = TRUE,
          columns = list(
            Season = colDef(width = 80), Player = colDef(minWidth = 150), Team = colDef(width = 60),
            EHI = colDef(format = num1, style = ehi_color, width = 65),
            Skill = colDef(format = num2, width = 65), Whistle = colDef(format = num2, width = 70),
            Archetype = colDef(minWidth = 125),
            Min = colDef(format = colFormat(separators = TRUE, digits = 0), width = 70),
            FGA = colDef(format = colFormat(separators = TRUE, digits = 0), width = 65),
            `SMAE (pts/FGA)` = colDef(format = colFormat(digits = 3)), `Unassisted %` = colDef(format = num1),
            Difficulty = colDef(format = colFormat(digits = 3)), `Travels+OF /100` = colDef(format = num2),
            `Excess FTr` = colDef(format = colFormat(digits = 3)), `3PT fouls /100 3PA` = colDef(format = num2),
            `FT % of pts` = colDef(format = num1), `Perim. and-1 /100` = colDef(format = num2)))

Playoffs

Playoff player-seasons with 150+ minutes and 12+ FGA per 36, standardized against that postseason’s qualifiers (1,302 seasons).

Show code
po_tbl <- po[, .(Season = season, Player = player, Team = primary_team, EHI = ehi, Skill = skill,
                 Whistle = whistle, Archetype = archetype, Min = mp, FGA = fga)][order(-EHI)]
reactable(po_tbl, searchable = TRUE, striped = TRUE, highlight = TRUE, defaultPageSize = 10, theme = rt_theme, compact = TRUE,
          columns = list(EHI = colDef(format = num1, style = ehi_color), Skill = colDef(format = num2),
                         Whistle = colDef(format = num2), Player = colDef(minWidth = 150), Archetype = colDef(minWidth = 125)))

Download the full data: ehi_player_seasons.csv and ehi_careers.csv.