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!).


Year to Year Correlations
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
95% Confidence

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.  

Pitcher Slash Line Correlations
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. 

Batter Slash Line Correlations
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

Andrew Perpetua is the creator of and, and plays around with Statcast data for fun. Follow him on Twitter @AndrewPerpetua.

Newest Most Voted
Inline Feedbacks
View all comments
7 years ago

Great post! Where do you find xHRs for batters on the spreadsheet? I do not seem to be able to locate it. Thanks.

7 years ago

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.

7 years ago
Reply to  RobertoCutch

Also, are the xStats park-adjusted or park-neutral? Sorry for all of the questions.