Variation
Standard Deviation
Compute the sample standard deviation — the square root of the sample
variance. Standard deviation is in the same units as the data, making it
more interpretable than variance. By hand, compute the sample variance
(dividing by n−1) then take the square root. With the library,
statistics.stdev does both steps with the same n−1 denominator.
By hand
With the library
statistics.stdev uses n−1 and matches math.sqrt(statistics.variance(values))
exactly. np.std defaults to ddof=0 (population std) — pass ddof=1
for the sample std. The snapshot shows both numpy variants alongside the
stdlib result to make the ddof trap visible.
naive.py
import math
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
std = math.sqrt(sq_diff / (n - 1))
print('RESULT:', round(std, 10))
library.py
import statistics
import numpy as np
from dalib.display import set_display
set_display()
values = [4, 8, 6, 13, 10, 6, 9]
std_stdlib = float(statistics.stdev(values))
std_np_pop = float(np.std(values))
std_np_samp = float(np.std(values, ddof=1))
print('statistics.stdev:', std_stdlib)
print('np.std (ddof=0): ', round(std_np_pop, 4))
print('np.std (ddof=1): ', std_np_samp)
print('RESULT:', round(std_stdlib, 10))
statistics.stdev: 3.0
np.std (ddof=0): 2.7775
np.std (ddof=1): 3.0
RESULT: 3.0
Implementation notes
np.stddefault isddof=0(population std, divides by n under the square root). Passddof=1whenever you want the sample std from numpy.statistics.stdevalways uses n−1; there is no ddof parameter.- Standard deviation is in the same units as the original values (here, whatever unit the values represent). Variance is in squared units, which is why std is more commonly reported.
- Cross-reference:
sample-variance(this chapter) for the squared version and a detailed explanation of Bessel's correction.