# Correcting for season-length bias of Gini on win percentage

I made this plot to try and compare the competitiveness of the major US sports (NHL/NBA/MLB/NFL):

Each point of a given color represents, for a given season, the Gini coefficient of the win percentages in that league. So for example, the rightmost red circle is the Gini for the 2015-16 NBA season (as of yesterday). I calculate the win-loss percentage for each team in the league and feed this as data to ineq::Gini in R, which should be calculating the Gini as explained on Wikipedia.

Unfortunately, using this plot to compare across sports is fraught with issues; my main concern is the mechanical suppression of the Gini induced by the varying number of games in a season across the sports.

The NFL season is only 16 games long, while that in the MLB is 162. It is possible (and in fact empirically valid) that a team can go 0-16 in a short season, but nigh-impossible that even a horrible team goes 0-162, even while a team in a long season can go on a 16-game losing streak.

Basically, it appears that regression to the mean is biasing the Gini coefficient down for long-season sports. To test this hypothesis, I randomly sampled sub-seasons of MLB of varying lengths, computed the win percentage on the sub-season, and averaged over many repetitions to see if there's a clear relationship between subseason length and Gini, within the same sport. The result is clear:

How can we correct the simple Gini used in the first graphic in order to allow for a more equitable (i.e., not statistically incomparable) comparison of the sports?

Code to reproduce this analysis can be found on my GitHub here; the simulation for season-length sensitivity is towards the bottom.

• Did you manage to solve this issue ? I've a similar problem. – Nicolas Rosewick Jan 27 '17 at 12:44
• @NicoBxl see minor update – MichaelChirico Apr 4 '17 at 19:48

Decided to do another small simulation study. Basic idea being to just randomly assign winners & losers to a league of a given size for a variety of different season lengths. One key assumption here is that all teams are equal -- there's no "dominant team" and every game is decided 50-50.

Here's the code (caveat coder -- this takes a fair amount of time to run. I should have done it in Julia):

library(ineq)
library(data.table)
n_teams = 30L
#vary over season lengths: 5 to 200
gini_sl = rbindlist(lapply(setNames(nm = 5L:200L), function(n_games) {
# for each season length, simulate 1000 seasons
data.table(gini = replicate(1000L, {
#declare win-loss matrix for recording "standings"
WL = matrix(0L, nrow = n_teams, ncol = 2L)
idx = rowSums(WL) < n_games
while (any(idx)) {
# draw two teams at random from among the
#   teams who haven't "completed their season" yet;
#   sometimes, one team is left with a bunch of games
#   to play, but no incomplete pair to play against --
#   in this case, they play against themselves.
teams = sample(which(idx), 2L, replace = sum(idx) == 1L)
#increment win/loss for chosen teams
WL[teams, ] = WL[teams, ] + diag(2L)
idx = rowSums(WL) < n_games
}
#compute gini coefficient on "completed season"
Gini(WL[ , 1L])
}))}), idcol = 'season_length')

# idcol casts as character by default; convert
gini_sl[ , season_length := as.integer(season_length)]
boxplot(gini ~ season_length, data = gini_sl)


Here's the output:

gini_sl[ , .(median = median(gini), mean = mean(gini)),
keyby = season_length][seq(1, .N, by = 10)]
#     season_length     median       mean
#  1:             5 0.24452778 0.24453555
#  2:            15 0.14302026 0.14303616
#  3:            25 0.11172033 0.11227162
#  4:            35 0.09474721 0.09566695
#  5:            45 0.08339062 0.08392356
#  6:            55 0.07573928 0.07599356
#  7:            65 0.06966614 0.06995423
#  8:            75 0.06549000 0.06580514
#  9:            85 0.06144261 0.06171767
# 10:            95 0.05774995 0.05815323
# 11:           105 0.05521296 0.05554579
# 12:           115 0.05247558 0.05281911
# 13:           125 0.05051253 0.05080175
# 14:           135 0.04831696 0.04857244
# 15:           145 0.04695128 0.04704699
# 16:           155 0.04559718 0.04564016
# 17:           165 0.04390681 0.04440646
# 18:           175 0.04235574 0.04258819
# 19:           185 0.04142130 0.04162010
# 20:           195 0.04013068 0.04055239


So even without any "dominant teams", we observe a fair amount of inequality for short seasons, which goes away the longer the season is. I still haven't been able to capture this relationship mathematically, but I'm even more convinced it's fundamental. It seems one way to correct for the season-length bias would be to place a given sport's Gini in a season as a quantile in the distribution obtained here.