Home / Blog / Math & Scientific

Math & Scientific

Calculate Z Scores in Python with a Clear SD Convention

Calculate z scores with Python statistics or SciPy, choose population or sample scaling, validate inputs, and reuse a fixed reference for new values.

Calculate Z Scores in Python with a Clear SD Convention

Choose the reference before choosing a function

A z score is (value−reference mean)/reference standard deviation. In code, decide whether the reference is an entire supplied dataset, a sample estimate or a separately specified population. Standardizing a dataset against its own mean is different from scoring new observations against a reference fitted earlier. Record the standard-deviation convention alongside the result, because population scaling divides the squared deviations by n while sample scaling uses n−1. Two programs can use the same data and produce different valid scores when those conventions differ.

Use the standard library for a small explicit example

The code below treats [10,12,14] as the complete reference population. Its mean is 12 and population standard deviation is sqrt(8/3), approximately 1.632993162. The standardized values are approximately −1.224744871,0 and 1.224744871. The finite-number check rejects NaN and infinity, and the zero-spread guard prevents division by zero. The example deliberately uses numeric observations rather than silently converting arbitrary text fields into numbers; parse and validate imported data according to its source first.

from math import isfinite
from statistics import mean, pstdev

data = [10.0, 12.0, 14.0]
if not data or not all(isfinite(x) for x in data):
    raise ValueError("Use nonempty finite numeric data")
mu = mean(data)
sd = pstdev(data)
if sd == 0:
    raise ValueError("Reference spread must be positive")
scores = [(x - mu) / sd for x in data]
print([round(z, 9) for z in scores])
# [-1.224744871, 0.0, 1.224744871]

Change the denominator deliberately for a sample

For the same three values, the sample standard deviation is 2 because the sum of squared deviations 8 is divided by n−1=2. Replacing pstdev(data) with stdev(data) therefore gives scores −1,0 and1. A sample standard deviation needs at least two observations. Neither convention is chosen by the word z alone; the question or analysis plan must specify the reference. State which function was used so a reviewer can reconcile a difference with a spreadsheet or another statistics library.

Apply a previously fitted reference to new values

If the agreed reference mean is 12 and standard deviation is 2, new values 16 and 8 have scores 2 and −2. The second code example applies those fixed reference parameters rather than refitting them with the new observations included. Enter value 16, mean 12 and SD 2 in the local form, then change the value to 8, to verify both signs. Recomputing a mean from [16,8] happens to give 12 here, but refitting spread would change the comparison and is not generally equivalent.

reference_mean = 12.0
reference_sd = 2.0
new_values = [16.0, 8.0]
scores = [
    (x - reference_mean) / reference_sd
    for x in new_values
]
print(scores)  # [2.0, -2.0]

Use SciPy with explicit options when it is available

SciPy’s stats.zscore accepts ddof, axis and nan_policy options. Its default ddof is 0, corresponding to population-style scaling of the supplied array. Set ddof=1 when the intended denominator is n−1. For a table, axis=0 standardizes columns separately, whereas axis=1 standardizes rows; these answer different questions. The shown call makes ddof and NaN handling explicit. SciPy is a separate dependency, so the standard-library example remains usable without installing it.

from scipy.stats import zscore

scores = zscore(
    [10.0, 12.0, 14.0],
    ddof=1,
    nan_policy="raise",
)
print(scores)  # [-1.  0.  1.]

Decide how missing observations should be handled

Dropping a missing value changes both the reference size and potentially its centre and spread. Replacing a missing observation with zero also changes the data and should not happen merely to satisfy a numeric input requirement. Reject, omit or impute values only according to the stated data procedure, and report that choice. The examples here reject non-finite values to make the result reproducible. If an application uses omission, verify how an entirely missing or constant column is represented in its output.

Check the result without assuming normality

For scores computed against the same population mean and population standard deviation, their mean should be near zero and their population standard deviation near one, subject to rounding. Sample-standardized scores instead have sample standard deviation one. These identities are useful implementation checks but do not demonstrate a normal distribution. Standardization rescales data; it does not remove skewness, dependence or unusual tails. A normal percentile requires a separate distribution assumption and cumulative-probability calculation.

Preserve reference information with the output

Keep the original values, reference mean, reference spread, ddof or function name, axis and missing-value policy together when storing results. Round only for presentation if later calculations still need the numerical values. For a fixed reference, applying x=mean+z×SD should recover the original observation within floating-point precision. If a score changes after a software rewrite, compare those modelling and preprocessing choices before assuming that the arithmetic formula itself changed.

Calculator for the supported step

The Python examples calculate or apply an explicitly chosen reference. The local browser form checks one value using the same mean and positive standard deviation; it does not run Python, choose an axis or clean a dataset for you.

Open Z Score Calculator

Sources and method

Python: statistics mean, population and sample standard deviation

SciPy: stats.zscore options and conventions