Wednesday, July 21, 2021

Rate State Series, pt. 8: Rate Stats for Linear Weights III

This installment will tie up a few miscellaneous loose threads pertaining to rate stats to be used within a linear weights framework. The first relates to R+/PA, which I demonstrated is a “correct” rate stat to be used in this framework; I prefer it to RAA/PA, which produces identical linear differences between players, because it can be meaningfully compared on a ratio basis as well.

One issue with R+/PA for users is that R/PA is not a quantity that most people have intuitive feel for. We could still use RAA/650 PA, or we could use R+/650 PA, or we could convert R+/PA to a “team game basis” (along the lines of the previously discussed runs/25.2 or runs/27 outs) by multiplying by the league PA/G, or a long-term average thereof. As long as it’s a scalar multiplier consistently applied, there’s no real distortion imposed on the results – it’s just a matter of user preference as to which scale should be used.

A thornier issue is the implications of RAA/PA or R+/PA for teams. I have encountered sabermetricians for whom I have a great deal of respect whose ideal rate stat would be equally applicable to individuals and teams. I do not think - for reasons that were discussed earlier in this series - that this is possible. Of everything I’ve asserted in this series, I’m most confident that R/O is the proper rate stat for teams. Applying it to the normal range of major league players causes distortions, which while not disastrous are  too frequent for me to just ignore.

Let’s look at all of the teams in the 1994 AL through these rate stats. For this exercise, we can greatly simplify the calculation of R+/PA – we don’t need to estimate extra PA, we know exactly how many PA each team has generated. We can also calculate RAA simply by using R/O. While we could always look at the number of runs a given run estimator produces for a team, it is also cleaner to just use actual runs scored:

In this case, the rank order using R/O and R+/PA is the same – this does not have to be the case, and I’m a little disappointed it worked out this way as it would have been nice to have a real-life example from this league-season. Again, the fundamental reason why plate appearances are not the correct rate state denominator for teams is that since team plate appearances are solely a function of team OBA, it is of no consequence how many plate appearances they need to produce the same R/O rate as another team. An offense that every inning produced four walks and three outs would score 1/3 R/O, the same as a team that every inning produced one home run and three outs, but the former would score .167 R/PA and the latter .250. In a league where the average team scored 1/6 R/O and .123 R/PA, each would get .5 RAA per inning, but the former would have a R+/PA of .194 and the latter .248.

To make the point again, if we use actual team runs scored or an estimate of team runs created as the starting point for a team rate stat, there is no need to attempt to measure the impact of their PA generation. In fact, making an additional adjustment would be inappropriate double-counting. The team’s totals already incorporate this impact, as the team’s actual plate appearances were a function of their on base average.

What if someone decided they wanted to construct a rate stat that didn’t include any subtraction in the numerator, and instead would just be a positive quality per plate appearance? If you follow this path, you will no longer have a final result expressed in a unit of runs, but perhaps due to your desire for a different scale this is preferable. Or maybe you want a rate stat that can never assume a negative value, as any stat that has a negative linear weight coefficient for an event has the potential to do; as we’ve discussed, even our absolute runs variant of linear weights will produce negative values for pitcher-level hitters. Maybe you want to make one of these alterations and them impose a different scale for some reason.

One way you could do this is to eliminate outs from the LW_RAA/PA equation. If you just ignore them, you will distort all of the values, and be left with a rate stat that is not only unitless, but also is just plain wrong. However, recognizing that outs are simply the complement of the events with the positive coefficients (since we’ve restricted our list of events to mutually exclusive and exhaustive components of plate appearances given our simplified definitions of terms for this series), we could rectify this by just subtracting the absolute run out value from each positive event. To put this in practice, start with our LW_RAA/PA equation:

LW_RAA/PA = (.5069S + .8382D + 1.1695T + 1.4970HR + .3495W - .3150(outs))/PA

Now we will subtract -.3150 from each of the events in the numerator that comprise the complement of outs (again, in this case this is all of the other variables in the numerator) to get a rate stat that for the moment I will call U (for “unitless”, although it’s really just for ease of reference) :

U = (.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W)/PA

This looks weird, since these weights are no longer in units of R or even R+, but what value does it take on for the league average? By definition, LW_RAA/PA for the league is zero, so this resolves to zero for the league:

LW_RAA/PA = (.5069S + .8382D + 1.1695T + 1.4970HR + .3495W - .3150(outs))/PA 

