Нашли ошибку?
Скачать чистый
урок 1 из 4≈ 20 минупражнения: 0 из 4

Описательная статистика

Среднее и медиана — когда какое; стандартное отклонение — насколько данные разбросаны; квантили — границы долей; idxmax и idxmin — в какой строке максимум и минимум.

Python запустится при первом выполнении

Таблицу из тысячи строк нельзя удержать в голове — её описывают несколькими числами. Какое значение типично? Насколько остальные от него отличаются? Где крайности? В этом модуле появляется новый набор данных — data/weather.csv: погода в пяти городах за каждый день 2025 года.

[ ]Погода: Москва
import pandas as pd

weather = pd.read_csv("data/weather.csv", parse_dates=["date"])
moscow = weather[weather["city"] == "Москва"]
moscow.head(3)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
date city temp_min temp_max precip_mm wind_ms
0 2025-01-01 Москва -9.9 -3.2 0.0 1.9
1 2025-01-02 Москва -9.7 -3.2 0.0 2.3
2 2025-01-03 Москва -9.0 -3.7 0.0 5.2

temp_min и temp_max — наименьшая и наибольшая температура за сутки, precip_mm — осадки в миллиметрах, wind_ms — ветер в метрах в секунду.

Типичное значение: среднее или медиана

Сколько осадков выпадает в Москве в обычный день?

[ ]Осадки: среднее, медиана и доля сухих дней
rain = moscow["precip_mm"]
print(rain.mean())
print(rain.median())
print((rain.dropna() == 0).mean())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
1.954120879120879
0.0
0.5384615384615384

Среднее — почти 2 мм, а медиана — ноль. Оба числа верны, но отвечают на разные вопросы. Больше половины дней сухие — поэтому «день посередине» без осадков. А среднее учитывает редкие ливни и «размазывает» их по всем дням. (Один день в Москве без данных об осадках; в долю сухих дней он не входит — отсюда dropna.)

Медиана устойчива к необычно большим и малым значениям, среднее — нет:

[ ]Зарплаты без директора и с директором
salaries = pd.Series([60, 65, 70, 75, 80])
with_boss = pd.Series([60, 65, 70, 75, 80, 900])
print(salaries.mean(), salaries.median())
print(with_boss.mean(), with_boss.median())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
70.0 70.0
208.33333333333334 72.5

Одно значение 900 подняло среднее с 70 до 208 — и оно перестало описывать кого-либо из шести человек. Медиана сдвинулась с 70 до 72.5. (Когда значений чётное число, посередине оказываются два — медианой считают их среднее: (70 + 75) / 2 = 72.5.)

Практическое правило: если среднее и медиана близки, подойдёт любое. Если заметно расходятся — в данных перекос, и «типичное» значение честнее описывает медиана.

Вопрос

Что выведет print(pd.Series([1, 2, 100]).median())?

[ ]Упражнение 1Типичная строка заказа решено

В revenue — выручка каждой строки таблицы продаж. Сохраните в mean_revenue её среднее, в median_revenue — медиану, а в above_mean — долю строк, где выручка больше средней.

orders = pd.read_csv("data/shop_orders.csv")
revenue = orders["price"] * orders["quantity"]
mean_revenue = ...
median_revenue = ...
above_mean = ...

Среднее — 1349 ₽, медиана — 1080 ₽, и выше среднего всего 39 % строк. Несколько крупных покупок тянут среднее вверх — как директор в примере с зарплатами.

Пояснение с ответом появится, когда решите упражнение «Типичная строка заказа».

Разброс: стандартное отклонение

Два города могут иметь похожую среднюю температуру и совсем разный климат. Насколько значения разбросаны вокруг среднего, показывает стандартное отклонение (standard deviation) — метод std:

[ ]Москва и Сочи: среднее и разброс дневного максимума
sochi = weather[weather["city"] == "Сочи"]
print(moscow["temp_max"].mean(), moscow["temp_max"].std())
print(sochi["temp_max"].mean(), sochi["temp_max"].std())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
9.123013698630135 10.108617078726315
17.724931506849316 6.342617739486737

Грубо говоря, это «типичное расстояние от среднего» (формула сложнее простого среднего расстояния, но смысл тот же). В Сочи дневная температура обычно отличается от средней градусов на шесть, в Москве — на десять. Чем больше число, тем сильнее разброс; ноль — все значения одинаковы:

