Разброс
Среднее не говорит, насколько данные «разбросаны». Две группы заказов могут иметь среднее 50, но в одной все заказы 49–51, а в другой от 1 до 99. Для этого есть меры разброса.
Меры разброса
Заголовок раздела «Меры разброса»| Мера | Что это |
|---|---|
| Размах (range) | max − min. Просто, но зависит от двух крайних значений |
| Дисперсия (variance) | Среднее квадрата отклонения от среднего |
Стандартное отклонение (standard deviation, σ или s) | Корень из дисперсии. В тех же единицах, что и данные |
| Перцентиль (percentile) | Значение, ниже которого лежит заданная доля данных. P90 — ниже него 90% данных |
| Квартили | Q1 = P25, Q2 = P50 (медиана), Q3 = P75 |
Стандартное отклонение — главная мера. Если время доставки 48 часов, а σ = 8 часов, то обычно заказ приходит за 48 ± 8 часов.
Как считается стандартное отклонение
Заголовок раздела «Как считается стандартное отклонение»- Для каждого значения возьмите отклонение от среднего:
x − среднее. - Возведите в квадрат.
- Сложите.
- Разделите на
n − 1. Это дисперсия. - Возьмите корень. Это стандартное отклонение.
Пример: данные 2, 4, 6. Среднее 4. Отклонения: −2, 0, 2. Квадраты: 4, 0, 4. Сумма 8. Дисперсия 8 / 2 = 4. Стандартное отклонение 2.
Считаем
Заголовок раздела «Считаем»Подготовка: вы в папке stats-practice.
import csvimport statistics as st
with open("data/orders.csv") as f: orders = list(csv.DictReader(f))
hours = [float(r["delivery_hours"]) for r in orders]
print(min(hours), max(hours), round(max(hours) - min(hours), 1))print(round(st.variance(hours), 2))print(round(st.stdev(hours), 2))
# квартили: 3 точки, делящие данные на 4 частиprint(st.quantiles(hours, n=4, method="inclusive"))Ответ:
21.8 69.9 48.165.588.1[42.8, 48.25, 54.0]method="inclusive" даёт тот же результат, что и SQL. Без этого параметра Python считает чуть иначе.
SELECT min(delivery_hours) AS min_h, max(delivery_hours) AS max_h, round(var_samp(delivery_hours), 2) AS variance, round(stddev_samp(delivery_hours), 2) AS std, quantile_cont(delivery_hours, [0.25, 0.5, 0.75]) AS quartilesFROM orders;Ответ:
min_h max_h variance std quartiles21.8 69.9 65.58 8.1 [42.8, 48.25, 54.0]quantile_cont(x, p) — перцентиль с долей p (0,9 = P90). Можно передать список долей.
Читаем: время доставки в среднем 48 часов, стандартное отклонение 8,1 часа. Половина заказов приходит за 42,8–54 часа (от Q1 до Q3).
Практика
Заголовок раздела «Практика»Задание 1
Заголовок раздела «Задание 1»Посчитайте стандартное отклонение сумм заказов (amount). Сравните его со средним (77,33).
Проверка: 276,83. Оно в 3,5 раза больше среднего. Это признак выбросов.
Решение
Python:
amount = [float(r["amount"]) for r in orders]print(round(st.stdev(amount), 2))SQL:
SELECT round(stddev_samp(amount), 2) FROM orders;Задание 2
Заголовок раздела «Задание 2»Посчитайте стандартное отклонение сумм без заказов дороже 1000. Сколько заказов осталось?
Проверка: 995 заказов, стандартное отклонение 40,82. Пять заказов подняли его с 40,82 до 276,83.
Решение
Python:
rest = [a for a in amount if a <= 1000]print(len(rest), round(st.stdev(rest), 2))SQL:
SELECT count(*), round(stddev_samp(amount), 2)FROM ordersWHERE amount <= 1000;Задание 3
Заголовок раздела «Задание 3»Найдите P90 суммы заказа: значение, ниже которого лежат 90% заказов.
Проверка: 101,75. Девять из десяти заказов дешевле 101,75.
Решение
Python. quantiles(..., n=10) возвращает 9 точек: P10, P20, …, P90. Нам нужна последняя:
deciles = st.quantiles(amount, n=10, method="inclusive")print(round(deciles[-1], 2))SQL:
SELECT quantile_cont(amount, 0.9) FROM orders;Задание 4
Заголовок раздела «Задание 4»В какой срок приходят 90% заказов? Найдите P5 и P95 времени доставки. Это и есть «обычный диапазон».
Проверка: P5 = 34,8 часа, P95 = 61,8 часа. 90% заказов приходят за 35–62 часа.
Решение
SQL:
SELECT quantile_cont(delivery_hours, [0.05, 0.95]) FROM orders;Python:
cuts = st.quantiles(hours, n=100, method="inclusive")print(cuts[4], cuts[94])cuts[4] — это P5, cuts[94] — это P95: индексы идут с нуля.
Задание 5
Заголовок раздела «Задание 5»Для каждого месяца посчитайте число заказов, средний чек и медианный чек.
Проверка:
| месяц | заказов | среднее | медиана |
|---|---|---|---|
| 2024-01 | 334 | 84,47 | 50,18 |
| 2024-02 | 312 | 71,91 | 48,46 |
| 2024-03 | 354 | 75,39 | 44,52 |
Среднее и медиана показывают разную картину. В марте среднее выше, чем в феврале, а медиана — ниже (44,52 против 48,46). Причина — выбросы.
Решение
SELECT strftime(order_date, '%Y-%m') AS month, count(*) AS orders, round(avg(amount), 2) AS mean_amount, round(median(amount), 2) AS median_amountFROM ordersGROUP BY monthORDER BY month;Дальше: Распределения и выбросы.