As a basketball fan who is also interested in math, the lack of symmetry of the NBA regular season schedule has always been a source of small annoyance. While the league has 30 teams, each team plays 82 games (ignoring the recent in season tournament). This combination makes it impossible to play each of the other teams an equal number of times. Instead the games are allocated as follows:
A team will play teams in the opposing conference 2 times per season.
A team will play teams within their own division 4 times per season.
A team will play the remaining teams within their own conference either 3 or 4 times depending on the season.
This imbalance means that in a given season a team may have an effectively harder or easier schedule depending on the strength of their conference and division. As a fan of the Denver Nuggets, a member of the consistently superior Western Conference (and perhaps surprisingly consistent Northwest Division), this is rather annoying. Why should the Boston Celtics receive the same benefit (in terms of wins) by defeating the hapless Brooklyn Nets as the Nuggets get by winning a bloodbath with the Timberwolves?
Fun Fact! Each division winner receives a unique trophy. The Northwest Division winner receives the “Sam Jones Trophy”.
This got me thinking, wouldn’t it be nice if the value of a win was somehow proportional the quality of the teams record. We can make the value of a win against each team proportional to their record but now that results in a new record. So the question becomes, can we make the value of winning against each team such that a win value is exactly proportional to the resulting win counts of each team?
It turns out this is exactly the structure of an eigenvector problem. If we construct a matrix of the season’s results \(A\), such that the \(i, j^{th}\) entry is the number of times the \(i^{th}\) team beat the \(j^{th}\) team. Then we seek the eigenvector \(\boldsymbol{u}\):
\[A\boldsymbol{u} = \lambda \boldsymbol{u}\]This means that when the win matrix \(A\) is multiplied by the win value vector \(\boldsymbol{u}\), we get a vector of win counts exactly proportional to the win values. We can solve this system easily with any eigenvector solver (I used NumPy). The scale of \(\boldsymbol{u}\) we get from the solver won’t make much sense in comparison to the value of a win we are used to (aka 1), so we scale things so the total number of wins is what it would be in a normal season (\(15 \cdot 82 = 1230\)). You can see the adjusted win values in the below table. You can also see the effective win total using the new win values (an “unskewed” schedule result so to speak) and how that would have affected the location of the team in the overall standings.
What are the big takeaways for the 2023-2024 NBA season?
(Note, these values don’t exactly reflect the tiebreaker scenarios the NBA employs for teams with the same records. So it is possible the ranking changes can be a little off depending on how tied teams got randomly sorted.)
I like that this adjustment takes place on an individual team level - as opposed to a conference wide adjustment. It would be fun if there was a particular “giant killer” one year who beat all the best teams despite an overall poor record.
Big shoutout to the nba_api library. I found it surprisingly difficult to find a convenient source of nba records.
Win Value | Team | Adjusted Win Count | Original Win Count | Ranking Change |
---|---|---|---|---|
1.77 | Boston Celtics | 64.67 | 64 | 0 |
1.68 | Oklahoma City Thunder | 61.22 | 57 | 1 |
1.62 | Minnesota Timberwolves | 59.01 | 56 | 1 |
1.62 | Denver Nuggets | 58.87 | 57 | -2 |
1.43 | LA Clippers | 52.13 | 51 | 0 |
1.42 | Phoenix Suns | 51.79 | 49 | 3 |
1.40 | New Orleans Pelicans | 51.18 | 49 | 1 |
1.40 | Milwaukee Bucks | 50.91 | 49 | 2 |
1.38 | Sacramento Kings | 50.28 | 46 | 8 |
1.38 | Dallas Mavericks | 50.11 | 50 | -4 |
1.37 | Indiana Pacers | 50.01 | 47 | 3 |
1.37 | Los Angeles Lakers | 49.81 | 47 | 1 |
1.30 | New York Knicks | 47.31 | 50 | -6 |
1.27 | Cleveland Cavaliers | 46.26 | 48 | -3 |
1.23 | Golden State Warriors | 44.93 | 46 | 3 |
1.21 | Philadelphia 76ers | 44.23 | 47 | -4 |
1.21 | Orlando Magic | 44.13 | 47 | -2 |
1.15 | Houston Rockets | 41.78 | 41 | 1 |
1.14 | Miami Heat | 41.38 | 46 | -3 |
1.01 | Chicago Bulls | 36.89 | 39 | 0 |
0.99 | Atlanta Hawks | 36.17 | 36 | 0 |
0.82 | Utah Jazz | 29.98 | 31 | 1 |
0.81 | Brooklyn Nets | 29.52 | 32 | -1 |
0.74 | Memphis Grizzlies | 26.85 | 27 | 0 |
0.66 | Toronto Raptors | 23.96 | 25 | 0 |
0.62 | San Antonio Spurs | 22.63 | 22 | 0 |
0.57 | Charlotte Hornets | 20.66 | 21 | 0 |
0.53 | Portland Trail Blazers | 19.38 | 21 | 0 |
0.34 | Washington Wizards | 12.41 | 15 | 0 |
0.32 | Detroit Pistons | 11.50 | 14 | 0 |