Variation
Sample Variance
Measure how spread out the data is. Compute the mean, then average the
squared deviations from it — dividing by n−1 (Bessel's correction) to
get an unbiased estimate of the population variance. By hand, two loops:
one for the mean, one for the squared deviations. With the library,
statistics.variance uses the same n−1 denominator.
By hand
First loop: accumulate total to compute mean. Second loop: accumulate
sq_diff = sum((v - mean)**2). Divide by n - 1 (not n) to produce the
sample variance. With n=7 values, mean=8.0, and sq_diff=54.0, the result
is 54 / 6 = 9.0.
values = [4, 8, 6, 13, 10, 6, 9]
n = len(values)
total = 0.0
for v in values:
total = total + v
mean = total / n
sq_diff = 0.0
for v in values:
sq_diff = sq_diff + (v - mean) ** 2
variance = sq_diff / (n - 1)
print('RESULT:', round(variance, 10))
values ← [4, 8, 6, 13, 10, 6, 9]
1values = [4, 8, 6, 13, 10, 6, 9]2n = len(values)values this step[4, 8, 6, 13, 10, 6, 9]valuesn ← 7
1values = [4, 8, 6, 13, 10, 6, 9]2n = len(values)3total = 0.0values this step7ntotal ← 0.0
2n = len(values)3total = 0.04for v in values:values this step0.0totalv ← 4, total ← 4.0
pass 1 of 73total = 0.04for v in values:5 total = total + v6mean = total / nvalues this step4v0.0 → 4.0totalAll 7 passes — pass 1 is the card above pass vtotal1 4 0.0 → 4.0 2 4 → 8 4.0 → 12.0 3 8 → 6 12.0 → 18.0 4 6 → 13 18.0 → 31.0 5 13 → 10 31.0 → 41.0 6 10 → 6 41.0 → 47.0 7 6 → 9 47.0 → 56.0 for v in values:
3total = 0.04for v in values:5 total = total + vmean ← 8.0
5 total = total + v6mean = total / n7sq_diff = 0.0values this step8.0meansq_diff ← 0.0
6mean = total / n7sq_diff = 0.08for v in values:values this step0.0sq_diffv ← 4, sq_diff ← 16.0
pass 1 of 77sq_diff = 0.08for v in values:9 sq_diff = sq_diff + (v - mean) ** 210variance = sq_diff / (n - 1)values this step9 → 4v0.0 → 16.0sq_diffAll 7 passes — pass 1 is the card above pass vsq_diff1 9 → 4 0.0 → 16.0 2 4 → 8 — 3 8 → 6 16.0 → 20.0 4 6 → 13 20.0 → 45.0 5 13 → 10 45.0 → 49.0 6 10 → 6 49.0 → 53.0 7 6 → 9 53.0 → 54.0 for v in values:
7sq_diff = 0.08for v in values:9 sq_diff = sq_diff + (v - mean) ** 2variance ← 9.0
9 sq_diff = sq_diff + (v - mean) ** 210variance = sq_diff / (n - 1)11print('RESULT:', round(variance, 10))values this step9.0variancestdout ← RESULT: 9.0
10variance = sq_diff / (n - 1)11print('RESULT:', round(variance, 10))values this stepRESULT: 9.0stdout
With the library
statistics.variance uses n−1 and matches the naive result exactly.
np.var defaults to ddof=0 (population variance, divides by n) — pass
ddof=1 to get the sample variance. The snapshot shows all three side by
side to make the ddof difference concrete.
import statistics
import numpy as np
from dalib.display import set_display
set_display()
values = [4, 8, 6, 13, 10, 6, 9]
var_stdlib = float(statistics.variance(values))
var_np_pop = float(np.var(values))
var_np_samp = float(np.var(values, ddof=1))
print('statistics.variance:', var_stdlib)
print('np.var (ddof=0): ', round(var_np_pop, 4))
print('np.var (ddof=1): ', var_np_samp)
print('RESULT:', round(var_stdlib, 10))
statistics.variance: 9.0
np.var (ddof=0): 7.7143
np.var (ddof=1): 9.0
RESULT: 9.0
Implementation notes
- Dividing by n−1 instead of n is Bessel's correction: the sample mean slightly underestimates deviations from the true population mean, so shrinking the denominator compensates. Dividing by n gives the population variance, which is correct only when you have the full population.
np.vardefault isddof=0(population). Always passddof=1when you want sample variance from numpy.statistics.variancealways uses n−1; there is no ddof parameter.