The manipulation we did to get U was just to subtract -.3150*PA from everything, so:

(.5069S + .8382D + 1.1695T + 1.4970HR + .3495W - .3150(outs) - (-.3150*PA) )/PA = (0 + .3150*PA)/PA = .3150

So the league average of U is by definition equal to the negative of the outs coefficient (.3150 for the 1994 AL). So what happens if we compare a player’s U to the league average?

(.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W )/PA – LgU 

multiply U by PA/PA to get

(.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W)/PA – (LgU *PA)/PA

= (.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W – LgU*PA)/PA

plug back in that LgU = .3150 in our case to get:

(.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W – .3150PA)/PA

If we distribute the -.3150 to all of the events already in the numerator that are plate appearances, then the leftover PA are outs, and so we are left with:

(.5069S + .8382D + 1.1695T + 1.4970HR + .3495W - .3150(outs))/PA

So U - LgU = LW_RAA/PA. Even though the coefficients have been manipulated into unitless, non-negative values, U maintains the necessary condition to be a proper rate stat for a linear weight framework because it produces the correct RAA/PA.

Why would someone want to express an equivalent to RAA/PA in these terms? This is not a question that I am qualified to answer, since I don’t personally use this form – but there’s a decent chance that you, as a consumer of baseball analysis circa 2021 have been exposed to it, whether you realize it or not. 

Since U is now unitless, one might wish to manipulate it in order to put it on a scale that they find useful, perhaps the scale of a fundamental statistic. If you think about what U is, the numerator includes all on-base events, weighted by their run value – the RAA out coefficient. The denominator is just plate appearances. There is a fundamental statistic that we have been using throughout this series that takes a similar form, except instead of weighting the on-base events, it gives them all an equal weight of one. The fundamental form is the same though:

U = (.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W)/PA

other stat = (S + D + T + HR + W)/PA

The other stat is of course On Base Average. If one were to tweak the numerator coefficients for each event in U, it could be put on the same scale as OBA, but instead of giving each on-base event a weight of one, it would give each on-base event a weight based on its run value. It would be a weighted On Base Average. Enter Tom Tango and wOBA, which is now one of the two most ubiquitous rate stat in general sabermetric use thanks to its prominence at Fangraphs (with the other being OPS+ thanks to Baseball-Reference).

In order to convert what I have called U to wOBA, we just need to multiply it by the ratio between the league OBA and U, or equivalently the ratio between the league OBA and the negative of the LW_RAA out coefficient. For the 1994 AL, the average OBA was .3433 and U is .3150, so the ratio is 1.0896 (I will define V = LgOBA/LgU just for ease of writing formulas) which produces:

wOBA = U*V = (.8219S + 1.1533D + 1.4846T + 1.8210HR + .6646W)/PA*1.0896

wOBA = (.8956S + 1.2566D + 1.6176T + 1.9744HR + .7241W)/PA

I think there is a lack of understanding among even engaged consumers of sabermetric analysis as to what wOBA actually represents, and how it relates to linear weights. I admit that even as someone who is deeply interested in anything related to run estimators or rate stats, as I don’t actively use wOBA, I have to remind myself why it works. I have fielded multiple email questions from people who obviously think much more deeply about the construction of metrics than the average consumer, and they don’t know the connection and don’t find it intuitive.

I don’t consider this is the fault of Tango, who has explained this. Dave Studeman has written a good article explaining this. But for whatever reason it feels like a secret despite the best efforts of the people who are responsible for it.

So I will take a second here and spell out the relationship between the wOBA family of metrics, which includes wOBA, wRC (Weighted Runs Created, which will be equivalent to what we called R+), and wRAA (Weighted RAA, which is equivalent to LW_RAA), and R+/PA and LW_RAA/PA as we’ve discussed in this series. Keep in mind that I am speaking generally about these relationships using the metrics as I have defined them in this series, and not specifically about the implementation at Fangraphs or anywhere else, although the basic relationships hold. Some of the algebraic demonstrations can be simplified.

If you wish to convert wOBA into RAA (which Fangraphs would call wRAA), we’ve already demonstrated that we can compare U directly league U, so when using wOBA instead of U you just need to remember to remove V:

wRAA = (wOBA – LgwOBA)/V * PA

To calculate wRC (which will be equivalent to R+),  you need to add in the league average R/PA times the batter’s PA:

