Bayesian vs Frequentist: NFL TDs

Elijah Cavan
CodeX
3 min readApr 16, 2021

--

In this post I wanted to compare two different ways of projecting next year’s TD (touchdown) totals for new Jeopardy host Aaron Rodgers given some prior knowledge (i.e his TD totals from previous years). If you simplify this example, it’s like if I flip a coin 3 times and I want to know what comes up next. There are 2 points of view: The Bayesian perspective and the Frequentist perspective. One is not necessarily better than the other, but they will both give us different answers. Check out this post for some work I did with Bayesian statistics with R: https://ecavan.medium.com/predicting-nfl-first-downs-453a683a827d (this time I’ll use a python library, PYMC3). I’ll use seasons 2008–20012 where the TD totals for Rodgers were: [28, 30, 28, 45, 39].

I’ll spare the in-depth mathematics and just show you how to apply them to this problem. For the frequentist perspective, if we assume the data follows a normal distribution, then the estimators to predict the mean and variance of the true value are just the sample mean and the sample variance (basically a fancy way of stating the law of large numbers). The sample mean in this case is 34. So if I wanted to build a 95% confidence interval, I would estimate the number of TDs Aaron Rodgers will throw on any given year to be between [28, 40] (see this link for a calculator for https://www.mathsisfun.com/data/confidence-interval-calculator.html). So basically, we would assume in the next healthy year Aaron Rodgers will throw 34 +/- 6 TDs. In his next healthy year (he was injured in 2013) he threw 31.

Let’s look at the Bayesian perspective. With the Bayesian perspective, we’ll start with our prior (basically, our guess about what the correct distribution is) which will get updated as we run simulations. Using pym3 this is easy, we can run a bunch of simulations to predict how many TDs Rodgers will throw on any given year.

import pymc3 as pmwith pm.Model() as model:
obs = pm.Normal('obs', mu, sig)
with model:
trace = pm.sample(900, return_inferencedata=False)
ax = pm.plot_posterior(trace, figsize = (8, 8))

Here I’ve just found the mean and standard deviation (as was needed for the frequentist case) and have run 900 simulations. You can look at those simulations to find out how many TDs Rodgers threw that year. It can be shown nicely in this plot (the last line in the code):

(Image by Author)

So our 94% HDI (the Bayesian version of a confidence interval) is between [20, 46]. But wait you say, “isn’t this a much worse confidence interval- because it is larger?”. I would say not necessarily, what it does is capture more uncertainty in the data. For example, in his injured season, Rodgers threw 17 TDs, in 2020 he threw 48 TDs. These values are better captured by the bayesian model. If you’re interested, you can check out the full notebook with all the code here: https://www.kaggle.com/sportsstatseli/nfl-plays-bayesian?fbclid=IwAR0bLRn5F2jOVTfd6AKRFDi6FKmFiQ18CLHaLbs5VSsPooJVv55-bSB4Gs8

And so there you have it, frequentist v.s bayesian perspectives in 2min; and we got to talk about one of the greatest QBs/Jeopardy host to ever do it.

--

--