KajoData / statistics
Z-scores and standard deviations: calculation and interpretation
I explain distance from the mean, show how to check the calculation and identify what a z-score cannot establish about rarity.

A score of 500 looks impressive until we ask how many points were available and how everyone else performed. The same problem appears with support times, order counts and examination results. A number on its own often provides too little context. A z-score expresses a value’s distance from a reference mean in standard deviation units. I like its simplicity, although that simplicity can make an interpretation look more secure than it is.
I will work through a calculation by hand, reproduce it in Python and examine situations where correct arithmetic still produces a misleading conclusion. Every numerical example below uses synthetic data. None describes a real examination, company or team. The question I want to keep visible is straightforward: which reference group and which measure of spread give this result its meaning?
What a z-score actually describes
A z-score tells us how many standard deviations a value lies above or below a selected mean. With a known population mean and a positive population standard deviation, the formula is z = (x - μ) / σ. Here, x is the observation, μ the reference mean and σ the standard deviation. When working with a sample, we often substitute estimates of those parameters. That distinction affects the calculation.
Subtracting the mean places the reference point at zero. A value equal to the mean therefore receives a score of zero. Dividing by the standard deviation then expresses the difference on a common scale. The standard deviation has the same unit as the original data, so points divided by points produce a unitless result. The number tells us about relative distance rather than an absolute difference in points.
A positive sign means above the mean; a negative sign means below it. A score of two is two standard deviations above the reference, while minus half is half a standard deviation below it. The sign does not judge performance. A high number of correct answers might be welcome, whereas a high waiting time might be a problem. The direction of improvement comes from the question being asked.
The example with 500 examination points
Suppose a hypothetical examination has a mean of 300 points, a standard deviation of 50 points and a maximum score of 500. Someone who scores 500 is 200 points above the mean. Dividing 200 by 50 gives four. Their result lies four standard deviations above the mean under the reference parameters we have supplied.
We cannot yet conclude what percentage of people scored less. We have neither the full distribution nor the group size. The examination also has an upper boundary, so an unbounded normal distribution should not be applied without considering whether it is a useful approximation. The arithmetic is valid, but a claim about rarity needs additional information. This is where I separate a calculated result from an interpretation.
With the same mean and standard deviation, a result of 250 has a z-score of minus one, while 350 has a score of plus one. Both are equally distant from the mean on opposite sides. That does not make the difference between 250 and 350 unimportant. It describes that difference relative to the group’s spread, leaving its practical significance to someone who understands the examination.
Calculate the standard deviation by hand
Take eight observations: 2, 4, 4, 4, 5, 5, 7 and 9. For the first calculation, I treat these as the entire population I want to describe. They sum to 40, so the mean is five. Their differences from the mean are minus three, minus one, minus one, minus one, zero, zero, two and four.
Simply adding those differences would make the positive and negative values cancel. To calculate variance, I square them instead. The squared differences are 9, 1, 1, 1, 0, 0, 4 and 16, which sum to 32. Population variance divides that total by eight, giving four. Taking the square root returns to the original unit and gives a standard deviation of two.
I can now divide each difference from the mean by two. Nine receives a score of two; two receives minus one and a half. The table also provides an easy consistency check: all three occurrences of four must receive the same score. If they did not, I would inspect the grouping or the reference parameters used for each row.
| Value | Observations | Z-score |
|---|---|---|
| 2 | 1 | -1.5 |
| 4 | 3 | -0.5 |
| 5 | 2 | 0 |
| 7 | 1 | 1 |
| 9 | 1 | 2 |
The eight resulting scores have a mean of zero and a population standard deviation of one. Those properties follow from transforming this particular dataset using its own mean and positive standard deviation. New observations transformed with the old parameters do not have to average zero. That difference becomes useful when we want to notice a change in a process.
Population and sample calculations
We could instead treat the eight values as a sample from a wider population. The usual sample variance calculation then divides by seven rather than eight. Its variance is 32/7, and its standard deviation is approximately 2.1381. On that scale, nine receives a score of approximately 1.8708. The difference from two is a consequence of the definition, not a broken calculator.
Python makes the distinction explicit: statistics.pstdev calculates population standard deviation, while statistics.stdev calculates sample standard deviation and needs at least two values. The statistics documentation describes both. I would record which calculation a report uses because the phrase “standard deviation” alone leaves this choice unresolved.
I would not choose the denominator after seeing which one pushes an observation over a convenient threshold. First establish the purpose: describing a complete collection, estimating spread in a wider population or preparing a feature for a particular algorithm. For example, scikit-learn’s StandardScaler uses the equivalent of ddof=0. Knowing a tool’s default lets you assess whether it suits the intended task.
Reproduce the calculation in Python
This example uses only Python’s standard library. Run the blocks in order in the same session, or combine them into one script. I start by reproducing the manual calculation. Rounding applies only to displayed values; subsequent operations keep the available precision. That prevents a presentation choice about decimal places from silently changing later calculations.
# example: reference
from math import isclose, isfinite
from statistics import mean, pstdev, stdev
values = [2, 4, 4, 4, 5, 5, 7, 9]
center = mean(values)
scale = pstdev(values)
scores = [(value - center) / scale for value in values]
print(center, scale)
print(scores)
print(round(stdev(values), 4))
The first output line contains five and two. The list is [-1.5, -0.5, -0.5, -0.5, 0.0, 0.0, 1.0, 2.0], and the final number is 2.1381. Before using a file, I would check types, missing values, measurement units and scope. My Python and pandas introduction follows that preparation in more detail. A statistical function cannot infer what an incorrectly recorded measurement was supposed to mean.
Next, I separate the reference parameters from the observation being assessed. The function accepts ordinary integer or floating-point numbers within the range of this exercise. It rejects nonfinite values and a nonpositive scale. It is not a universal validator for every numerical type or extreme numerical range. Its purpose is to make assumptions visible instead of leaving them implicit in the calculation.
# example: scoring
def z_score(value, center, scale):
if not all(isfinite(item) for item in (value, center, scale)):
raise ValueError("Expected finite numbers")
if scale <= 0:
raise ValueError("Scale must be positive")
return (value - center) / scale
print(z_score(500, 300, 50))
print(z_score(11, center, scale))
print(round(z_score(9, center, stdev(values)), 4))
The results are 4.0, 3.0 and 1.8708. Eleven is compared with the existing centre of five and scale of two. It has not automatically been added to the reference data before those parameters are calculated. This separation helps preserve a stable baseline when new observations arrive after the baseline period has ended.
When the division is undefined
If every reference value is five, the standard deviation is zero. Dividing by zero does not provide a meaningful z-score. I would not silently replace the result with zero: that would suggest a valid comparison with an existing scale. Here, the scale itself is missing. I would mark the result as undefined and explain that the reference group has no variation.
An empty collection does not supply a mean, and a single observation does not support sample standard deviation. A missing measurement is not a zero either. If excluding missing records is justified, I record both the rule and the number of observations actually used. Otherwise, readers may compare results calculated from quite different subsets without realising that the reference has changed.
# example: checks
assert isclose(mean(scores), 0.0, abs_tol=1e-12)
assert isclose(pstdev(scores), 1.0)
assert z_score(5, center, scale) == 0
assert z_score(3, center, scale) == -1
assert pstdev([5, 5, 5]) == 0
These checks confirm particular mathematical properties and expected results. They do not demonstrate that the reference group represents the right process. A program can pass every arithmetic check while comparing complex complaint handling with simple information requests. Correct implementation and sensible analytical design need separate attention.
Standardisation does not create a normal distribution
Subtracting a mean and dividing by a positive constant shifts and rescales data. It does not remove asymmetry, clusters or a long tail. If most values were small and a few were very large, that pattern remains after standardisation. The axis changes, while the ordering of observations and their relative spacing stay intact.
A normal distribution has a particular shape; its standard form has mean zero and standard deviation one. Those two numerical properties alone do not make an arbitrary dataset normal. NIST describes the definition and properties. Before interpreting probabilities, I would examine the distribution, for example with a histogram.
A z-score of two does not automatically correspond to the 97.7th percentile of your data. That approximate cumulative percentage comes from a standard normal model. In our eight-observation collection, seven values lie strictly below nine: 87.5%, rather than 97.7%. Ties also require a stated ranking convention. Distance from a mean and position within an ordered collection answer different questions.
Choose the reference group deliberately
Suppose a task takes 12 minutes. In synthetic group A, the mean is eight and the standard deviation is two, giving a z-score of two. In group B, the mean is ten and the standard deviation is four, giving a score of half. The observation has not changed. The comparison attached to it has.
If A contains simple requests and B contains difficult complaints, a combined mean may conceal a useful distinction between processes. However, grouping should follow the question rather than a desired result. Extremely small groups provide little information and unstable reference parameters. I would describe the scope, time period and inclusion rules before calculating the measure.
Across different examinations, similar z-scores describe similar distances from the means of the respective groups. They do not prove equal ability, equal test difficulty or equal measurement quality. Across teams, standardisation does not remove differences in assignments or resources. A shared mathematical unit makes numbers easier to read, but the design of the comparison still needs justification.

