Predicting the 2023 NBA Draft Using Decision Trees
by Austin Jeong (austinsehojeong@gmail.com) and Thomas Kim (thomasekim10@gmail.com)
Every year, the NBA hosts a draft to recruit the next generation of talent into the league. From the 100-200 prospects who declare for the draft, only 60 players are ultimately selected. With every draft comes an element of unpredictability due to the possibility of players being overrated, known as "busts", or underrated, known as "steals". Since teams cannot always predict a player's potential before they are drafted, they must carefully strategize and choose players who will enhance their roster. So how do they do that?
The drafting process does not neccessarily come down to an exact science. However, according to an article on Bleacher Report, NBA draft scouts often look for physical attributes and athleticism. This includes height, wingspan, speed, and verticality. The NBA is a very competitive league, and having vertical reach and horizontal mobility is undoubtedly an important asset to have. They also seek players with solid work ethic and coachability. And of course, they look for a saavy basketball player. Someone who excels at offense or defense, and in the best case, both. And if a team cannot acquire a generational talent, they try to secure a role player who can seemlessly fit into and contribute to a team's system. There is no qualitative data that can encapsulate all these factors, and the selection often comes from a scout's knowledge and expertise. However, we believe that a prospect's draftability is reflected by their on-court productivity in college.
We will employ a Decision Tree Classifier to predict the 2023 draft order. This approach emulates the decision making process an NBA scout could make when selecting players. Our model will be trained on data containing various college statistics as well as height. An important thing to note is that we will remove players who did not attend US college from our data. While many of the most famous picks in the NBA draft came from the non-college route, such as Kobe Bryant, Lebron James, and most recently Victor Wembenyama, we want to maintain a level of uniformity in our data because the competition in high school and international leagues can be argued to be different versus that in college. As a result, our 2023 draft predictions will not include non-college prospects.
Import Libraries and Datasets
First, import necessary libraries. We will primarily be using Pandas for data manipulation as well as Numpy, Matplotlib, and Sklearn for doing mathematical calculations, plotting figures, and modeling, respectively.
Next, import the necessary datasets. We used the Beautiful Soup Library to webscrape statistics from Basketball Reference and Sports Reference. These are the datasets we found:
Data Cleaning
We start by removing unwanted rows and columns from the nba_draft dataset and adding respective draft classes for visual purposes, although we will not be using players' draft classes in our model.
Remove players who did not attend college, or where 'College' is nan. This process results in removing 294 players from our dataset.
We then merge datasets of NBA draftees, college stats, and their heights.
*Note that college_stats has fewer rows than nba_draft_clean because of problems we ran into while web scraping, such as not being able to find the player or some stats were missing. As a result, when we merge these two datasets, we exclude the players in nba_draft_clean that are not in college_stats.
Next, we abbreviate column names for better readability and usability. We also add a column called 'STRT%', which is the number of college games started divided by the number of college games played for each player.
We now proceed with dropping unnecessary columns. We drop features that will not be used in the training data, such as 'Player', 'College' and 'draft_class'. We also drop columns that can be explained better in another singular column. For example, FG% (field goal percentage) is a result of the field goals attempted and made, so we can drop columns like 'FGMPG' (field goals made per game) and 'FGAPG' (field goals attempted per game).
We also fill nan with 0 for every column except for height and remove rows with nan in the height column.
Now, the data is organized and void of any nan values. nba_draft_college_clean will be used as the training/validation data and contains 831 players' pick number and college statistics. We can proceed with the model.
Implementing the Decision Tree Model
The features that we decided to use in our model are:
FG%: the percentage of field goal attempts made from any distance, excluding free throws. This includes 2-point and 3-point field goal percentages, so those are excluded. FG% indicates a player's efficiency and quality of shot selection which are important for a productive player.
FT%: the percentage of free throw shots made. A high percentage free throw shot is a good indication of great shooter. It can also represent a player's focus and work ethic.
RPG: the number of rebounds per game. Represents a player's activity on the board and their physicality. Having a high number of rebounds per game indicates the player is securing the ball and can help contribute to a team's win.
APG: the number of assists per game. Assists are recorded when a player passes the ball to a teammate which leads directly to a made shot. Displays a player's playmaking and decision-making skills. Represents a player's offensive ability.
SPG: the number of steals per game. Steals are recorded when a player intercepts a pass or dislodges the ball from an opposing player. Steals disrupt the opponent's offense and often creates offensive opportunities through fastbreaks. Represents a player's defensive ability.
BPG: the number of blocks per game. Represents a player's defensive ability to stop shots close to the rim. Having a player who is good at blocking can pose as a difficulty for teams to score in the paint.
PPG: the number of points per game. Represents a player's shotmaking ability and efficiency on offense. Players with high points per game often show consistent scoring ability and shot creation. Being efficient and high scoring are traits that are coveted in the NBA.
WS/40: the number of wins shares per 40 minutes played. Win shares are an advanced statistic that estimates the number of wins an individual contributes to a team and is calculated using a multitude of statistics (more information here). We use win shares per 40 minutes over win shares to account for the variations in playing times between players. WS/40 estimates the number of win shares a player contributes if they played a full 40 minute game.
Height: the height of a player in centimeters. Height is not the be-all end-all for NBA players, but it does improve a player's ability to do things on the court, from shooting at a higher point, passing over defenders, to grabbing rebounds and blocking.
For the Decision Tree model, we referred to this tutorial from Datacamp. We first create an 80/20 split and then we run the model for 1000 iterations and save the best performing classifier into best_clf. We determine the performace of a single model by getting the mean of the differences between our predicted pick and actual pick and save the the lowest mean difference into best_diff. We use the absolute differences as our performance evaluator as opposed to accuracy because with 60 different classes, the accuracy will tend to be low for all cases. For instance, if our model predicts a player to be one position above or below their actual pick, this means the model performed well despite not being completely accurate. We then store the array of differences into best_abs_diff.
Above, we can see the distribution of differences between our predictions and actual pick numbers in our test data. The distribution is skewed right, which is a good sign for us since we want the differences to be as small as possible. The red dotted line indicates the mean difference.
We visualized part of the decision tree here to show how the tree comes to its classifications.
Now, we can use our model to predict the picks for the 2023 NBA draft. First, we merge and manipulate the 2023 draft datasets so that we get a dataset that is the same format as nba_draft_college_clean.
*Note that the players listed in the class_2023 dataset are the top 60 players that attended a US college from this list (this link now shows the best available players after the 2023 Draft took place). In other words, we are simulating a draft without non-college players.
We now use our model to make predictions on the 2023 draft prospects.
This table shows what our model predicts to be the order of the 2023 draft.
*This part was done after the 2023 NBA Draft took place.
At the time of writing, we now know the outcomes of the 2023 draft, so we can evaluate our model based on the real outcomes as opposed to mock drafts. Here, the 'Predicted Pick' is our model's predictions, the 'Actual Pick' are the results of the 2023 draft, and the 'difference' is the absolute difference between the predicted pick and the actual pick. The players are sorted in ascending orders on 'Actual Pick'.
The result shows only 36 rows, because 24 players from the mock draft we used did not end up getting drafted.
Takeaways
Our model was able to predict the 2023 draft with a difference error of around 15 picks. Considering that there are 60 picks in the draft where the difference can vary from 0-59, roughly being in the lower quartile of that range is a decent result for us. Furthermore, as stated in the introduction, the NBA draft has some quantitative analytical aspects to it, but it is widely a qualitative decision making progress. That said, some improvements we can make if we were to do this project again are:
Lastly, we would like to give credit to this article by Saadin Mir which served as an inspiration and a helpful guide to kickstart our project.