Creating WNBA Power Rankings
Reproducing my favorite Elo model, with automation and forecasting.
Click here to view each team’s individual Elo progression and forecast
To forecast wins in professional sports, there are a many different approaches that could be taken. In the past, I’ve used Monte Carlo simulation, both at the player and team level to create box scores and projected outcomes. Although these are great, it can often be hard to tell how these simulations are being made. When considering easy but accurate power rankings though, Fivethirtyeight’s have always had a soft spot in my heart.
Fivethirtyeight’s Elo models have been heralded as some of the best that are publically available, and Neil Paine has done a great job of keeping them up even after many of Fivethirtyeight’s original rating systems haven’t updated. My goal of this article was to re-create the rating system on my own (using their recommended k-factor and home court advantage) and build upon it by creating new foreacasting charts.
Elo ratings have always been a favorite of mine because they are simple and interpretable. Each team starts at the same point, and they either gain or lose points for a win or a loss. How much they gain or lose depends on the quality of their opponent. If you beat a good team, you get a lot of points. If you beat a bad team, you get relatively few points but still gain. If you lose to a really good team, it’s not a large point reduction. An Elo rating above 1,500 is generally a winning team, and an Elo rating below 1,500 is generally a losing team.
Another benefit of Elo is that it can be used to predict future outcomes. Within every Elo calculation is a pregame winning expectation for each team. This projected win percentage can be used to simulate future games. In this write-up, I’ll discuss how I re-created a similar Elo system to Fivethirtyeight and then added a couple of new ideas to it. Another big part of this project was automation: time can be costly and I don’t want to have to manually update these rankings and tables. Through this process, I put together an automation process that I’m generally pleased with.
When it comes to the structure of this article, I’ll proceed in three sections:
Creating an Elo system
Simulating future games
Creating an automation
(Re)Creating an Elo System
When it comes to setting up an Elo rating system, there are two unique factors to this analysis that I wanted to consider: the k-factor and home-court advantage. For both of these, I went with what FiveThirtyEight recommended: k = 20 and a home court boost of 100 Elo points. I think there is some argument to be made that home court advantage is less in the WNBA (and maybe doesn’t even affect the Indiana Fever this season) but for the sake of simplicity and consistent results, I stuck with those. Fivethirtyeight’s power ranking system is what I consider the best out there and it’d be pointless for me to try and come up with something better from scratch. Instead what I plan to do is use their factors as a starting point, and incrementally update the system as I explore new information.
If you’re interested in actually programming an Elo system yourself, geeksforgeeks has a great example here. If you’re interested in learning more about Fivethirtyeight’s model, you can view their description here. When it comes to actual Elo ratings, you can consider 1,500 to be a pretty neutral team. Anything above it is a relatively ‘good’ team and anything below is relatively worse. For example, the Indiana Fever, at the time of writing have a forecasted win total of 20-20 and an Elo of just above 1,500.
If you have any concerns or thoughts for improvement with the current calculations, please let me know. It seems like the biggest discrepancy between my ratings and Neil Paine’s are that I didn’t use previous years’ data, rather only this year. It’s in general a small difference at the end of the season, but may be helpful when a fresh season occurs.
Simulating Future Games
Now that the current wins have created an Elo system, the next step was to forecast the future games. The good thing about this? It’s actually pretty straightforward.
Included in Elo calculation is an expected win percentage when two teams play each other. What I do is I take this expected win percentage, roll a “die” based on that percentage, track the outcome of the die roll, and then update the ratings accordingly.
To get an accurate representation of what may actually happen, I do this 1,000 times and then track both a 95% confidence interval and the mean outcomes of these simulations. I can then plot the actual and forecasted Elo (an addition to the current models and rankings employed by Fivethirtyeight) like the following:
The above chart shows the current Elo for the New York Liberty. There’s a chance that you don’t actually see the average or confidence interval and if that’s the case it’s because there isn’t a current ongoing WNBA season. The chart live updates each day, so as the season progresses it’ll change over time. I’ll continue to build upon the current system in the future but for now it’s exactly what I’m hoping for!
Creating an Automation
The final step in this process was to automate the system so I didn’t have to update every rating manually. There are only 12 teams in the WNBA, so it wouldn’t be too time intensive to try and update each on my own, but if I want to apply the same idea to other teams it’d be silly. My steps for automation were the following:
Get the current data from Basketball Reference
To get the data from basketball reference, I used the above-linked ‘scedule and games’ page they have. They do a great job of updating this and in general I couldn’t praise Basketball Reference enough. I try and source them in all charts that have any data for their site.
Split the games up into completed and incomplete games
Using some simple if/else statements, I can create two dataframes in R. One for completed games and one for games that haven’t happened yet.
Calculate elo for completed games
Simulate future games and track outcomes
Steps 3 and 4 are what I discussed in the previous section, but this is simply doing them within an R script.
Publish the data to Google Sheets
Using R’s Googlesheets4 library, I then write the data to google sheets. I like Google Sheets for this because it allows for super easy viewing of the data without download (if others want to see it) but really anything that can create CSV files will work for this step.
Link Google Sheet to Datawrapper table
Datawrapper allows for CSV links (and updates) to be used, so although it took a little time to duplicate and rename/recolor charts for each time, it was actually a pretty quick process to create the chart for every team.
Set up WNBA Central
The part of this project I’m most excited for is WNBA central: one place linked on the website’s homepage where you can find information on all WNBA teams. If this goes well I plan to add similar pages for other leagues (NFL, NBA, and College Football all start soon)!
Concluding Remarks
Alrhough this is a pretty straightforward project, I had a ton of fun putting it together. Fivethirtyeight has had my favorite ratings for a long time and it was an awesome experience giving Elo a go, and setting up a power ranking system based off of theirs. I’m not making any money off of this and Elo isn’t a proprietary model (it was originally used in chess) but if you have any concerns with the model or ideas related to it please leave a comment and I’d be more than happy to get back to you.
As always, thanks for giving this a read!