wRC = wRAA + LgR/PA*PA = (wOBA – LgwOBA)/V*PA + LgR/PA*PA = ((wOBA – LgwOBA)/V + LgR/PA)*PA

wOBA can be easily converted to wRAA/PA, which is equal to LW_RAA/PA:


and since R+/PA = LW_RAA/PA + LgR/PA, we can also write:

R+/PA = (wOBA – LgwOBA)/V + LgR/PA

Let’s run a leaderboard using the “w” stats, although we’ve already seen most of these values in different guises:

Personally, I prefer R+/PA to wOBA as a rate stat, as the former is directly comparable both as a difference and a ratio, while the latter has to be manipulated in order to be compared either way – both differences and ratios of wOBA have no intrinsic meaning. However, the advantages of having a scale similar to that of OBA, where no negative values are possible, where each event has a clean positive weight, and the “natural” denominator of plate appearances is used. Tango et. al. also took advantage of its structure to more easily apply statistical techniques in The Book, so there are certainly reasons why a user might prefer it, and it is well-constructed by which I mean that the scaling does not cause issues for derivative metrics as long as you know how to account for it.

Finally, the third loose thread I wanted to address in this post. Prior to introducing wOBA, Tango developed a rate stat version of linear weights he called Linear Weight Ratio. It was somewhat conceptually similar to wOBA in that it sought to eliminate the negative weight for outs. Instead of adding the out value to the positive events in the numerator and thus being able to dispense with the negative value of the out as is the case for wOBA, LWR was constructed by making outs the denominator. In order to make the relationship between the positive events more clear, the value of a single was fixed at 1.0, with the coefficients for the other events defined as the ratio of the LW value for the given event to the LW value for a single. If you let the LW value of a single be s, a double be d, etc., then the formula for LWR is:

LWR = (s/s*S + d/s*D + t/s*T + hr/s*HR + w/s*W)/Outs

Which for our 1994 AL weights of  .5069S + .8382D + 1.1695T + 1.4970HR + .3495W becomes:

LWR = (S + 1.6536D + 2.3072T + 2.9532HR + .6895W)/Outs

If we define “x” as the absolute LW value of the out (-.1076 in this case), there are some very straightforward relationships between LWR and LW_RC/O:

LW_RC/O = s*LWR + x

LWR = (LW_RC/O + x)/s

If we define “y” as the average LW value of the out (-.3150 in this case), we can define similar relationships between LWR and LW_RAA/O:

LW_RAA/O = s*LWR + y

LWR = (LW_RAA/O + y)/s

Of course, LW_RAA is the building block for our “correct” rate stat (be it LW_RAA/PA, R+/PA, or wOBA) for the linear weights framework, so you could with some additional algebra convert LWR to those, although LWR sans manipulation does not meet the differential or ratio comparability standards. 

Wednesday, July 07, 2021

Rate State Series, pt. 7: Rate Stats for Linear Weights II

In the last post, we ended with a dilemma: we have a metric (linear weights RAA/PA) that we believe is correct for a linear framework, but it can’t be compared using ratios. We also have an approach (linear weights RC/O) that produces the right RAA but as a rate is inconsistent with RAA/PA. I asked whether we might be able to make adjustments to one or both of these that would get us to the right place.

Let’s start with trying to manipulate R/O to get a proper rate stat. We know that using R/O for individual players (even when using a linear weights estimate for runs created) overstates their value by treating them as a team with respect to their plate appearance generation. We know that using R/PA fails miserably because it doesn’t account for PA generation at all. What if, instead of trying to manipulate the denominator to get an acceptable rate stat, we attempted to manipulate the numerator?

Linear weight runs created with the “-.1 type out value” doesn’t take into account the extra opportunities created (or not created) for a batter’s teammates by his avoidance of outs, but we could make an explicit adjustment that would take care of this. In part 2, we laid out the math to calculate plate appearances as a function of OBA:

PA/G = (LgO/G)/(1 – OBA)

To compare a player’s rate of PA generation to the league, we can calculate the PA/G he would generate as a team, less the league average. For the sake of simplicity, let’s use the variable X to represent league O/G, and the variable EPA to mean “Extra PA” relative to what would be produced by a hitter with a league average OBA. (What follows is a needless bunch of algebra, but I wanted to demonstrate that the final result is tied back to the equation that relates PA/G, O/G, and OBA):

X/(1 – OBA) – X/(1 – LgOBA) = EPA/G

