The Masters Tournament is one of four majors on the PGA Tour each year, and widely considered the biggest and best golf tournament in the world. I wanted to see if I could predict the results of that tournament using data science. The most common gambling bets you can make in golf are tournament winner, top-10 finisher, and making/missing the cut, so I decided these would be the things I try to predict. One of my questions will be if any of these three outcomes are easier or harder to predict than the others. I also am interested in what features are best at predicting these outcomes.
I am going to attempt to answer these questions by predicting a mean and variance for each golfer participating in the Masters Tournament, then use those values to run many simulations and see how often each golfer wins, places top 10, and makes the cut.
To get my data, I webscraped the PGA Tour leaderboards from ESPN’s website. Each tournament was a different webpage, and I aggregated those pages into one csv that I loaded into this notebook. I collected all the individual tournaments from each of the past 16 seasons (starting in the 2007 season until present day). The table below is a random sample preview of how the collected data looks. You can look at my GitHub repo for this project to see more details about how the data was scraped.
| position | player | score | cut | withdraw | dq | R1 | R2 | R3 | R4 | total | earnings | fedex_points | tournament | start_date | location | course | par | length | fedex_cup_event | TID |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 118 | Paul Barjon | NA | TRUE | FALSE | FALSE | 73 | 78 | NA | NA | 151 | 0 | 0 | U.S. Open | 2021-06-17 | La Jolla, CA | Torrey Pines (South Course) | 71 | 7652 | TRUE | 210617U.SO |
| 18 | Anthony Kim | -8 | FALSE | FALSE | FALSE | 63 | 69 | 73 | 67 | 272 | 75600 | 315 | Crowne Plaza Invitational at Colonial | 2007-05-24 | Fort Worth, TX | Colonial Country Club | NA | NA | TRUE | 070524CPIaC |
| 80 | Billy Hurley III | NA | FALSE | FALSE | FALSE | 71 | 71 | 73 | NA | 215 | 12104 | 0 | Zurich Classic of New Orleans | 2014-04-24 | Avondale, LA | TPC Louisiana | 72 | 7425 | TRUE | 140424ZCoNO |
Since I am trying to make predictions for the yearly Masters Tournament, I need to manipulate this data set into one that I can use to run predictive models on. I need one row for each participant for each year’s Masters Tournament, then I will need to create a set of predictors using the data I scraped from ESPN.
The first thing to think about when designing our data set is that we want to predict how golfers do compared to each other, rather than compared to par or total score. This is because due to course difficulty, weather conditions, or any other sort of external variation, a score that is good enough to place top-5 at one tournament may not be good enough to make the cut at the next. Because of this, we want our score variables to be in reference to the field of other golfers.
When calculating these scores, we can compare the player’s round score to the mean round score or the median round score.
As you can see in the plot above, they are very closely related to each other, but means tend to be higher estimates than medians. Only Round 1 means/medians are plotted above, but all rounds displayed this same pattern. This suggest that the distribution of scores is slightly skewed towards higher scores. You will see that this is true soon, but for the purposes of generating golfer round scores relative to other golfers, I will use the median since it better accounts for outliers.
The next thing we want to consider is whether or not we think that score distributions are statistically similar for each round. I have a good feeling that they are not, because after Round 2 of most tournaments, roughly half of the field is “cut” and do not play the next two rounds. Since the golfer in the middle of the distribution of Rounds 1 & 2 should now theoretically be at the bottom of the distribution in Rounds 3 & 4, it seems like we would want to estimate different scores for them depending what round they are in.
We can visually see that scores in Rounds 3 and 4 appear to be lower than in Rounds 1 and 2. (We also see that the distributions are slightly left skewed, as mentioned earlier). We will run a Kolmogorov-Smirnov Test on the distributions to see if they are statistically different from each other.
##
## Two-sample Kolmogorov-Smirnov test
##
## data: R12 and R34
## D = 0.084759, p-value = 0.0001004
## alternative hypothesis: two-sided
Our p-value is easily significant at the .01 level, so from this test we know that scores in Rounds 3 and 4 are not drawn from the same distribution as scores from Rounds 1 and 2. This confirms that we should make different mean estimates for golfers in the later two rounds than in the first two rounds.
We set up our data frame by having one row for each golfer in each Masters Tournament. We will have two outcome variables in each row, one for the mean of the first two rounds one one for the mean of the second two rounds. Remember, all of our scores now are relative to the median golfer in that round, and not the total strokes or relative to par.
I excluded the first year’s (2007) Masters Tournament from our data set because I want to use the year leading up to each Masters as predictors, and my data doesn’t include 2006 data, so we’d have no predictors for it. I also excluded the 2020 Masters since that season was heavily affected by COVID and caused cancellation of many tournaments leading up to the Masters, as well as the Masters being delayed 7 months.
Now we need to create features that can help predict our outcome variables.
I first wanted to see if making cuts in tournaments in the year leading up to the Masters is related to Masters score. I create two binned scatter plots; the x-axis is a created feature representing the percentage of time a golfer makes the cut in tournaments he played in during the year prior to the Masters. The y-axis is score in the first two or last two rounds of the Masters.
As you can see, there is a clear trend showing that as a golfer makes more cuts, their score in the Masters decreases. I will use this feature when making predictions, and break it down into more specific time periods: the month prior, 1 months to 6 months prior, and 6 months to 1 year prior.
Along with cuts made, I want to use top-10 finishes and tournament wins in the prior year as predictors for Masters round score.
Here are the binned scatter plots for wins and top-10 finishes. Some are more closely related than others, but in all 4 you can see that as wins or top-10 finishes change, so does average round score. In the wins plots, you can see that having no wins doesn’t predict that you will do worse than the median golfer that day (about 0 predicted score for no wins), but as you get more wins throughout the year, your predicted Masters score drops lower and lower.
The last predictor I want to add is how the golfer did in the Masters the previous year.
Here is a preview of our data set with the predictors we created. We can now move on to using it to create models.
| player | start_date | year | TID | R12 | R34 | last_year_masters_finish | cuts_percent_last_year | cuts_percent_last_month | cuts_percent_1m_to_6m | cuts_percent_6m_to_1yr | top10_last_year | top10_last_month | top10_1m_to_6m | top10_6m_to_1yr | wins_last_year | wins_last_month | wins_1m_to_6m | wins_6m_to_1yr |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Dustin Johnson | 2016-04-07 | 2016 | 160407MstT | -2.0 | -2.0 | 6 | 0.9545455 | 1 | 1.0000000 | 0.9285714 | 11 | 1 | 3 | 7 | 0 | 0 | 0 | 0 |
| Derek Ernst | 2014-04-10 | 2014 | 140410MstT | 2.0 | NA | NA | 0.3793103 | 0 | 0.4545455 | 0.4000000 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
| Vijay Singh | 2018-04-05 | 2018 | 180405MT | -1.5 | 3.5 | 75 | 0.3333333 | 0 | 0.2500000 | 0.4000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
To start my modeling process, I will separate my data into testing and training sets. My test set will be observations from the most recent Masters Tournament (2022) and my train set will be all other seasons. I will break down my train set into 6 fold cross validation, stratified by year of the tournament.
I want to find a model and predictors that give a low RSME after being cross-validated because that suggest that the model is not overfit and would make good predictions on data it hasn’t seen before. I want to try a few different models: a simple linear regression, an elasticnet regression model, and a non-parametric model, Random Forest. I want to try these models on a couple different sets of predictors: one set will have the predictors I created that account for the past year, and the other set will be the same predictors, but instead of one variable accounting for the last year, the year will be broken down into 3 variables that combine to make up the last year.
Simple linear regression with our last_year predictors created a model with 2.24 RMSE for the first two rounds and an RMSE of 2.07 for the last two rounds. Lets see if that increases or decreases when we use the more specific time predictors.
Simple linear regression with our more specific predictors created a model with 2.23 RMSE for the first two rounds and an RMSE of 2.06 for the last two rounds. These are practically the exact same as the results with the last_year predictors.
The last thing I want to try with simple linear regression is to try and find any predictive interaction terms that I can.
I interacted the golfers performance in the Masters last year with their performance variables in the tournaments in the year leading up to the Master’s. It made a negligibly small difference in the resulting RMSE. (I also tried some transformations of the predictors using log, sqrt, and polynomials, but nothing made any noteworthy differences)
I now want to try a regularized linear regression model. I will cross validate the penalty and mixture values.
After running the elasticnet model, we once again get no meaningful changes to our RMSE. Above you can see a graph of how our RMSE changes when our parameters changed in CV. As you can see, it appears that we are on an asymptote of our RMSE where we can no longer reduce the error. However, before making our predictions, I want to try a non-parametric model to see if it can do any better, so I will use a random forest.
It also appears in the random forest model that we have reached the minimum RMSE given our predictors. Using the random forest model we ran, we can find which predictors are most important to predicting the outcome. As we can see, wins in the past year aren’t very predictive of score at the Masters.
Since all of our models produced basically identical results, we will use the simplest one to make predictions with. Our simplest model is our linear model with no interactions and only using the last_year predictors.
After predicting the means and calculating the standard deviation for each golfer participating, we end up with a data frame that looks like this that we can use to run simulations.
| player | R12pred | sd12 | R34pred | sd34 |
|---|---|---|---|---|
| Tiger Woods | 2.9273971 | 3.114790 | 1.6339967 | 3.261077 |
| Matthew Wolff | 0.6557983 | 3.380332 | 0.7913496 | 3.210151 |
| Louis Oosthuizen | -1.2026731 | 2.892967 | -0.2785152 | 2.547218 |
I now am going to write a function that uses our created data frame with the round means and standard deviations for each golfer that will run n simulations.
After running 10,000 simulations of the 2022 Master’s Tournament and summarizing the results, we end up with a data frame that looks like this
| player | win_percent | top10_percent | make_cut_percent |
|---|---|---|---|
| Aaron Jarvis | 0.0000 | 0.0006 | 0.1004 |
| Abraham Ancer | 0.0357 | 0.2570 | 0.8191 |
| Adam Scott | 0.0086 | 0.1205 | 0.6741 |
After summarizing the results of our simulations, we can look and see who won, finished top 10, and made or missed the cut most often in our simulations.
We can then collect the betting odds from before the tournament started and find the implied percentage they give each golfer of winning, finishing top 10, and making the cut. If our simulation says they achieve those milestones more often than the betting odds imply they would, then our model says its a good bet to make.
I will collect betting odds from BetUS Sportsbook from the morning the 2022 Masters started (before any golfer teed off).
After comparing the probabilities the simulation gives a golfer to win and the probabilities the betting odds give a golfer to win, we can find the widest margins to find the best and worst bets according to our model. Note that betting odds are not available for every golfer in the field.
The black line in this graph is where the probability of winning according to the betting odds and the probability according to our simulations are the exact same. Points above the line represent good value bets according to our model, and points below the line represent bad value bets. You can see that there are more bad value bets than good value, and this holds true in top10 and making or missing the cut.
When identifying the bets we want to make, we will look for the points that are the furthest distance above the line. We will make a data frame of all the bets out model suggest we should make. We can then calculate how many of those bets we win, and what profit we would make on them.
| prop | good_bets_identified | bets_won | net_profit |
|---|---|---|---|
| Winner | 4 | 1 | 14.00 |
| Top 10 | 6 | 0 | -6.00 |
| Make Cut | 14 | 8 | 5.08 |
| Miss Cut | 5 | 2 | 4.10 |
| Total | 29 | 11 | 17.18 |
As you can see from the table, we found 29 bets to make and won 11 of them. If we bet 1 unit on each bet, we would profit over 17 units (with most of that profit coming from the fact that we correctly identified the winner). You can also see that we took 6 tries at identifying valued Top 10 bets, but missed on all 6. That could be a model deficiency, or just random chance. It’s important to note that we only tested these model results on one year of Masters tournaments, so this could be an exceptionally good result, a exceptionally bad result, or an average result of this model. We wouldn’t know until we tested more seasons.
As you could see above, for the 2022 Masters, we successfully identified some good value bets and ended up making a 17 unit profit on 29 one unit bets. This model cannot be considered successful though unless we test it on more data.
The impact of this model would primarily be in the sports gambling market. I designed the predictors for the annual Master’s tournament, but it could be generalized to other PGA tournaments as well.
There are future improvements I plan on making. I’d like to collect more data for other predictors. The PGA Tour Website has stats that I’d like to webscrape. These stats account for how good a golfer is at certain areas of his game (ex. driving, putting, etc.). Since the Master’s is played on the same course every year, it would make sense that if putting is very predictive of round score in 1 year, then it will also be predictive of round scores in other years. Because of this, I think those stats that break down skills will be useful predictors that could decrease my RMSE when making round score predictions. I will update this file when I implement those changes.