Investigate a large score before acting
A rule that deletes everything beyond three standard deviations can remove the events you most need to understand. A large value might reflect an incorrect unit, but it might also record an unusual event accurately. NIST distinguishes flagging a potential outlier from establishing that it is erroneous. A numerical threshold does not perform that investigation.
I would begin with the source record. Was time entered in minutes or seconds? Were several events combined? Does the identifier appear more than once? Then I would examine the process context. If the record is valid, I would retain it and consider a presentation or analytical method that handles extreme values appropriately. Any correction should have a reason another person can follow.
Remember that an extreme observation influences the mean and standard deviation used to calculate its own score. Those parameters are not an independent judge standing outside the data. Especially in a small collection, a threshold can behave differently from an intuition based on a large, stable population. Inspecting the data and applying documented cleaning rules remain part of the work.
Keep the baseline visible over time
When I want to detect change, I retain the baseline period’s parameters and apply them to later values. Recalculating the mean and standard deviation every day moves the ruler each time. Such a score may describe a day’s position within a newly defined group, but that is a different question from deviation relative to the earlier process.
A fixed baseline still needs maintenance. A change in product, season or measurement method may make the old comparison unsuitable. I would document a revised definition and parameter version instead of silently mixing scores from different baselines. In a report, I would keep the original value, reference mean, standard deviation and baseline period alongside the z-score.
For machine learning, scaling parameters are learned from training data and then applied to test data. Estimating them from the complete dataset before splitting can let test information influence model preparation. The scikit-learn guidance on data leakage explains this issue. We are not building a model here, but separating parameter estimation from application is a useful habit from the beginning.
Return to the original unit
A report reader may understand that a score is high without knowing what action it calls for. I therefore return to the measurement unit when presenting the result. Rearranging the formula gives x = μ + z * σ. With our mean of five and standard deviation of two, a score of one and a half corresponds to eight. Reversing the transformation also provides a calculation check: we should recover the original observation within numerical precision.
For a time measurement, the recipient may need minutes of delay, the number of affected cases and a completion deadline alongside a comparison with history. An operational threshold of 15 minutes does not automatically change when the spread of handling times increases. A larger standard deviation can lower the z-score of an unchanged delay. Without the original value, that could resemble an improvement even though the customer waits just as long. Showing both measures makes the distinction visible.
I take similar care when comparing several features. Before adding their scores into one index, I would establish direction, weights and the meaning of the total. Standardisation does not explain why speed should count as much as quality. Two features may also repeat almost the same information, giving it extra influence in the sum. I would initially present the measures separately with brief explanations. A combined score needs an agreed purpose and an examination of how changes in each component affect it.
An exercise in units and interpretation
Multiply all eight observations, the mean and the standard deviation by ten. Predict the score for ninety. Its distance from the new mean is forty, and the new standard deviation is twenty, so the score remains two. This checks whether you understand the role of units and whether your code accidentally combines a rescaled observation with old parameters.
Then score eleven against the existing baseline. Separately, add it to the collection and calculate a new mean and standard deviation before scoring it again. You will get different results because you have asked different questions. In your notes, identify which calculation compares a new measurement with history. Showing two numbers and choosing the more persuasive one would leave the analytical decision unexplained.
Finally, describe the result without symbols: the observed value, its reference group, its distance from the mean and what remains unknown. Those four pieces make a z-score a useful part of an analysis. If all that survives in the report is a number coloured red or green, I would return to the definition of the comparison before recommending an action.
Key takeaways
Does a z-score require a normal distribution?
Calculating distance relative to a mean and positive standard deviation does not. Normality is an additional assumption when using probabilities from a normal model.
What does a negative z-score mean?
The value lies below the selected reference mean. Whether that is desirable depends on what the measurement represents.
What happens when standard deviation is zero?
The z-score is undefined. Mark the case explicitly and inspect the reference group instead of silently substituting zero.
AI was used in an automated way while working on this article. If you want to learn how to do it too, check out this project.