where “games” are defined as X outs. Since this is the case, we can factor out X from the left side of the equation and divide both sides by X, which converts EPA/G to EPA/Out:

1/(1 – OBA) – 1/(1 – LgOBA) = EPA/O

For ease of notation, I’m going to switch to using O/PA to represent the hitter’s 1/(1 – OBA); the complement of OBA is O/PA, and it’s reciprocal is thus PA/O. I will leave LgOBA as a variable since it is a constant from the perspective of calculating the individual’s PA generation:

PA/O – 1/(1 – LgOBA) = EPA/O

As this is an individual metric, I’d rather express it with a denominator of PA than O, so I will multiply both sides by O/PA to get:

(PA/O – 1/(1 – LgOBA))*O/PA = EPA/PA = 1 – 1/(1 – LgOBA)*(1 – OBA) since O/PA is just 1 – OBA

= 1 – (1 – OBA)/(1 – LgOBA) 

replace 1 with (1 – LgOBA)/(1 – LgOBA) to get:

(1 – LgOBA)/(1 – LgOBA) – (1 – OBA)/(1 – LgOBA) = (1 – LgOBA)*(1 – OBA)/(1 – LgOBA)

= (OBA – LgOBA)/(1 – LgOBA) = EPA/PA

This simple equation yields the number of additional PA generated for a batter per PA, beyond what a batter with a league average OBA would have generated. Of course, if we multiply by PA, we will get the raw number of extra PA generated. As an example, Frank Thomas had a .4921 OBA in a league where the OBA was .3433, and he had 508 PA, so he created an additional 115.1 PA for his team beyond what an average hitter would have contributed:

(.4921 - .3433)/(1 - .3433)*508 = 115.1

In order to use this with our modified R/PA, we need to convert it to runs, which can be done by simply multiplying by the league average of .1363 R/PA to get 15.7. As we’ve computed previously, Thomas had 131.4 LW_RC, which is his direct run contribution as a result of his own PA, but without considering the impact he had on his team by creating additional PA (or, more precisely, on a league average team since the entire linear weights framework we’ve been working with this in this series is built from the league average). That was worth an additional 15.7 runs, so his total run contribution for the numerator was about 147.1 runs.

Before moving on, credit is due to the developer of this approach. This methodology, at least expressed in terms of absolute runs plus the PA impact, was first developed by a poster with the moniker “Sibelius”; if he was not the first, he is certainly the person who introduced me to this concept. Sibelius’ original construct combined this with Jim Furtado’s XR (Extrapolated Runs), so he called it XR+ and the resulting rate XR+/PA. I will be using the more generic R+/PA to describe this metric going forward.

Additionally, Sibelius calculated the “+” portion due to PA generation in a mathematically equivalent but quicker way than I did. This later tripped me up, as I had been influenced by his ideas but approached the problem in the manner I did above, starting from extra PA and converting to runs. Thus I posted it on the board as if it was a new, alternative approach rather than simply a different way of calculating the same thing. My faux paus was quickly pointed out and I gladly concede it, although I personally still find the “proof” above to be the most straightforward way to understand the math. But Sibelius’ calculation is more straightforward and I will use it going forward. Instead of messing around with PA, he jumped straight to outs, calculating the number of outs that the player avoided beyond those an average OBA hitter would have made in the same number of PA. Then he multiplied by the league average R/O to get the runs from PA generation/out avoidance. Six of one, half a dozen of the other as of course R/PA = R/O * (1 – OBA), and so Sibelius' equation for the “+” portion would look like this:


For Thomas, this is (.4921 - .3433)*508*.2075 = 15.7

So our formula for R+/PA will be:

R+/PA = (LW_RC + (OBA – LgOBA)*PA*LgR/O)/PA

Note that this is equivalent to:

R+/PA = LW_RC/PA + (OBA - LgOBA)*LgR/O

In order to compute the associated RAA:

RAA = (R+/PA – LgR/PA)*PA

This works as of course the league average R+/PA is equal to the league average R/PA by definition.

Here are the top and bottom five hitters from the 1994 AL:

The first column for RAA is RAA based on R+/PA, and it is an exact match for LW_RAA. Thus R+/PA meets the necessary condition for being an acceptable rate stat. However, so did R/O. We need to test that it produces the same rank order as LW_RAA/PA beyond these players; a good place to start would be with the cohort of four players who were jumbled in order when looking at RAA/PA and R/O:

