Standardize a feature list to mean 0 and unit variance via (x − mean)/std, where std uses ddof=0 (population std). Three loops: accumulate mean, accumulate variance sum, apply transform. Library: sklearn.preprocessing.StandardScaler ().fit_transform(X). RESULT: standardized list (rounded). CRITICAL: sklearn StandardScaler uses population std (ddof=0), NOT sample std (ddof=1).

By hand

data=[1,2,3,4,5], mean=3.0, population std=√(10/5)=√2≈1.4142 (ddof=0). Each value: (v−3)/1.4142. Standardized: [−1.4142, −0.7071, 0.0, 0.7071, 1.4142].

naive.py
Replay: real traced execution (multi-file project)
import math
data = [1, 2, 3, 4, 5]
n = len(data)
total = 0.0
for v in data:
    total = total + v
mean = total / n
var_sum = 0.0
for v in data:
    var_sum = var_sum + (v - mean) ** 2
std = math.sqrt(var_sum / n)
scaled = []
for v in data:
    scaled.append(round((v - mean) / std, 4))
print('RESULT:', scaled)
  1. import math

    1import math2data = [1, 2, 3, 4, 5]
  2. data ← [1, 2, 3, 4, 5]

    1import math2data = [1, 2, 3, 4, 5]3n = len(data)
    values this step[1, 2, 3, 4, 5]data
  3. n ← 5

    2data = [1, 2, 3, 4, 5]3n = len(data)4total = 0.0
    values this step5n
  4. total ← 0.0

    3n = len(data)4total = 0.05for v in data:
    values this step0.0total
  5. v ← 1, total ← 1.0

    pass 1 of 5
    4total = 0.05for v in data:6    total = total + v7mean = total / n
    values this step1v0.0 1.0total
    All 5 passes — pass 1 is the card above
    passvtotal
    110.0 1.0
    21 21.0 3.0
    32 33.0 6.0
    43 46.0 10.0
    54 510.0 15.0
  6. for v in data:

    4total = 0.05for v in data:6    total = total + v
  7. mean ← 3.0

    6    total = total + v7mean = total / n8var_sum = 0.0
    values this step3.0mean
  8. var_sum ← 0.0

    7mean = total / n8var_sum = 0.09for v in data:
    values this step0.0var_sum
  9. v ← 1, var_sum ← 4.0

    pass 1 of 5
    8var_sum = 0.09for v in data:10    var_sum = var_sum + (v - mean) ** 211std = math.sqrt(var_sum / n)
    values this step5 1v0.0 4.0var_sum
    All 5 passes — pass 1 is the card above
    passvvar_sum
    15 10.0 4.0
    21 24.0 5.0
    32 3
    43 45.0 6.0
    54 56.0 10.0
  10. for v in data:

    8var_sum = 0.09for v in data:10    var_sum = var_sum + (v - mean) ** 2
  11. std ← 1.4142135623730951

    10    var_sum = var_sum + (v - mean) ** 211std = math.sqrt(var_sum / n)12scaled = []
    values this step1.4142135623730951std
  12. scaled ← []

    11std = math.sqrt(var_sum / n)12scaled = []13for v in data:
    values this step[]scaled
  13. v ← 1, scaled ← [-1.4142]

    pass 1 of 5
    12scaled = []13for v in data:14    scaled.append(round((v - mean) / std, 4))15print('RESULT:', scaled)
    values this step5 1v[] [-1.4142]scaled
    All 5 passes — pass 1 is the card above
    passvscaled
    15 1[] [-1.4142]
    21 2[-1.4142] [-1.4142, -0.7071]
    32 3[-1.4142, -0.7071] [-1.4142, -0.7071, 0.0]
    43 4[-1.4142, -0.7071, 0.0] [-1.4142, -0.7071, 0.0, 0.7071]
    54 5[-1.4142, -0.7071, 0.0, 0.7071] [-1.4142, -0.7071, 0.0, 0.7071, 1.4142]
  14. for v in data:

    12scaled = []13for v in data:14    scaled.append(round((v - mean) / std, 4))
  15. stdout ← RESULT: [-1.4142, -0.7071, 0.0, 0.7071, 1.4142]

    14    scaled.append(round((v - mean) / std, 4))15print('RESULT:', scaled)
    values this stepRESULT: [-1.4142, -0.7071, 0.0, 0.7071, 1.4142]stdout

With scikit-learn

StandardScaler().fit_transform(X) computes the same formula with ddof=0 internally. The snapshot shows the learned mean and scale for verification.

library.py
import numpy as np
from sklearn.preprocessing import StandardScaler
from dalib.display import set_display
set_display()

data = [1, 2, 3, 4, 5]
X = np.array(data).reshape(-1, 1)
scaler = StandardScaler()
scaled = [round(v, 4) for v in scaler.fit_transform(X).ravel().tolist()]
print('mean:', round(float(scaler.mean_[0]), 4))
print('std (ddof=0):', round(float(scaler.scale_[0]), 4))
print('RESULT:', scaled)
mean: 3.0
std (ddof=0): 1.4142
RESULT: [-1.4142, -0.7071, 0.0, 0.7071, 1.4142]

Implementation notes

  • ddof trap: StandardScaler uses population std (ddof=0), dividing by n. The z-scores lesson in python-stats ch02 used sample std (ddof=1, dividing by n−1) — the two produce different results for finite samples. Always match the formula to what the library uses when verifying parity.
  • scaler.scale_ equals np.std(data) (ddof=0 default), NOT np.std(data, ddof=1).
  • After standardization the population mean is 0 and population std is 1; the sample std (ddof=1) is slightly above 1 for finite n.
  • Cross-reference: min-max-scale (this chapter) for the [0,1] alternative; z-scores (python-stats ch02) for the ddof=1 variant.