Размах, дисперсия и стандартное отклонение
Центр говорит, где данные, а разброс — насколько они кучные или разбросанные. Без разброса картина неполная.
Стандартное отклонение — это, грубо говоря, среднее расстояние от точек до их среднего. Маленькое — данные кучные, большое — разбросанные.
Размах — самая простая мера
Размах (range) — это просто разница между максимумом и минимумом. Он мгновенно говорит, в каком диапазоне лежат данные, но учитывает только две крайние точки и потому очень чувствителен к выбросам.
data = [12, 15, 14, 10, 18, 16]
print("Максимум:", max(data))
print("Минимум:", min(data))
print("Размах:", max(data) - min(data))
Вывод:
Максимум: 18 Минимум: 10 Размах: 8
От идеи к дисперсии
Хочется меры, которая учитывает все точки, а не только края. Логичная идея: посмотреть, насколько каждая точка отклоняется от среднего, и усреднить эти отклонения. Но если просто складывать отклонения, плюсы и минусы взаимно сократятся и сумма всегда даст ноль. Поэтому отклонения возводят в квадрат (убираем знак) и усредняют. Это и есть дисперсия.
Посчитаем дисперсию вручную, по шагам, чтобы увидеть всю кухню.
from statistics import mean
data = [2, 4, 4, 4, 5, 5, 7, 9]
m = mean(data)
print("Среднее:", m)
# Квадраты отклонений от среднего
sq = [(x - m) ** 2 for x in data]
print("Квадраты отклонений:", sq)
# Дисперсия совокупности = средний квадрат отклонения
variance = sum(sq) / len(data)
print("Дисперсия (population):", variance)
Вывод:
Среднее: 5 Квадраты отклонений: [9, 1, 1, 1, 0, 0, 4, 16] Дисперсия (population): 4.0
Стандартное отклонение — возвращаемся к единицам
У дисперсии есть неудобство: она в квадратных единицах (рубли в квадрате?). Чтобы вернуться к исходным единицам, берут квадратный корень из дисперсии — это и есть стандартное отклонение (σ). Его уже можно толковать как «типичное отклонение от среднего».
import math
from statistics import pstdev, pvariance
data = [2, 4, 4, 4, 5, 5, 7, 9]
print("Дисперсия:", pvariance(data))
print("Корень из дисперсии:", math.sqrt(pvariance(data)))
print("pstdev напрямую:", pstdev(data))
Вывод:
Дисперсия: 4 Корень из дисперсии: 2.0 pstdev напрямую: 2.0
Важный нюанс: деление на n или на n−1
В модуле statistics есть две пары функций, и путать их — частая ошибка:
pvariance/pstdev— для всей совокупности, делят наn.variance/stdev— для выборки, делят наn − 1(поправка Бесселя).
Деление на n − 1 чуть увеличивает оценку и компенсирует то, что по выборке мы недооцениваем истинный разброс. На практике вы почти всегда работаете с выборкой, поэтому берите stdev и variance.
from statistics import stdev, pstdev
data = [2, 4, 4, 4, 5, 5, 7, 9]
print("Выборочное (n-1):", round(stdev(data), 3))
print("Для совокупности (n):", round(pstdev(data), 3))
Вывод:
Выборочное (n-1): 2.138 Для совокупности (n): 2.0
Зачем это аналитику
Стандартное отклонение позволяет сравнивать стабильность. Две доставки с одинаковым средним временем 30 минут, но σ = 3 и σ = 15 — это небо и земля: первая предсказуема, вторая то за 15 минут, то за час. Среднее их не различает, а стандартное отклонение — сразу.
Итог
- Размах = максимум − минимум; прост, но смотрит только на края.
- Дисперсия — средний квадрат отклонения от среднего (учитывает все точки).
- Стандартное отклонение = корень из дисперсии, в исходных единицах.
- Для выборки делят на n−1 (
stdev), для совокупности — на n (pstdev).