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

Сводные таблицы

pivot_table раскладывает итоги по двум измерениям: одно — в строках, другое — в столбцах. Параметры values, index, columns, aggfunc; среднее по умолчанию; итоги margins и заполнение пустых ячеек fill_value.

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

Группировка по двум столбцам даёт длинный список: «Екатеринбург, маркетплейс — столько-то; Екатеринбург, приложение — столько-то…»

[ ]Пары «город, канал» — списком
import pandas as pd

orders = pd.read_csv("data/shop_orders.csv")
orders["revenue"] = orders["price"] * orders["quantity"]
orders.groupby(["city", "channel"])["revenue"].sum().head(6)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
city          channel
Екатеринбург  маркетплейс     83080
              приложение     150240
              сайт           190030
Казань        маркетплейс    113670
              приложение     106970
              сайт           219510
Name: revenue, dtype: int64

Сравнивать города между собой по такому списку неудобно. Человеку привычнее таблица, где города — в строках, каналы — в столбцах, а на пересечении — число. Это сводная таблица; если вы работали в Excel, вы её знаете.

pivot_table

[ ]Выручка: города × каналы
table = orders.pivot_table(values="revenue", index="city", columns="channel", aggfunc="sum")
table
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
channel маркетплейс приложение сайт
city
Екатеринбург 83080 150240 190030
Казань 113670 106970 219510
Москва 343390 334240 632480
Новосибирск 85650 97200 141240
Санкт-Петербург 250280 213780 339660

Четыре параметра отвечают на четыре вопроса:

  • values — что считаем: столбец с числами;
  • index — что будет в строках;
  • columns — что будет в столбцах;
  • aggfunc — как сворачиваем: "sum", "mean", "count", "nunique", "max"…

По сути это та же группировка по двум ключам — только результат разложен по двум осям. Получилась обычная таблица: города — в индексе, каналы — названия столбцов.

[ ]Ячейка, лучший город сайта, размер
print(table.loc["Казань", "сайт"])
print(table["сайт"].idxmax())
print(table.shape)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
219510
Москва
(5, 3)
[ ]Упражнение 1Категории по городам решено

Сохраните в by_city сводную таблицу выручки: в строках — категории, в столбцах — города. В spb_tea сохраните выручку от чая в Санкт-Петербурге.

by_city = ...
spb_tea = ...

По умолчанию — среднее

Если aggfunc не указать, pivot_table посчитает среднее:

[ ]Без aggfunc
orders.pivot_table(values="revenue", index="city", columns="channel").round(1)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
channel маркетплейс приложение сайт
city
Екатеринбург 1298.1 1517.6 1275.4
Казань 1306.6 1258.5 1298.9
Москва 1436.8 1285.5 1408.6
Новосибирск 1259.6 1185.4 1307.8
Санкт-Петербург 1480.9 1353.0 1296.4

Числа правдоподобные, ошибки нет — а это не выручка, а средняя выручка строки.

Вопрос
small = pd.DataFrame({"city": ["Омск", "Омск", "Тула"], "cups": [10, 30, 5]})
print(small.pivot_table(values="cups", index="city").loc["Омск", "cups"])

Что выведет этот код?

Итоги по строкам и столбцам

Параметр margins=True добавляет итоговую строку и итоговый столбец; margins_name задаёт их название (по умолчанию — All):

[ ]С итогами
orders.pivot_table(values="revenue", index="city", columns="channel", aggfunc="sum", margins=True, margins_name="Всего")
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
channel маркетплейс приложение сайт Всего
city
Екатеринбург 83080 150240 190030 423350
Казань 113670 106970 219510 440150
Москва 343390 334240 632480 1310110
Новосибирск 85650 97200 141240 324090
Санкт-Петербург 250280 213780 339660 803720
Всего 876070 902430 1522920 3301420

В правом нижнем углу — общий итог: знакомые 3 301 420 ₽.

[ ]Упражнение 2Сколько штук продано решено

Сохраните в items сводную таблицу числа проданных штук (quantity): категории в строках, каналы в столбцах, с итогами под названием «Всего». В site_share сохраните долю сайта в общем числе проданных штук — посчитайте её по ячейкам items.

items = ...
site_share = ...

Пустые ячейки

Если какого-то сочетания в данных нет, в ячейке будет пропуск. Посмотрим на аксессуары по месяцам и городам:

[ ]Аксессуары: месяцы × города
orders["month"] = pd.to_datetime(orders["date"]).dt.month
gadgets = orders[orders["category"] == "Аксессуары"]
gadgets.pivot_table(values="revenue", index="month", columns="city", aggfunc="sum").head(4)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
city Екатеринбург Казань Москва Новосибирск Санкт-Петербург
month
1 NaN 8700.0 7360.0 2300.0 4830.0
2 480.0 NaN 9900.0 NaN NaN
3 1630.0 4600.0 960.0 480.0 720.0
4 9420.0 9600.0 3980.0 NaN 6460.0

В январе в Екатеринбурге аксессуаров не покупали — и на этом месте NaN. Из-за пропусков вся таблица стала дробной. Параметр fill_value подставляет значение в пустые ячейки:

[ ]Ноль вместо пропуска
gadgets.pivot_table(values="revenue", index="month", columns="city", aggfunc="sum", fill_value=0).head(4)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
city Екатеринбург Казань Москва Новосибирск Санкт-Петербург
month
1 0 8700 7360 2300 4830
2 480 0 9900 0 0
3 1630 4600 960 480 720
4 9420 9600 3980 0 6460

Здесь ноль оправдан: «продаж не было» и значит «выручка ноль». Со средними так делать нельзя: если в группе нет ни одной оценки, её средний балл не ноль, а неизвестен.

[ ]Упражнение 3Сезонность решено

В таблице orders уже есть столбец month. Сохраните в monthly сводную таблицу выручки: месяцы в строках, категории в столбцах. В tea_peak сохраните номер месяца с наибольшей выручкой чая, в december_top — название категории с наибольшей выручкой в декабре.

monthly = ...
tea_peak = ...
december_top = ...

Строка и столбец сводной таблицы — обычные Series, и idxmax работает с обоими: для столбца возвращает метку строки, для строки — название столбца.

Средние баллы

Сводные таблицы удобны не только для сумм. В файле data/grades.csv — оценки 30 студентов трёх групп по пяти предметам за два семестра, по строке на каждую оценку:

[ ]Ведомость
grades = pd.read_csv("data/grades.csv")
grades.head(4)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
student group subject term score
0 Анна А. ИТ-21 Математика 1 68
1 Анна А. ИТ-21 Математика 2 71
2 Анна А. ИТ-21 Физика 1 49
3 Анна А. ИТ-21 Физика 2 60
[ ]Упражнение 4Группы и предметы решено

Сохраните в group_subject сводную таблицу средних баллов (score): группы в строках, предметы в столбцах, округление до одного знака. В best_subject сохраните предмет, по которому у группы ИТ-22 самый высокий средний балл.

group_subject = ...
best_subject = ...

Итоги

  • таблица.pivot_table(values=..., index=..., columns=..., aggfunc=...) — что считаем, что в строках, что в столбцах и как сворачиваем.
  • Без aggfunc считается среднее — для сумм пишите aggfunc="sum".
  • margins=True добавляет итоги, fill_value заполняет пустые ячейки.
  • Результат — обычная таблица: loc, idxmax, сортировка работают как всегда.

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

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