pandas: группировки, соединения и упорядоченные показатели

groupby и transform: групповые признаки на уровне строк и фильтрация групп

Содержание курса

Фильтрация строк по условию на групповом агрегате

До этого момента transform использовался для добавления нового столбца с групповым показателем. Но та же идея — результат той же длины, что исходный DataFrame — открывает второй сценарий: фильтрацию строк по условию на уровне группы, а не на уровне строки.

Представь задачу: есть таблица продаж по магазинам, и нужно оставить только строки из магазинов, чья суммарная выручка превышает пороговое значение. Наивное решение — посчитать groupby('store')['revenue'].agg('sum'), получить сжатую таблицу, отфильтровать там нужные магазины, а потом вернуться к исходному DataFrame и выкинуть строки через merge или isin. Это работает, но требует нескольких шагов.

С transform паттерн короче:

import pandas as pd

df = pd.DataFrame({
    'store': ['A', 'B', 'A', 'C', 'B', 'C', 'A'],
    'revenue': [100, 50, 200, 30, 80, 20, 150]
})

group_sum = df.groupby('store')['revenue'].transform('sum')
mask = group_sum > 200
df_filtered = df.loc[mask]
print(df_filtered)

Вывод:

  store  revenue
0     A      100
2     A      200
6     A      150

Что происходит по шагам. transform('sum') для каждой строки возвращает суммарную выручку её магазина: строки магазина A получают 450, строки B — 130, строки C — 50. Результат — Series длиной 7 с теми же индексами, что у df. Сравнение > 200 превращает её в булевую маску той же длины. df.loc[mask] отбирает только строки, для которых маска истинна, — то есть все строки магазина A.

Ключевое здесь: маска живёт в пространстве строк, а решение принято на уровне группы. Магазины B и C не проходят порог целиком — ни одна их строка не попадает в результат, даже если отдельные транзакции большие. Это именно групповая фильтрация, а не строчная.

Паттерн одинаков для любого агрегата. Хочешь оставить группы, где среднее выше порога — меняешь 'sum' на 'mean' и подбираешь нужный threshold. Хочешь отбросить группы с единственной строкой — transform('count') > 1. Маска в любом случае строится за одно выражение и напрямую передаётся в df.loc без промежуточных таблиц.

Начать заново?

Помощник начнёт новый диалог по этой задаче. Текущая переписка останется в истории до конца срока хранения.

О переписке

Можно приложить до трёх фото PNG, JPEG или WebP по 5 МБ.

Переписка и фото хранятся 90 дней после последнего принятого сообщения. Преподаватель получит доступ к диалогу, когда вы попросите его помочь.

Проверка решения остаётся отдельным действием.