Z-Scores & Historical Stats

We Can’t Move Forward Without Looking Back.

As part of my process leading up to the next season and the next lot of Redraft rankings, I found it incredibly valuable to first look back at historical seasons and test category ranking formulas.

So I thought rather than keeping the process and all the findings and formulas to myself… why not share with the subreddit. Together we can strengthen the collective knowledge and improve our processes.

I warn you here, this will be very number heavy, and I will start with some basic concepts.
If you are already very confident on these areas, I will provides skip points.

1. Basics of a z-score system.
(Confident in the basics? Please skip to 2.)

A z-score, or standard score, for how we will use it in fantasy, tells you how far a category score is from the average value (mean). It’s measured in standard deviations. This helps us see where a specific category value stands compared to the rest of the league.

The basic formula for z-score:
Z = (Player Category Stat Value − League Average Category Stat Value) / Standard Deviation of Category

Range:

  • Most z-scores will fall within the range of -3 to +3.
  • Approximately 68% of the data will fall within ±1 standard deviation (z-scores between -1 and +1).
  • About 95% will fall within ±2 standard deviations (z-scores between -2 and +2).
  • Nearly 99.7% will fall within ±3 standard deviations (z-scores between -3 and +3).

Practical Implications:

  • In a well-balanced category, a player with a z-score around 0 for a category is performing at the league average.
  • Players with high positive z-scores (e.g., +2, +3) in certain categories are extremely valuable in those areas.
  • Players with high negative z-scores (e.g., -2, -3) may significantly drag down a team’s performance in those categories.
  • Values outside this range are possible, but in most cases should be rare.

2. Flaw 1 of z-score, outliers.
(Not interested in flaws and fixes, just want to see historical results? Please skip to 8.)

The Benefit of a z-score system is it will simply identify stat outliers, however the effect of these on a ranking system is also a major flaw.

If we look at a thread such as : Greatest Single Season Z-Scores (Great work, it just highlights a point)
We see Curry’s 22-23 season identified as a z-score of 3.01. However this is not entirely accurate.

Using the basic formula in 22-23:
Curry’s made 4.9 threes per game,
The entire league average for 22-23 was 0.99 and the standard deviation 0.87.
So Curry’s actual z-score was 4.48 (4.9 threes is a difference of 4.48*0.87 over 0.99).

Just last year, Wembanyama had 3.6 blocks per game, the entire league average for 23-24 was 0.4 and the standard deviation 0.41. giving Wembanyama an actual z-score of 7.74…
The effect of that single z-score would give him a top 5 total z-score rank for the last 20 years…

Impressive, but doesn’t feel right in how we want to use it does it?
Going forward into the era of Wembanyama and increased outliers, its important we can properly calculate rankings.

3. Addressing the Outlier Flaw.

So how can we address this flaw in a clean and easily repeatable way?

A common simple method would be “weighted z-scores”. Simply assigning a weight to each category based on the rarity of the stat.
This may be clean and simple, but deciding the weight of each category is subjective and not applicable to all team builds. Additionally the rarity and importance of stats changes over time. The potential for skewed results is high.

Instead we can reduce outliers by improving the average and standard deviations we are generating for categories.
The above example of a league average blocks per game of 0.4 and standard deviation of 0.41 for 23-24 is in its truest form accurate, but not entirely useful…
This is using a total pool of 557 players, many of whom played less than 5 minutes a game.
Why should the average fantasy player care how much better Wembanyama is then 7 minutes of Kaiser Gates? (Sorry Kaiser…)

So let’s reduce the pool of players used to generate averages and standard deviations.
Your average league size is 12 with rosters of 13, let’s take of 2 spots for streaming thats 132 players.
If we introduce a mpg limit of greater than 28mpg, the league average amount of players to play over 28mpg in the last 20 years is 124 per year, thats very close and allows for some leeway of smaller leagues.

If we introduce the 28mpg limit to the pool of players used to generate averages and standard deviations we now get a z-score for Wembanyama’s 23-24 blocks of 5.5, and for Curry’s 22-23 threes of 3.2. Keeping some of the benefits of the outlier strength whilst not letting it overpower the whole ranking system.

4. Flaw 2 of z-scores, low volume shooting %.

This is a fairly simple idea but often overlooked, good or bad shooting percents mean nothing with no volume. If we generate a basic z-score for fg% of 23-24 it will return Gobert as the strongest result with his 66% fg%, but the more veteran fantasy players amongst you would know Giannis with 61% fg% has a larger benefit for your fantasy team.

This simply comes down to volume, Giannis is taking 18.8fga to Goberts 8.1fga. When added to the sum of your total teams fga and fgm, the more than double makes you are getting from Giannis is a huge difference. Same concept applies ft%.

5. Addressing the volume % Flaw.

The best method I found to moderate the influence of volume on fg%’s (or ft%) was through the use of a logarithmic scale:

((Players fg% – League average fg%) / League Standard deviation fg%)
* (LOG(Players fga + 1) / LOG(League average fga + 1))^Weight factor