Here we get a match in rank order. Of course, looking at fourteen players and finding consistency in their ranking doesn’t prove that there would never be a player for whom the two would not agree. We will need some other approach to demonstrate that.

Let’s leave R+/PA for now and go back to the other approach we were considering, which was making an adjustment to RAA/PA that would allow it to produce meaningful ratio comparisons. The obvious solution is to add the league average R/PA to RAA/PA to get a modified absolute R/PA. After all, RAA/PA  represents an individual’s contribution above average per PA, taking the impact of PA generation into account. Adding back in the league average R/PA will return this to an absolute R/PA basis, that will equal raw R/PA at the league level by definition, and that unlike LW_RC/PA will capture the value of extra PA generated by the batter. We know that by definition it will match RAA, since the difference between an individual and the league average will be equal to RAA/PA (RAA/PA + LgR/PA – LgR/PA).

Here are the top and bottom 5, with “mod R/PA” being the metric we’re discussing (LW_RAA/PA + LgR/PA):

If these figures look familiar, it’s because (with minor rounding discrepancies), they are equal to the R+/PA figures we just calculated. That’s right – all of that algebra to calculate extra plate appearances or outs avoided, and multiply by the league average R/PA or R/O, add back to LW_RC – we could have dispensed with all of it, and just added LgR/PA to LW_RAA/PA.

This is our “proof” that R+/PA as we built it from adjusted absolute runs created meets our criteria for a proper rate stat in a linear weights framework – it’s equivalent to using RAA/PA. The two parallel approaches are not in fact parallel – they are alternative ways of getting to the same place.

To demonstrate why the math works out this way, let’s return to our two linear weights equations from part 1:

LW_RC = .5069S + .8382D + 1.1695T + 1.4970HR + .3495W - .1076(outs)

LW_RAA = .5069S + .8382D + 1.1695T + 1.4970HR + .3495W - .3150(outs)

If we think about everything on a per plate appearance basis and building R+/PA using the RAA/PA + LgR/PA path, what we’re doing is taking the second equation and adding the league average R/PA for every event that corresponds to a plate appearance, which is all of them (in a full blown implementation, where we would be considering non-PA events both in the linear weights formula and the calculation of the PA generation impact, this wouldn’t be as clean). Since the league R/PA is .1363, this results in:

R+ = .6432S + .9745D + 1.3058T + 1.6332HR + .4858W - .1788(outs)

Alternatively, from the Sibelius approach, the plus component can be manipulated to read:

(OBA – LgOBA)*PA*LgR/O = ((H+W)/PA – LgOBA)*PA*LgR/O = (H + W – LgOBA*PA)*LgR/O

Continuing to treat everything on a per PA basis, this is (H + W – LgOBA)*LgR/O

Thus any hit or walk contributes (1 – LgOBA)*LgR/O = LgR/PA = .1363, and each out “contributes” (0 – LgOBA)*LgR/O = -LgOBA*LgR/O = -.3433*.2075 = -.0712. Adding .1363 to the LW_RC value for each event results in the same weights we just found (i.e. .6432 for a single), as the weights for on base events are the same between the LW_RC and LW_RAA equations. The out is now worth -.1076 + -.0712 = -.1788 runs, also the same value. We knew from the results that the two approaches must be equivalent, but I always prefer a “proof” when possible.

At this juncture we reach a philosophical question: should we dispense with the notion of absolute runs created for individuals altogether, and replace it with a R+ approach? In other words, instead of our default way of discussing an individual’s contribution being something like: “Frank Thomas created 131 runs in 508 plate appearances while making 258 outs”, and presenting RC, the rate stat, and some metric compared to a baseline, we could cut to the chase and say “Frank Thomas contributed 147 runs in 508 plate appearances”, with the rate and baselined metric. This approach does away with the need to explicitly think about outs, since their special impact beyond plate appearances has been built in to the 147 R+. It also prevents the awkward situation of having a runs created figure of 131 but no handy denominator with which to convert it to a rate stat without doing a R+ or RAA calculation first. 

There is no right answer, although there certainly is a good case to be made for just reporting Thomas’ runs created as 147, since it limits the likelihood of user-initiated bad math. Call it inertial reasoning if you must, but I still like the idea that the runs created figure is the batter’s direct contribution, and the secondary impact of PA generation is captured when looking at the rate or the baselined stat.