Help Me Fix My Statcast Charged Batter xHR/FB Rate
Nearly a year ago, I introduced the newest version of my xHR/FB rate, this time using the new Statcast metric, Barrels per Batted Ball Event (Brls/BBE). Along with Brls/BBE, I included two additional components — pulled and opposite field fly ball percentage, which I just lumped together for the second factor in the equation (oh, and also a park factor adjustment).
Since we only had Statcast data going back to 2015, I was unable to formulate the equation using best practices. Typically, I would want to run the data for all years up through Y-1 and then test the equation on the just completed season to avoid overfitting the data. Instead, I had no choice but to use both 2015 and 2016 data with no season to test. Despite the caveats, a regression produced a rather strong formula with an adjusted R-squared 0.6815. Given the simplicity of the formula and the ease of accessing the data and calculating it, this was a success.
Unfortunately, now the leaguewide HR/FB rate surge has thrown a wrench into my equation! Sad face. Let’s dive into a variety of averages from my master xHR/FB rate file:
| Season | # Players | Pull% + Oppo% | Brls/BBE* | Park Adj xHR/FB | HR/FB |
|---|---|---|---|---|---|
| 2015 | 445 | 62.6% | 6.5% | 11.6% | 11.0% |
| 2016 | 438 | 63.1% | 6.4% | 11.6% | 12.2% |
| 2017 | 401 | 63.3% | 6.4% | 11.5% | 13.3% |
Since 2015, we find that Pull% + Oppo% has risen marginally. Keep in mind that this component of the equation has a significantly smaller effect on xHR/FB rate than Brls/BBE. So the increase here is close to meaningless.
On the other hand, Brls/BBE has stood virtually unchanged. Look at the consistency! Given that the two components of xHR/FB rate have remained pretty darn stable, it’s no surprise then to see that the park adjusted xHR/FB rate marks have barely budged. Actually, if you go out to another decimal point, you’ll see that the mark has declined ever so slightly from 2015.
So, Brls/BBE hasn’t moved any in the past three seasons. But check out the HR/FB rate trend, which you’re all no doubt very familiar with! It’s skyrocketed, despite identical xHR/FB rate components! So, that poses a real problem for the equation as it’s now overshooting 2015 numbers, undershooting 2016, and dramatically undershooting 2017.
Yesterday, I discussed what was intended to be a sort of preface to this challenge. From 2016 to 2017, batters are hitting the same rate of barrels, but more of those barrels are flying out of the yard. We haven’t yet identified exactly why, whether it’s a batter change/improvement or the baseball itself, or perhaps some combination of both.
Right now, though, I’m not as concerned with the why. I just want to know how to fix my equation so each season isn’t so wrong.
The first idea I had was to rerun the regression, now including 2017 data. I still won’t have a test season, but the higher rate of barrels going for a homer in 2017 would force the equation to close the gap between HR/FB and xHR/FB in that season. So let’s get into the results:
| Season | Park Adj xHR/FB | HR/FB |
|---|---|---|
| 2015 | 12.2% | 11.0% |
| 2016 | 12.1% | 12.2% |
| 2017 | 12.1% | 13.3% |
The good news: the 2016 xHR/FB rate almost perfectly matches the actual HR/FB rate, and the 2017 expected mark increased by just over half a percent to close the gap with the actual. The bad news: oy vey, now 2015 went from being overshot by a bit to overshot by a lot! And ummmm, despite 2017’s gap closing, it’s still too far off to call it a day and be satisfied.
So what’s an equation creator to do? I close the gap here, while widening the gap there! Should I even be focused on getting all three seasons as close to matching as possible, or simply acknowledge that something changed in 2016 (and maybe even 2017) and accept that there’s not going to be any solution for the time being?
I call on you wonderful readers for help. What do you suggest I do and try? Though I would prefer not to start testing additional components (I’ll probably try incorporating FB% out of curiosity, since intuitively, more fly balls means a greater percentage of BBE could possibly end up in the ideal launch angle range), I am open to any assistance you could provide. This expected metric, along with all my other metrics, drive my Pod Projections, so getting them right is very important to me. Here’s to a weekend of developing the bestest Statcast-charged xHR/FB rate yet!
Mike Podhorzer is the founder of ProjectingX IQ, an advanced fantasy baseball analytics platform that transforms projection data and in-season performance signals into actionable intelligence. He is the 2015 Fantasy Sports Writers Association Baseball Writer of the Year and three-time Tout Wars champion. He is the author of the eBook Projecting X 2.0: How to Forecast Baseball Player Performance, which teaches you how to project players yourself. Follow Mike on X@MikePodhorzer and contact him via email.
My quick thoughts (I’m working on the same thing).
I’d try feature engineering with batted balls between ~16-32 degrees to the pull side. Ditto with balls hit at >97mph (maybe try 100mph too).
So basically breaking the component pieces of barrels down further.
2015 is being thrown off by the extra carry in the 2016 and 2017 balls. Can you try using 2016 data only to predict 2017? Or try 2nd half of 2015 and 2016 to predict 2017.
What’s important tho are those well struck balls in those bins.
All of this is too complex. I want an easy formula that everyone could easily access the data and calculate.
A standard approach to this problem would be to randomly divide the data from all 3 seasons into a training set (typically 70% of the data), which you’d use to build your equation and a test set (the other 30%), which you would use to test your equation. So instead of training the data on 2015 and 2016 data and testing it on 2017, you’d train it on 70% of all seasons and test it on the other 30%.
When doing the regression, you’d add a variable for the year, whose coefficient would make an adjustment based on the season.
The drawback to this approach is that your coefficients will vary depending on which (randomly selected) data points are used for training and which for testing. This is usually handled by repeating the process many times (randomly dividing the data and then building the model) and then averaging across all models.
Yup, cross validation is always a good way to go, I wasn’t sure how nerdy we were going to take this, but that will help.
I can confirm that what you are looking for lies in isolating the balls in the 16-32 degree angles and the balls hit with velocity >97 and >100 (you can choose other break points, it’s just what I’ve been using).
I’m only working with data for fantasy relevant players, and infielders are mostly what’s in my sample so far (because I haven’t completely scraped the statcast data yet), but what I see is in 2015 ~40% of balls hit in that flyball region (most likely to produce HRs) were hit 97mph. Compared to 2016 and 2017 (~43%). From there you see HR/FB in those launch angles go from ~15% in 2015 to ~17% in 2016 to ~19% in 2017.
The launch angles above (32-40 degrees) that are only helpful if you hit the ball really hard (think Paul Goldschmidt) thus I used 100mph as the point there. You’ll see a similar trend.
Interesting, but unfortunately, it doesn’t seem like there’s an easy way to fix the formula without totally diving into the Statcast data, which for this equation, I don’t want to do.
Got it. An easyish fix would be to start splitting out your flyballs on the site like you do for IFFB. HRZFB (home run zone) would just be a subset of all FB. It’s where we’re going…. FB% alone isn’t descriptive enough and I can see how it’s making fantasy players come to confounding conclusions.
What I would do is include league average HR/FB in the regression (either as a constant or as something to multiply brls/bbe by). This isn’t perfect for predictiveness but you can guess the league average for future years. If the reason for the difference is the change in the ball, it wouldn’t effect too much other than the homers (maybe distance as well which could be added).
I like this approach. For 2018, I think it’d be safe to just average the HR/FB% from the past 2yrs (13.25%) for 2018 projections.
You could allow for a random intercept in your model, in this case year. This is how I handle this issue in all my modeling.
https://en.wikipedia.org/wiki/Multilevel_model
Which is basically agreement with other commenters that I should just add a season specific multiplier or integer to get the league xHR/FB to match actual, right?
I suppose that is reasonably similar. The model provides the differences mathematically. I am unsure how much different the results would be if you simply hand calculated the raw differences and applied them after the fact. In certainly would have an significant effect on the variance components of the model but those are probably not of particular interest in this case.
I’m not knowledgeable enough about creating models to know how to set it up to add a different multiplier before the fact. How would I do that?
Agreed with others, the ball changed since 2015, what happens if you exclude 2015 and only use 2016/2017 data to train the model?
Then 2015 would be overshot even more than it is for the 2015/2016 and 2015/2016/2017 equations!
So? Isn’t the point to identify hitters who were lucky/unlucky in recent seasons? 2017 is more important than 2016 which is more important than 2015.
I don’t have the stats or data-scraping chops that some of y’all clearly have, but I will contribute my observations for what they are worth.
(My numbers will be slightly different from Mike’s because I used a 90 BBE cutoff. That gives around 405 hitters per year. Shouldn’t make a meaningful difference.)
We all believe the ball is juiced but… here are the percentages of BBE with 95 MPH+ EV in 2015, ’16 and ’17: 34.3%, 35.4% and 34.1%. I’m no Alan Nathan, but when I think about a juiced ball, I think of the defining characteristic being that it comes off the bat at a higher exit velocity. But the data just does not show that.
Maybe that’s too simplistic. Maybe hitters are doing what Jeff Zimmerman wrote about yesterday: contacting the ball just a bit lower, relative to its center. That would give it more backspin and SHOULD cost of a bit of velocity, BUT… maybe that expected loss of velocity has been exactly offset by the increased bounciness of the ball. That would be a pretty amazing coincidence, but I think it would explain what Mike is seeing: more HR/FB despite no meaningful change in the components of the current xHR/FB formula.
I say that because more backspin without a loss of velocity should result in more distance and therefore more HR/FB, but it wouldn’t change the Pull/Oppo rates. Striking lower on the ball should result in more FB, which we do see. I don’t *think* it would necessarily change Brls/BBE, because some number of batted balls that had launch angles too low to fit the definition of Barrels in earlier seasons would now be hit with higher launch angles, be called Barrels, and replace former Barrels that were now hit too high and lost that designation. The added barrels might just replace the lost barrels, even as average launch angle increased (did it?).
Wasn’t the speculation that balls are simply traveling further given the same EV and launch angle? The seams on the ball changed which led to increased distance. That’s what we’re seeing with the same Brls/BBE, which uses the EV/LA combo, but a rising HR/FB rate.
Yeah nothing about the ball changing should affect EV as far as I know
I feel like there’s another potential explanation that relates to the height of the seams, and what a change there might have done to the distance the ball travels, given identical launch angles, exit velocities and (back)spin rates.
Higher seams = spinning ball grabs more air? = same backspin produces additional distance?
The actual physics are beyond me and we don’t have the spin rate data to analyze it, so there’s probably nothing you can put in your formula to deal with it directly.
Yup, basically my response to the comment above.
It’s not directly applicable to the problem you are trying to solve, but is it possible your park factors are out of date? If you are using the ones from the Guts! page here, they haven’t been updated since 2015. I know these things have changed since then: ATL got a new stadium in 2017, COL raised their fences in some places for 2016, and MIA moved their fences in for 2016. There could be some I missed.
The best source I have found for current, hand-specific, HR park factors is Baseball Prospectus.
I’m using the factors from StatCorner. Didn’t even realize BP had park factors. What baffles me is that different sources could sometimes have wildly different PFs. I get there are different methodologies, but how have we not settled on the best by now, and why would they be so far off? I get a 113 vs a 114 from 2 sources, but not a 101 and 118.
In your xHR/FB article from a year ago, I didn’t understand your explanation for adding pulled and oppo FB% together. They are different types of batted balls that have very different HR rates. HR/FB for pulled balls is around 30 – 35%. For oppo, it’s around 4%.
I might have misunderstood what you wrote, but it kind of seemed like you were conflating barrels with HR, but I don’t think that’s helpful.
When I re-create your xHR/FB study from last year, with 2017 player-seasons included and a 90 BBE cutoff, I get better results by treating FB Pull% and FB Pull% as separate variables, each with its own coefficient. Specifically, this change improves the Adjusted R Square from 0.6841 to 0.6918.
More to the point, MLB has seen a slight decline in oppo flyballs and a larger increase in pulled flyballs (some of which came at the expense of stuff hit up the middle, of course). According to the Splits Leaderboard, for all PA by non-pitchers, among FB, the Pull% since 2015 has climbed from 22.5% to 24.1%. That change alone should have added half a point to the overall HR/FB figure, right?
It’s because we already know the Brls/BBE. For prediction purposes, you are correct that we care much more about pulled FB% and more of those should result in a higher Brls/BBE. But if we already know the Brls/BBE, then all I care about is directionally where on the field they hit it…to the shortest fence distance, which is down the lines.
Initially, I did try running it by separating them and I really debated which way to go. Sadly, I can’t remember exactly why I lumped them together if the R-squared was higher separate.
My article from Wednesday notes the pulled FB% trend, you’re right, it has increased slightly in 2016 and then 2017.
One more silly nit and then I’ll hang up and listen…
Some HR are not FB. During the Statcast era, there have been between 145 and 188 HR on balls BIS classified as LD. These are only around 3% of all homeruns in those years, and they didn’t vary enough in those years to contribute to the phenomenon that has you asking for ideas from the crowd.
But, over the past 16 seasons, batted balls classified here as LD have accounted for anywhere from 1.9% to 13.3% (!) of all HR in a given year. To me, this cautions against attaching excessive meaning to the fact that a particular batted ball or many of them were classified as FB.
Not sure it was you, but I read this comment on another article and it’s crazy! Statcast makes it easier to classify batted balls as it should be a simple formula based on EV and LA. No subjectivity needed.
Wait… I think you might have a plain ol’ data error. It looks to me like the actual Brls/BBE number for 2015 was around 5.5%. In the Wednesday article, that’s what you report. In the article above, you show it as 6.5%. Your footnote acknowledges a change and attributes it to a larger sample, but that doesn’t pass the smell test. First, how much larger would your sample have needed to be to raise the rate that much? Second, presumably the players added to your sample were scrubs who would almost certainly have LOWERED the overall average, not raised it.
In this article, I’m not weighting it by BBE (the first article I summed all the barrels and divided by all the BBE, for this, I just averaged all the Brls/BBE marks), since I didn’t include that number in my file. Prob could have added it though. And maybe it wasn’t clear, but the first article sample size was larger, hence the lower Brls/BBE, which is what you expected.
That’s doesn’t solve everything though because even if it explains the jump from 2015 to 2016, I still need to unexplained jump from 2016 to 2017.
Why are you using barrels instead of component parts (LA/EV)? Could be that barrels/bbe is constant while the average barrel is shifting from a hard hit LD to a hard hit FB, ie the distribution of barrels is shifting even if the total number of barrels remains constant.
Why not use LA/bbe and EV/bbe?
Yup, this was exactly my thought that I believe I kind of alluded to in the post. The problem is then I’d have to run the data on every single batted ball from the Statcast database and do tons of extra work. That’s just to get the improved equation. Then in-season when I’m looking for xHR/FB rate overperformers and underperformers, I’d have to once again run all the batted balls from Statcast. No one would be able to calculate the metric themselves without doing a lot of work, and I want this to be easy to calculate and the data to be easily collectable. It might be at the expense of a point or two of adjusted R-squared, but that’s fine.