The weight factor is a manual influence to increase or decrease the effect of volume. I found a weight of 1.75 for fg% and 2.18 for ft% returned the most useful results.
This, being a manual influence, should have room to be improved. Based on some results seen at the end of this post there can be an argument to increase the weight for fg% volume.

Notes:

  • Remember to keep your 28mpg restriction on averages and standard deviations.
  • One for the accountants among you, never average an average! You should not average the league wide fg%, instead you sum the league wide total fg and dived it by the sum of the league wide fga.

6. Flaw 3 of z-scores, category punts.

A commonly known flaw with z-scores is using all 9 categories to generate a ranking will completely ignore and devalue punt builds.
The example being Giannis with a -6.24 Z-score for FT% will completely negatively skew his overall ranking, whilst in reality his strengths greatly out weigh this in the correct build.
You don’t need to win all 9 Categories.

7. Addressing the category punts flaw.

Luckily for us this flaw has been elegantly addressed by Josh Lloyd with -1 rankings.

Fairly simple, instead of taking the average of all 9 categories, we remove each players worst category and average the remaining 8. Simple and effective.

Are there concepts this doesnt cover like the effectiveness of specialist players?
Yes, but maybe this is one for another day.


8. The fun stuff, what does this system return historically?

I have gathered all seasons since 2001 and calculated per game z-scores for every player to test this and here are some of the results.

2024-25 Top 5:

Name Season Avg Z-Score Minus 1
Joel Embiid 23-24 1.49
Shai Gilgeous-Alexander 23-24 1.22
Nikola Jokic 23-24 1.19
Luka Doncic 23-24 1.18
Anthony Davis 23-24 1.11

Last 20 years Top 5:

Name Season Avg Z-Score Minus 1
Stephen Curry 15-16 1.66
James Harden 18-19 1.61
James Harden 19-20 1.58
Joel Embiid 23-24 1.49
Kevin Durant 12-13 1.44

You may notice Embiid last year comes out as the 4th all time score per game, unfortunately we only got 39 games of it.

Under 21 years of age Top 5:

Name Season Avg Z-Score Minus 1
Anthony Davis 13-14 1.06
LeBron James 04-05 0.97
Victor Wembanyama 23-24 0.96
Kevin Durant 08-09 0.64
Andre Drummond 13-14 0.64

Notice the gap between top 3 and the rest.

Top 5 Category ranks last 20 Years:

Top 5 V3pm:

Name Season V3pm
Stephen Curry 15-16 4.34
Stephen Curry 18-19 3.62
Stephen Curry 20-21 3.45
James Harden 18-19 3.30
Stephen Curry 22-23 3.15

Curry…

Top 5 Vpts:

Name Season Vpts
Kevin Durant 13-14 3.7
James Harden 18-19 3.4
Kobe Bryant 05-06 3.4
Tracy McGrady 02-03 3.2
Allen Iverson 01-02 3.2

Top 5 Vreb:

Name Season Vreb
Andre Drummond 17-18 3.75
Ben Wallace 02-03 3.7
Kevin Love 10-11 3.55
DeAndre Jordan 14-15 3.53
DeAndre Jordan 17-18 3.46

Top 5 Vast:

Name Season Vast
Steve Nash 04-05 3.88
Steve Nash 06-07 3.83
Rajon Rondo 11-12 3.68
Chris Paul 07-08 3.57
Rajon Rondo 15-16 3.57

Top 5 Vstl:

Name Season Vstl
Jacob Gilyard 22-23 5.41
Chris Paul 08-09 4.37
Larry Hughes 04-05 3.97
Chris Paul 07-08 3.74
Allen Iverson 01-02 3.6

Extremely volatile, Gilyard getting it for playing 1 game of 41mins 3 steals… Ideally we weed this out.

Top 5 Vblks:

Name Season Vblk
Serge Ibaka 11-12 6.05
Myles Turner 20-21 5.76
Victor Wembanyama 23-24 5.52
Jaren Jackson Jr. 22-23 4.96
Hassan Whiteside 15-16 4.95

Not to say it to many times but, rookie Wembanyama in under 30mins a night…

Top 5 Vfg%:

Name Season Vfg%
Shaquille O’Neal 02-03 4.3
Shaquille O’Neal 01-02 4.0
Shaquille O’Neal 04-05 4.0
Shaquille O’Neal 03-04 4.0
Shaquille O’Neal 05-06 3.5

The Shaq Cat.

Top 5 Vft%:

Name Season Vft%
Jeremy Lin 17-18 4.25
Kevin Durant 12-13 3.66
Stephen Curry 19-20 3.59
Kevin Durant 09-10 3.51
Peja Stojakovic 03-04 3.1

Lin played 1 game and shot 7/7 from the line, similar from Curry in 19-20… A comparison use of a totals score would address this.


I hope this exercise was able to shed some light on any area of uncertainty, and that the knowledge helps you in the upcoming season!

Is the z-score system perfect?
No, as we approach the new season I suspect we see many attempts at new systems and approaches on how to read the results. Hell, I myself have used twists and introducing extra factors on this with positional and dynasty z-scores.

However, If I may come full circle, the best way to move forward is to first look back.
With a thorough understanding of the formula and the results we can improve our methods.

– Dynasty Hoops HQ!