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

Несколько показателей

Посчитать по группам сразу несколько итогов: agg со списком функций и именованная агрегация со своими названиями столбцов. Группировка по двум столбцам и результат с индексом из двух уровней.

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

Один показатель редко рассказывает всё. О городе хочется знать и выручку, и число заказов, и средний чек. Можно написать три группировки подряд — а можно одну.

Несколько итогов одного столбца

Метод agg (aggregate, «свести») после группировки принимает список названий функций — строками:

[ ]Сумма, среднее и число значений выручки по городам
import pandas as pd

orders = pd.read_csv("data/shop_orders.csv")
orders["revenue"] = orders["price"] * orders["quantity"]
orders.groupby("city")["revenue"].agg(["sum", "mean", "count"])
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
sum mean count
city
Екатеринбург 423350 1356.891026 312
Казань 440150 1290.762463 341
Москва 1310110 1381.972574 948
Новосибирск 324090 1256.162791 258
Санкт-Петербург 803720 1364.550085 589

Получилась таблица: строки — группы, столбцы — показатели. С ней работают как с любой таблицей:

[ ]Ячейка и столбец результата
stats = orders.groupby("city")["revenue"].agg(["sum", "mean", "count"])
print(stats.loc["Казань", "sum"])
print(stats["mean"].round(1).tolist())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
440150
[1356.9, 1290.8, 1382.0, 1256.2, 1364.6]

Названия функций — те же, что у методов: "sum", "mean", "median", "min", "max", "count", "nunique", "std", "size".

[ ]Упражнение 1Цены по категориям решено

Сохраните в price_stats наименьшую, наибольшую и среднюю цену (price) по каждой категории — столбцы min, max, mean. В widest сохраните название категории с наибольшей разностью между наибольшей и наименьшей ценой.

price_stats = ...
widest = ...

Разные столбцы — свои названия

Чаще показатели считаются по разным столбцам: сумма выручки, число разных заказов, средняя цена. Для этого есть именованная агрегация: в agg перечисляют новые столбцы в виде название=("исходный столбец", "функция").

[ ]Три показателя по трём столбцам
orders.groupby("city").agg(
    total=("revenue", "sum"),
    orders=("order_id", "nunique"),
    avg_price=("price", "mean"),
)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
total orders avg_price
city
Екатеринбург 423350 203 691.153846
Казань 440150 214 719.090909
Москва 1310110 627 695.253165
Новосибирск 324090 163 689.534884
Санкт-Петербург 803720 369 658.981324

Столбец после groupby здесь не выбирают — он указан внутри каждой пары. Названия новых столбцов вы придумываете сами; пишутся они без кавычек, как имена параметров.

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

[ ]Средний чек по городам
cities = orders.groupby("city").agg(total=("revenue", "sum"), orders=("order_id", "nunique"))
cities["check"] = (cities["total"] / cities["orders"]).round(1)
cities.sort_values("check", ascending=False)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
total orders check
city
Санкт-Петербург 803720 369 2178.1
Москва 1310110 627 2089.5
Екатеринбург 423350 203 2085.5
Казань 440150 214 2056.8
Новосибирск 324090 163 1988.3
Вопрос

Что выведет print(orders.groupby("channel")["revenue"].agg(["sum", "mean"]).shape)?

[ ]Упражнение 2Портрет каналов решено

Сохраните в channels таблицу по каналам продаж с тремя столбцами: total — выручка, orders — число разных заказов, buyers — число разных покупателей (customer_id). Добавьте столбец per_buyer — выручка на одного покупателя, округлённая до рублей.

channels = ...
# добавьте в channels столбец per_buyer

Сайт лидирует не только по выручке: каждый его покупатель приносит 7.9 тыс. ₽ против 5.7 тыс. ₽ в приложении и на маркетплейсе.

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

Группировка по двум столбцам

Если передать в groupby список столбцов, группой станет каждое сочетание их значений:

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

Слева теперь два столбца подписей — у индекса два уровня: город и канал. Название города напечатано один раз на всю свою группу строк. Такой индекс называют MultiIndex.

Значение достают по паре меток в круглых скобках. Если указать только первую метку, вернётся вся её группа:

[ ]Одна пара и весь город
print(by_pair.loc[("Казань", "сайт")])
print(by_pair.loc["Казань"])
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
219510
channel
маркетплейс    113670
приложение     106970
сайт           219510
Name: revenue, dtype: int64

Пять городов и три канала дают 15 групп, а сумма по ним — всё та же выручка года. Названия уровней хранит атрибут index.names:

[ ]Групп 15, итог прежний, уровни — city и channel
print(len(by_pair))
print(by_pair.sum())
print(list(by_pair.index.names))
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
15
3301420
['city', 'channel']

Порядок столбцов в списке задаёт порядок уровней: ["city", "channel"] — сначала города, внутри них каналы.

[ ]Упражнение 3Город и категория решено

Сохраните в city_category выручку по каждой паре «город, категория» (сначала город). В moscow — выручку по категориям в Москве, в moscow_tea — выручку от чая в Москве одним числом.

city_category = ...
moscow = ...
moscow_tea = ...

Именованная агрегация работает и с двумя ключами:

[ ]Два ключа и два показателя
orders.groupby(["category", "channel"]).agg(total=("revenue", "sum"), lines=("revenue", "size")).head(6)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
total lines
category channel
Аксессуары маркетплейс 46230 24
приложение 49520 32
сайт 77750 52
Кофе маркетплейс 461000 234
приложение 540520 272
сайт 912920 469

С индексом из двух уровней не всегда удобно работать дальше. Как превратить его в обычные столбцы, разберём в следующем уроке.

[ ]Упражнение 4Климат пяти городов решено

В прошлом модуле мы сравнивали два города и писали всё дважды. Теперь — все пять одной командой. Сохраните в climate таблицу по городам: t_mean — средний temp_max, t_std — его стандартное отклонение, rain — сумма precip_mm. Округлите всю таблицу до одного знака.

weather = pd.read_csv("data/weather.csv")
climate = ...

Итоги

  • .agg(["sum", "mean"]) — несколько итогов одного столбца; результат — таблица.
  • .agg(название=("столбец", "функция"), ...) — показатели по разным столбцам со своими названиями.
  • groupby(["a", "b"]) — группы по сочетаниям; у результата индекс из двух уровней.
  • Значение по двум уровням — результат.loc[("метка a", "метка b")].

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

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