Creating Your Rankings? Start with Z-Scores
One of the greatest fantasy tutorials I’ve ever received came in Jeff Zimmerman and Tanner Bell’s, The Process. In the book, there is a breakdown of two very important valuation systems; standing gains points and z-scores. Our auction calculator, for example, is built around z-scores. For a further dive into both, I highly suggest purchasing a copy of the book. In general, z-scores help us understand how good player A is compared to the rest of the draftable player pool and it can be used as a great jumping-off point for your rankings. I use the word “rankings” because they are not projections and that’s the beauty in z-scores. You are not trying to outsmart projections. Instead, you are using a projection system of your choice to create your rankings. In this post, I’ll be creating z-scores for shortstops in 2022 using Steamer projections.
A z-score is a simple mathematical calculation:
z = (x – μ) / σ
μ = sample mean
x = observation
σ = standard deviation of the sample
In our case, we’re calculating a z-score for each of the relevant 5 x 5 counting stats and I’ll also do it for AB and BB projections since Steamer does predict ABs. In The Process, Zimmerman and Bell go into detail on how to calculate z-scores for rate statistics and I’ll leave you with that. In this post, I’ll just be looking at the following:
R, RBI, SB, HR, PA, and BB.
The first step is to find a player pool of draftable players. I’ll keep it really simple and pretend that I am in a 12-team league and each team can only roster one SS. Obviously, that would be a weird league and you’ll have to adjust those numbers accordingly. For example, if you’re in a 12-team league and your roster has a slot for SS and a slot for a MI, then maybe you want to open the pool up to something like 20 shortstops, knowing that some second basemen will fill in that MI spot. Onward!
Looking at the top 12 shortstops sorted by Steamer WAR (sort by whatever you want), I get a list that looks like this:
| Name | H | R | RBI | SB | HR | PA | BB |
|---|---|---|---|---|---|---|---|
| Fernando Tatis Jr. | 165 | 116 | 107 | 26 | 46 | 677 | 75 |
| Carlos Correa | 149 | 83 | 89 | 1 | 28 | 621 | 70 |
| Wander Franco | 170 | 85 | 84 | 10 | 19 | 651 | 49 |
| Trea Turner | 178 | 104 | 83 | 27 | 25 | 681 | 53 |
| Bo Bichette | 178 | 98 | 96 | 18 | 28 | 668 | 44 |
| Corey Seager | 152 | 85 | 82 | 3 | 25 | 596 | 60 |
| Marcus Semien | 155 | 96 | 84 | 11 | 30 | 681 | 68 |
| Francisco Lindor | 148 | 90 | 90 | 13 | 30 | 667 | 64 |
| Xander Bogaerts | 158 | 85 | 92 | 6 | 25 | 649 | 67 |
| Trevor Story | 143 | 85 | 88 | 20 | 27 | 655 | 59 |
| Gleyber Torres | 149 | 81 | 83 | 14 | 23 | 632 | 64 |
| Oneil Cruz | 115 | 55 | 65 | 14 | 20 | 451 | 31 |
Maybe you don’t like the fact that Oneil Cruz has entered the top 12. Another advantage of this system is that you can move players above or below the cut-off line. Once again, I initially sorted Steamer’s rankings on projected WAR. You can experiment with that. Another viable option would be to sort by projected ABs and exclude them from the z-score calculation. That’s what I like about this system, you get to tinker without having to project.
Now, let’s calculate z-scores. Going back to our equation from above, we can fill it in as such:
RBI_z = (Player RBI Projection – Player Pool RBI Average) / Player Pool RBI Standard Deviation
Bo Bichette looks like this:
RBI_z = (96 – 86.9) / 9.90 = 0.96
Once we do this calculation for each counting stat (which should be done in excel or python or whatever environment can do it with a few clicks), we get an output like this:
| Name | H_Z | R_Z | RBI_Z | SB_Z | HR_Z | PA_Z | BB_Z | $ |
|---|---|---|---|---|---|---|---|---|
| Fernando Tatis Jr. | 0.61 | 1.94 | 2.12 | 1.58 | 2.86 | 0.68 | 1.37 | $11.16 |
| Trea Turner | 1.39 | 1.09 | -0.41 | 1.71 | -0.33 | 0.74 | -0.47 | $3.72 |
| Bo Bichette | 1.39 | 0.67 | 0.96 | 0.56 | 0.13 | 0.53 | -1.23 | $3.01 |
| Marcus Semien | 0.00 | 0.52 | -0.31 | -0.33 | 0.43 | 0.74 | 0.78 | $1.83 |
| Francisco Lindor | -0.42 | 0.10 | 0.33 | -0.07 | 0.43 | 0.51 | 0.45 | $1.33 |
| Trevor Story | -0.73 | -0.25 | 0.11 | 0.82 | -0.03 | 0.32 | 0.03 | $0.27 |
| Xander Bogaerts | 0.18 | -0.25 | 0.54 | -0.96 | -0.33 | 0.22 | 0.70 | $0.10 |
| Carlos Correa | -0.36 | -0.39 | 0.22 | -1.60 | 0.13 | -0.24 | 0.95 | -$1.29 |
| Gleyber Torres | -0.36 | -0.54 | -0.41 | 0.05 | -0.63 | -0.06 | 0.45 | -$1.50 |
| Wander Franco | 0.91 | -0.25 | -0.31 | -0.46 | -1.24 | 0.25 | -0.81 | -$1.91 |
| Corey Seager | -0.18 | -0.25 | -0.52 | -1.35 | -0.33 | -0.65 | 0.11 | -$3.17 |
| Oneil Cruz | -2.42 | -2.37 | -2.31 | 0.05 | -1.09 | -3.03 | -2.31 | -$13.48 |
But, we’re not done! We need to adjust these scores to show that these are all players worth drafting and above replacement value. This is easy enough as we can just look at the last player on the list and mark him as a replacement-level player. We then subtract all of that players’ scores, in this case, Oneil Cruz, in effect zeroing his value out and increasing the value of all the other players to get a final product along with a dollar value that is the sum of all the z-scores:
| Name | H_Z | R_Z | RBI_Z | SB_Z | HR_Z | PA_Z | BB_Z | $ |
|---|---|---|---|---|---|---|---|---|
| Fernando Tatis Jr. | 3.03 | 4.31 | 4.43 | 1.53 | 3.95 | 3.71 | 3.68 | $24.64 |
| Trea Turner | 3.81 | 3.46 | 1.90 | 1.66 | 0.76 | 3.77 | 1.84 | $17.20 |
| Bo Bichette | 3.81 | 3.04 | 3.27 | 0.51 | 1.22 | 3.56 | 1.08 | $16.49 |
| Marcus Semien | 2.42 | 2.89 | 2.00 | -0.38 | 1.52 | 3.77 | 3.09 | $15.31 |
| Francisco Lindor | 2.00 | 2.47 | 2.64 | -0.12 | 1.52 | 3.54 | 2.76 | $14.81 |
| Trevor Story | 1.69 | 2.12 | 2.42 | 0.77 | 1.06 | 3.35 | 2.34 | $13.75 |
| Xander Bogaerts | 2.60 | 2.12 | 2.85 | -1.01 | 0.76 | 3.25 | 3.01 | $13.58 |
| Carlos Correa | 2.06 | 1.98 | 2.53 | -1.65 | 1.22 | 2.79 | 3.26 | $12.19 |
| Gleyber Torres | 2.06 | 1.83 | 1.90 | 0.00 | 0.46 | 2.97 | 2.76 | $11.98 |
| Wander Franco | 3.33 | 2.12 | 2.00 | -0.51 | -0.15 | 3.28 | 1.50 | $11.57 |
| Corey Seager | 2.24 | 2.12 | 1.79 | -1.40 | 0.76 | 2.38 | 2.42 | $10.31 |
| Oneil Cruz | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | $0.00 |
It is once again evermore important to point out that this idea has been around for a long time, it has its downsides and other writers have detailed its uses much, much better than I have done here. It should also be pointed out that these dollar values should not be considered auction values. It would be pretty sweet to get Trea Turner for $17 anywhere. No, these are a jumping-off point for those who like to tinker without thinking they are going to better an established projection system. Do you have a measurement, like barrel rate or O-contact% that you would like to incorporate? Go right ahead, toss in an extra $0.25 for every shortstop above in the top 60 percentiles in whatever stat you like. Again, it’s a jumping-off point. For those who are more inclined to tinker than others, buy Jeff’s book and create your own process that keeps you going through the winter months of cold, baseball-less nights. Reading is good for the brain.
Very interesting. I’ve often tried to figure out how to put a premium on the best of the best players. Certainly something to think about more.
Don’t you subtract out the twelfth highest total for each category rather than whatever the twelfth best player happens to have in each category ?
No, because a player’s value is the sum of his z-scores, hence “replacement value” is the 12th player’s z-score sum. If you took the 12th highest for each category, each player would be above replacement level, as no player is worst in all categories. If you wanted to look at a player’s value in a particular category, you could do it that way, but since a player’s value is inherently tied to all of his z-scores, you do replacement level as Lucas has done here.
Well, based on this article alone, without referring to The Book, what is process for identifying (in the example, e.g.) player pool RBI average? And then, player pool SD from average?
This method should not be done using positional values/variances for reasons brought up every time it is brought up. For example, the same number of SB (above average) shouldn’t be worth more for positions that run less.
Even when done for the entire player pool, using variance to create valuation also has its own problems. I guess this explains why I find the auction calculator here to not be ideal.
While the z-score method is a potentially good way to evaluate players for fantasy purposes, this is not a particularly good way to go about it, for several reasons.
First, while there should probably be a PA cutoff so the means/SDs aren’t skewed by the numerous players with a small number of PA, you should definitely include more than just the number of players to fill out the starting spots. Steamer WAR is almost certainly not a good place to start, since SB are relatively meaningless in the WAR calculation, but fairly valuable in a fantasy setting, and defense is accounted for in the WAR calculation, which literally has zero value in the vast majority of fantasy leagues. For this example, if you include Tim Anderson (13th best Steamer WAR) instead of O’Neill Cruz in this example, Corey Seager is now the replacement level SS and everyone’s overall z-score drops by 7 points.
Second, as others have stated, calculating z-scores for just a single position is not the best choice, since a HR from a catcher counts just as much as a HR from a 1B. The entire player population (defined by whichever playing time cutoff you decide) should be used to calculate the means/SDs.
Third, the replacement player is not the last player to fill lineups, it is the next player, since that is theoretically the player you can pick up for free. The argument could be made that it’s actually lower than that, since some players could theoretically be drafted and kept on the bench the entire season. In conjunction with that, the replacement player should be defined as a $1 player, not a $0 player, since you can’t own a player without spending $1 on them.
Fourth, there is no explanation on what goes into the dollar values. It looks like you simply summed the z-scores after the replacement adjustment. There is a simple equation for calculating dollar values from the replacement adjusted z-scores: (team salary – roster spots)*(# of teams in league)*(player adjusted z-score)/(total adjusted z-score of all above replacement players) + 1. This is the core principal of this method.
I hate to be such a downer, and I’m aware that the article refers to the book, but a lot of what is presented is not best practices, and it could lead people down the wrong path.