[ ]Чем дальше значения от среднего, тем больше std
print(pd.Series([10, 10, 10, 10]).std())
print(pd.Series([9, 10, 10, 11]).std())
print(pd.Series([0, 5, 15, 20]).std())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
0.0
0.816496580927726
9.128709291752768

Единицы измерения у std те же, что у данных: градусы, рубли, штуки.

[ ]Упражнение 2Климат Новосибирска решено

Сохраните в novosibirsk строки таблицы weather для Новосибирска. По столбцу temp_max посчитайте: mean_nsk — среднее, std_nsk — стандартное отклонение, range_nsk — размах: разность наибольшего и наименьшего значений.

novosibirsk = ...
mean_nsk = ...
std_nsk = ...
range_nsk = ...

Разброс в Новосибирске — 14 градусов: вдвое больше, чем в Сочи. Это и есть «резко континентальный климат», записанный одним числом.

Пояснение с ответом появится, когда решите упражнение «Климат Новосибирска».

Квантили

Медиана делит данные пополам. Квантиль обобщает эту идею: квантиль 0.75 — значение, ниже которого лежит 75 % данных. Его ещё называют 75-м процентилем.

[ ]Медиана — это квантиль 0.5
print(moscow["temp_max"].quantile(0.5))
print(moscow["temp_max"].quantile(0.75))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
10.1
18.5

В трёх четвертях дней в Москве было не теплее 18.5 градуса. Если передать список, вернётся Series:

[ ]Три квартиля
moscow["temp_max"].quantile([0.25, 0.5, 0.75])
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
0.25    -1.2
0.50    10.1
0.75    18.5
Name: temp_max, dtype: float64

Это те же 25%, 50% и 75%, что показывает describe. Их называют квартилями: они делят данные на четыре равные части.

[ ]Упражнение 3Самые тёплые дни решено

Сохраните в q90 квантиль 0.9 столбца temp_max таблицы moscow. В hot_days — дни, когда было строго теплее этого значения, в n_hot — их число.

q90 = ...
hot_days = ...
n_hot = ...

Где максимум

max отвечает «сколько», но не «когда». Метку строки с наибольшим значением возвращает idxmax (index of maximum), с наименьшим — idxmin. По метке loc достаёт всю строку:

[ ]Самый тёплый день в Москве
label = moscow["temp_max"].idxmax()
print(label)
moscow.loc[label]
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
196
date         2025-07-16 00:00:00
city                      Москва
temp_min                    21.8
temp_max                    27.2
precip_mm                    9.5
wind_ms                      2.2
Name: 196, dtype: object

Метка 196 — это 16 июля: метки достались таблице moscow от полной таблицы weather. Поэтому нужен именно loc, а не iloc.

Статистика по нескольким столбцам

Все эти методы есть и у таблицы — считают по каждому столбцу:

[ ]Средние по четырём столбцам
moscow[["temp_min", "temp_max", "precip_mm", "wind_ms"]].mean()
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
temp_min     3.603288
temp_max     9.123014
precip_mm    1.954121
wind_ms      3.823836
dtype: float64

Но только если все выбранные столбцы числовые. В таблице moscow есть текстовый столбец city:

[ ]Среднее по таблице с текстомошибка: TypeError
moscow.mean()
Ошибкасохранённый · нажмите «Выполнить», чтобы получить свой
TypeError: Cannot perform reduction 'mean' with string dtype
[ ]Упражнение 4Рекорды Москвы решено

Сохраните в coldest_label метку строки таблицы moscow с самой низкой температурой temp_min, в coldest_date — дату этого дня. В windiest сохраните целиком строку самого ветреного дня (наибольший wind_ms).

coldest_label = ...
coldest_date = ...
windiest = ...

Итоги

  • Среднее чувствительно к крайним значениям, медиана — нет; если они расходятся, смотрите на медиану.
  • std() — стандартное отклонение: насколько значения разбросаны вокруг среднего.
  • quantile(q) — значение, ниже которого лежит доля q данных; quantile(0.5) — медиана.
  • idxmax(), idxmin() — метка строки с наибольшим и наименьшим значением; строку достаёт loc.

Подробнее в справочнике

Нашли ошибку?