Using a Shiny App in Prediction


In last week’s post, I introduced a Shiny App to demonstrate Bayesian prediction of batting rates for the remainder of a season. Here’s the link to the live version of the app:

On Twitter, Tom Tango was kind to say some nice things about my app, explain some of the notation and offer a suggestion for improvement. Motivated by Tom’s comments, I thought it would be worthwhile to provide additional explanation to demystify these predictions for the interested reader.

Predicting AVG for Second Half of the Season

Here is a snapshot from the “Rates” tab of my Shiny app. By selecting the Outcome “H”, I am focusing on predicting batting averages. I choose 2019-07-01 as a Date Breakpoint so we are using BAs in the first half of the season to predict the BAs in the second half of the season. By choosing Minimum At-Bats of 1, I am using all players who have at least 1 AB in the first half, and I am excluding pitchers batting (I’ll comment on that later).

Predicting Yonder Alonso’s BA Using a Prior

Let’s illustrate prediction for one player. Suppose we are interested in predicting Yonder Alonso’s BA for the second half of the 2019 season. In the first half of the season Yonder had 29 hits in 219 AB for a BA of 29 / 219 = 0.178. We certainly think that Yonder will improve in the second half, but by how much? A Bayesian does this prediction by first constructing a Beta prior on Yonder’s batting probability. Suppose I think that Yonder’s true batting average is 0.260 and my prior guess is worth about 100 observations. In other words, my prior information is equivalent to 100 x 0.260 = 26 hits and 100 x 0.740 = 74 outs. We combine this prior “data” with the observed data (39 hits and 180 outs) to obtain my estimate at Yonder’s true hitting probability as shown in the following table.

Combining the observed data with my prior data, we have a total of 319 AB and 65 Hits and so my estimate at Yonder’s true probability is 65 / 319 = 0.204. Basically I am “regressing” or moving Yonder’s 0.178 observed AVG towards my prior guess of 0.260.

Multilevel Model Predictions

This Bayesian method I just described is tricky to implement since it requires one to construct a prior for a player’s batting probability based on one’s opinion and we generally are not very good in this construction process. But if we fit a multilevel Bayesian model to all of the hitting rates of all players simultaneously, this model essentially estimates the prior that I can use in this prediction. Just like in my Bayesian prior, this model estimates two quantities — eta, the mean hitting probability of all players, and K, the estimate of the strength of the belief in the estimated value of eta.

The value K does not correspond to a strikeout — Bill James and Tom Tango call this quantity the Regression Amount or Ballast. It can be interpreted as a prior sample size that can be used as in the earlier example to predict the future BA.

Looking at the Shiny app output we have eta = 0.251 and K = 264 so the prior number of hits and outs are respectively 264 (0.251) = 66.3 and 264 (1 – 0.251) = 197.7. We combine this prior data with Yonder’s hit/out data to obtain the prediction.

Combining the data and prior, our prediction at Yonder’s future BA is 105.3 / 483 = 0.218. (By the way, the prior numbers of hits and outs are the estimated values of the Beta shape parameters that describe the talent distribution. One sees these values of the shape parameters in the Talents tab in the Shiny App.)

Should We Exclude Pitchers?

Tom Tango thought that I could improve the first version of my app by allowing one to exclude pitcher hitting from the data. Does this make a difference? If I select the “Exclude pitcher batting” option to be “No”, I am including all batters in the model. Now the Shiny app gives different estimates for eta and K:

eta = 0.244, K = 184.737

Note that my estimate eta for the average BA has dropped from 0.251 to 0.244 which is not surprising since we are including the weak-hitting pitchers. Also my estimate for K has dropped from 264 to 184. This means that the strength in my prior belief has dropped and the observed BA won’t be adjusted as strongly towards the average in my prediction.

Role of Minimum At-Bats

Tom Tango said that my Shiny app clearly shows that the number of at-bats is informative about the talent of the hitters. Let me explain this AB issue here.

My multilevel model assumes that the true batting rates follow a Beta curve. The mean of this curve is eta and the standard deviation of this curve is given by

SD = \sqrt{\frac{eta (1 - eta)}{K + 1}}

