The Updated xStats And Their Year To Year Correlations
Earlier this year I made my first attempt at integrating horizontal and vertical launch angle in addition to exit velocity. As I explained in my first post, I split batted balls into 5 degree by 5 degree launch windows, then split each window into buckets based upon the exit velocity, and in doing so I created an array of buckets that is about 20 units wide, 36 units deep, and 60 units tall. So, in other words, each batted ball could fall into one of 43,000 buckets, give or take. I then found the success rates of each bucket, how many go for singles, doubles, triples, home runs, errors, or outs, and I assigned each ball in the bucket the same probability.
This system has some strengths and quite a few weaknesses. For its strengths, it is easy to implement and debug, the code runs pretty fast (it can classify about 50k batted balls per second while running on a modest computer), and it gave results that both made sense and outperforming similar stats. However, this method draws a hard and firm line between potentially similar batted balls merely because one crossed an arbitrary threshold and landed in an adjacent bucket which could have radically different average success rates. This problem is best expressed visually with a chart for Value Hits.
This chart highlights a number of problems. First, look at that group of balls in deep left field. Those, I believe, are caused by bad or perhaps somehow corrupted Gameday coordinates. Next, look at the clear banding around the field. You see obvious lines where certain high value buckets end and other low value buckets begin. Of note, many of these bands are 10 degrees wide, thus accounting for two windows (remember, the windows are 5 x 5 degrees). Finally, look around the infield and even the shallow outfield, you see a lot of blips in places that perhaps don’t make sense. Are balls hit between home and third base really well hit? I think we can all agree they are not, the system wasn’t correctly accounting for buckets that may have had extremely small sample sizes, and statistical noise became amplified.
To correct for this, I decided to add a lot more buckets with varying sizes and start points. Some of these buckets, rather than being 5 degrees by 5 degrees by 2mph are instead 15 degrees by 15 degrees by 12 mph. Others are 6 degrees by 6 degrees by 5 mph. These buckets were designed to overlap as much as possible, so each batted ball would land in, at minimum, 5 distinct buckets, with each bucket weighted differently to account for its size. Using this method, each batted ball is given a much larger sample size of data to draw from while also weighting data points that are closer to it in each of the 3 dimensions. Also, the code still runs very quickly, which is a nice perk for me when I click go.
Yes, there are other ways of categorizing these batted balls. There are much more sophisticated forms of analysis out there. I’m well aware of that. However, for the moment, this is the method I am using.
To see the change in performance, here is an updated Value Hits chart.
You should see a significant drop in that banding. There is still some, but it is greatly diminished and smoothed out. There’s also much less noise around the field. The infield has been reduced to only a few batted balls, the hardest hit of the bunch. The shallow outfield has been cleaned up as well, while the outfield gaps appear to be filled in a little more. This version, 2.1, was a significant upgrade over version 1, and this is a direct result of using more buckets and weighting their results.
However, there are still a few weird things going on around the field, so I have since moved to a new manner of displaying this data with an upgraded coordinate system. Explaining how these coordinates are calculated is beyond the scope of this article, but it is nice to look at the data without all of these artifacts. Again, this is the same sort of Value Hits chart. This time using the fully up to date calculations, buckets, and coordinate system.
(the dots in this image are larger, so it cannot be compared directly to the other two charts)
So there have been a bunch of changes to xStats over this year, but let’s get down to brass tax. How well is this system working? How well do these stats compare across seasons? Good questions! Obviously, there are only two seasons of data, so this isn’t ideal. In a few years we’ll know more about how this is all working out. With that said, I’ve calculated a number of year on year stat correlations for pitchers and batters, which you can see in the chart below. I’m going to awkwardly squeeze all of this into one chart to save space (and it is sortable!).
Pitchers | Base Correlation | Low Estimate | High Estimate | Batters | Base Correlation | Low Estimate | High Estimate | |
---|---|---|---|---|---|---|---|---|
K% | .709 | .649 | .759 | K% | .793 | .755 | .826 | |
Horizontal Angle | .382 | .284 | .472 | Horizontal Angle | .793 | .754 | .826 | |
xHR | .654 | .587 | .713 | xHR | .773 | .731 | .809 | |
xHR-HR | .626 | .555 | .689 | xHR-HR | .733 | .685 | .775 | |
Vertical Angle | .724 | .667 | .772 | Vertical Angle | .722 | .672 | .765 | |
xOBA | .457 | .365 | .539 | xOBA | .711 | .660 | .756 | |
xSLG | .439 | .346 | .524 | xSLG | .678 | .622 | .727 | |
EV | .448 | .356 | .532 | EV | .668 | .611 | .718 | |
xOBP | .463 | .371 | .545 | xOBP | .655 | .596 | .707 | |
xAVG | .519 | .434 | .595 | xAVG | .652 | .593 | .704 | |
VH% | .264 | .158 | .363 | VH% | .639 | .578 | .693 | |
xOBA-wOBA | .375 | .276 | .466 | xOBA-wOBA | .610 | .546 | .667 | |
HR/TBF | .247 | .141 | .347 | HR/PA | .604 | .539 | .661 | |
xBACON | .112 | .002 | .219 | xBACON | .596 | .530 | .654 | |
wOBA | .305 | .202 | .402 | wOBA | .590 | .524 | .650 | |
xSLG-SLG | .349 | .248 | .442 | xSLG-SLG | .586 | .519 | .646 | |
SLG | .287 | .182 | .385 | SLG | .571 | .502 | .632 | |
xOBP-OBP | .407 | .311 | .495 | xOBP-OBP | .567 | .498 | .629 | |
BB% | .469 | .378 | .550 | BB% | .567 | .498 | .629 | |
OBP | .341 | .241 | .435 | OBP | .566 | .496 | .627 | |
HR/FB | .054 | -.057 | .163 | HR/FB | .553 | .482 | .616 | |
xAVG-AVG | .427 | .333 | .513 | xAVG-AVG | .519 | .446 | .586 | |
PH% | .294 | .190 | .391 | PH% | .516 | .442 | .583 | |
AVG | .336 | .235 | .430 | AVG | .510 | .436 | .578 | |
BACON | .067 | -.043 | .176 | BACON | .477 | .399 | .548 | |
xBACON-BACON | .055 | -.055 | .164 | xBACON-BACON | .464 | .385 | .536 | |
xBABIP | .134 | .025 | .241 | xBABIP | .460 | .381 | .533 | |
BABIP | .109 | -.001 | .217 | BABIP | .323 | .234 | .406 | |
xBABIP-BABIP | .068 | -.042 | .177 | xBABIP-BABIP | .319 | .230 | .403 | |
K/9 | .707 | .648 | .758 | |||||
BB/9 | .450 | .357 | .533 | |||||
scFIP | .438 | .345 | .523 | |||||
FIP | .395 | .298 | .484 | |||||
ScFIP-ERA | .338 | .237 | .432 | |||||
FIP-ERA | .322 | .220 | .418 | |||||
ERA | .237 | .130 | .338 | |||||
HR/9 | .231 | .124 | .332 | |||||
RA | .210 | .103 | .313 |
Look at the pitchers side first. On first note, xAVG, xOBP, xSLG, and xOBA are all above their respective traditional stats by varying degrees. xOBA has the largest change, pushing it’s year to year correlation pretty close to FIP.
2015 xStat to 2016 Stat | Correlation | 2015 Stat to 2016 Stat | Correlation | Difference |
---|---|---|---|---|
xAVG-AVG | .427 | AVG | .336 | .091 |
xOBP-OBP | .407 | OBP | .341 | .066 |
xSLG-SLG | .349 | SLG | .287 | .062 |
xBABIP-BABIP | .068 | BABIP | .109 | -.041 |
xBACON-BACON | .055 | BACON | .067 | -.012 |
xOBA-wOBA | .375 | wOBA | .305 | .069 |
Speaking of FIP, scFIP manages to out perform it both in comparing 2015 scFIP to 2016 scFIP and in comparing 2015 scFIP to 2016 ERA. Vertical launch angle leading the chart here as the most stable year to year may surprise a lot of people, it definitely surprised me. However, xHR running up only a slight ways behind K/9 may in fact be the star of the show here. Predicting home runs with Statcast data isn’t especially difficult, and it absolutely appears to transfer year to year better than most other stats.
To the batters side, Again, xAVG, xOBP, xSLG, and xOBA out perform each of their respective traditional cousins. These are each smaller improvements than I’d like to see, and the speed factor I am using for each batter may be a limiting factor here. I’m not particularly happy with the way running speed is implemented, but I haven’t found a better solution.
2015 xStat to 2016 Stat | Correlation | 2015 Stat to 2016 Stat | Correlation | Difference |
---|---|---|---|---|
xAVG-AVG | .519 | AVG | .510 | .009 |
xOBP-OBP | .567 | OBP | .566 | .002 |
xSLG-SLG | .586 | SLG | .571 | .015 |
xBABIP-BABIP | .319 | BABIP | .323 | -.004 |
xBACON-BACON | .464 | BACON | .477 | -.013 |
xOBA-wOBA | .610 | wOBA | .590 | .020 |
Another surprise twist, although perhaps not too surprising, horizontal spray angle is very consistent for batters, much more so than pitchers. That isn’t a huge deal, we all know certain batters are better pull hitters than others. xHR rate is, again, doing exceptionally well with the batters. Exit velocity is also very solid, along with value hits.
Looking through this data, a lot of the xStats appear to hold their own, with the exceptions of xBABIP and xBACON, which both seem to be even worse indicators than the stats they were aiming to address. So, I guess, long story short: predicting hard hit balls is easy, predicting BABIP is hard. You win some, you lose some, right? Back to the drawing board for those two. The rest, they’re doing a good job. We can keep them.
If you wish to use xStats, you can always find them on xStats.org
Andrew Perpetua is the creator of CitiFieldHR.com and xStats.org, and plays around with Statcast data for fun. Follow him on Twitter @AndrewPerpetua.
Great post! Where do you find xHRs for batters on the spreadsheet? I do not seem to be able to locate it. Thanks.
I never thought they would be useful so I never put it in the spreadsheet! Now it is there, though.
Thanks Andrew! Love it. Also, does your xAVG statistic use any speed component for the batter? I know some models will take the batter’s speed in to account but others do not. For example, if Jarrod Dyson and Miguel Montero hit the same exact ball to the shortstop we would expect Dyson to have a better chance of getting a hit due to his speed.
Also, are the xStats park-adjusted or park-neutral? Sorry for all of the questions.
With the exception of the stats that are representative of simple measures (like exit velocity or launch angle) all of the stats involve a speed component. I wrote about it here http://www.fangraphs.com/fantasy/speed-at-last/
I’m still using effectively the same system, but I changed the implementation a tiny bit when I changed how the ball binning process works. It is nearly identical, though. I’m not happy with it, to be honest. I wish I had a better way, but I haven’t thought of one. Ideally I’d have access to something like average run time from home to first, home to second and home to third, but for whatever reason MLB doesn’t make that information public.
Nothing is park adjusted. Or maybe it is adjusted to an average MLB park? I dunno, it averages the success rates based upon similarly hit balls, that’s it. I have found in the past that the stats work best for neutral ball parks like Citi Field, Busch Stadium, and even Kaufman Stadium and not quite as well in the more extreme parks like Coors Field, Chase Field, and even Turner Field.
You may not think of Kauffman as fair or Turner as extreme, and it probably has more to do with the players on the respective ballclubs than park factors, but Turner Field matched up second worst of all the parks when I compared predicted to actual. Coors Field was the worst. Citi Field was the best and was off by maybe a tenth of a percent. Busch did very well, so did Wrigley. Yankee stadium not too bad. Roger’s Centre very poorly.
But this is running off an analysis I did a *very* long time ago, and it may have changed significantly since then given that I now have probably twice as much data and a much more refined algorithm. It may have changed in a huge way since then, I honestly don’t know.