Going back to my example of using all hitters (minAB >= 1) and excluding pitcher hitting, the mean and standard deviation of this Beta curve are respectively eta = 0.251 and SD = 0.027. (We see the values of eta and SD from the app.)

What if I change minAB to be 100? The values of eta and SD change to 0.257 and 0.024. The hitting talents of these players are generally better (higher mean) and have smaller variation (smaller standard deviation).

Let’s change minAB to 300 — the values of eta and SD are now 0.279 and 0.014. The population of “regular” players who have a lot of at-bats are generally much better hitters (higher mean) than the population of all hitters who had at least one AB. In addition, the talent distribution of these regular hitters is much tighter (smaller standard deviation) than the talent distribution of all hitters.

The point is that it matters which batters we include in our modeling. The value of a player’s AB actually tells us something about his batting average.

Predicting Strikeout Rates

When one looks at batting rates of a group of hitters there are two sources of variation. Hitters have different talents, that is, there is variation that one sees in the spread of the talent curve. In addition, one has the binomial variation in estimating a proportion that sportscasters refer to the sample size effect. One nice aspect of multilevel modeling is that it separates out the two sources of variation. The estimate of the size of the talent curve variation is relevant for predicting future performance.

Suppose we change the Outcome input in the Shiny app from “H” to “SO”. Comparing the prediction of BAs with the prediction of strikeout rates, we see a dramatic difference in the estimated talent curves. Again looking at all batters, minAB >= 1 and excluding pitcher hitters, here are the means and standard deviation for the respective talent curves:

Hitting rates (BA’s): eta = 0.251, SD = 0.027, K = 264

Strikeout rates: eta = 0.263, SD = 0.071, K = 38

On the surface, the two groups of true rates look similar, since the average values (0.251 and 0.263) are close. But by comparing the SD values, we see the true strikeout rates have much more spread than the true hitting rates. There is a greater range in strikeout talents than batting average talents. These differences in the talent curves impact the predictions. The hitting rates have a large “ballast” value of K = 264 and the BA predictions adjust the observed BAs strongly towards the average. In contrast, the strikeout rates have a small ballast value of K = 38 and the strikeout rate predictions adjust the observed strikeout rates only a small amount towards the average.

Summary: Predicting Francisco Lindor’s 2021 Performance

To summarize some of the points here, let’s look at the current (May 28) batting statistics for the new NY Mets shortstop Francisco Lindor. Looking at Baseball Reference’s page for Lindor, we see that in 157 AB, he currently has 29 hits and 28 strikeouts. So his current BA and strikeout rate are 0.185 and 0.178 respectively. The task is to predict Lindor’s performance for the remainder of the 2021 season.

Without using any extra information about Lindor, I can make reasonable predictions for Lindor’s future performance using the Shiny app.

  • In the app, I choose H, make May 28 the date breakpoint and restrict AB to be at least 150. (I know Lindor is a regular player this season so I choose a large minimum value for AB). I see from the app that the estimated values of eta and K are 0.265 and 728 which means this prior information is equivalent to 193 Hits and 535 Outs. Combining this with Lindor’s observed hits and outs, I obtain a prediction of (29 + 193) / (157 + 728) = 0.251 for his BA in the remainder of the season.
  • To predict his SO rate, I choose SO in the app with the same date breakpoint and minimum number of AB. The estimated values of eta and K are 0.233 and 45 which is equivalent to 10.5 strikeouts and 34.5 non-strikeouts. I predict Lindor’s strikeout rate in the remainder of the season to be (28 + 10.5) / (157 + 45) = 0.190.

What this means is that I don’t really believe Lindor’s .185 AVG is reflective of his batting ability since BAs tend to be chance-driven and so I strongly adjust his BA towards the average for “regular” players. In contrast, I do believe more in his .178 strikeout rate since strikeouts are less chance-driven and my prediction is only a small adjustment towards the average.

Actually, if I was doing this prediction for a MLB team, I would use more information in my prior since Lindor has demonstrated in past seasons as one of the best hitters in baseball. But it is a bit remarkable that I can obtain reasonable predictions using the plain vanilla multilevel model that only assumes that Lindor is one of the regular non-pitchers.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: