Метод groupby в библиотеке pandas¶
groupby — это метод библиотеки pandas для языка программирования Python, реализующий принцип «разделение-применение-объединение» (split-apply-combine) для группировки данных по одному или нескольким ключам с последующим применением агрегирующих функций, преобразований или фильтрации. Метод является одним из ключевых инструментов анализа данных, позволяя выполнять вычисления над подмножествами строк DataFrame или Series без использования явных циклов.
¶Принцип работы
Механизм groupby основан на трёхэтапной парадигме, описанной Хэдли Уикхемом в 2011 году:
- Разделение — исходные данные разбиваются на группы на основе значений одного или нескольких ключей (столбцов, функций или уровней индекса).
- Применение — к каждой группе независимо применяется функция: агрегация (сумма, среднее), трансформация (стандартизация, заполнение пропусков) или фильтрация (отбор по условию).
- Объединение — результаты всех групп комбинируются в итоговую структуру (Series, DataFrame или GroupBy-объект).
Ключевая особенность метода — ленивые вычисления: вызов df.groupby() не выполняет операций немедленно, а лишь создаёт объект DataFrameGroupBy, который хранит правила группировки. Фактическое вычисление происходит при вызове агрегирующего метода, такого как sum(), mean() или agg().
¶Синтаксис и параметры
Базовый синтаксис: DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, observed=False, dropna=True).
Основные параметры:
- by — ключи группировки: имя столбца, список столбцов, Series, функция, применяемая к индексу, или массив значений той же длины, что и ось группировки.
- axis — ось, вдоль которой выполняется группировка (0 — по строкам, 1 — по столбцам).
- level — уровень(и) MultiIndex, если группировка выполняется по индексу.
- as_index — при значении
Trueключи группировки становятся индексом результата; приFalseвозвращаются в виде обычных столбцов. - sort — сортировка групп по ключам; отключение ускоряет вычисления на больших данных.
- dropna — исключение строк с пропущенными значениями в ключах группировки (по умолчанию
True).
¶Агрегирование
Наиболее распространённое применение groupby — расчёт сводных статистик по группам. Встроенные методы агрегации включают sum(), mean(), median(), min(), max(), count(), std(), var(), sem(), first(), last() и nunique().
Для одновременного применения нескольких функций используется метод agg() (аналог aggregate()):
``python df.groupby('category').agg({'price': ['sum', 'mean'], 'quantity': 'count'}) ``
Метод agg() также принимает пользовательские функции, в том числе лямбда-выражения, что обеспечивает гибкость при нестандартных вычислениях. С версии pandas 2.0 появилась возможность использовать именованные агрегации через namedagg, позволяющие задавать понятные имена результирующим столбцам.
¶Трансформация и фильтрация
В отличие от агрегации, которая уменьшает количество строк, метод transform() возвращает объект той же формы, что и исходный. Это применяется для нормализации данных внутри групп, заполнения пропусков групповыми средними, удаления выбросов или вычисления отклонений от групповых показателей:
``python df['normalized'] = df.groupby('category')['value'].transform(lambda x: (x - x.mean()) / x.std()) ``
Метод filter() позволяет отбирать группы целиком по условию, накладываемому на группу:
``python df.groupby('category').filter(lambda x: x['value'].sum() > 100) ``
Дополнительно доступны методы head(), tail() и nth() для извлечения первых или последних записей каждой группы.
¶Итерация и применение произвольных функций
Объект GroupBy является итерируемым и возвращает пары «ключ группы — подгруппа». Это позволяет вручную обрабатывать каждую группу:
``python for name, group in df.groupby('category'): print(name, group.shape) ``
Метод apply() применяет произвольную функцию к каждой группе и объединяет результаты. Поведение apply() отличается для Series и DataFrame: для DataFrame результат может быть скаляром, Series или DataFrame, что влияет на способ объединения. Следует учитывать, что apply() с пользовательскими функциями работает медленнее векторизованных агрегаций и требует осторожности при использовании из-за неочевидной логики объединения результатов.
¶Работа с несколькими ключами
Группировка по нескольким столбцам создаёт иерархический индекс (MultiIndex) в результате:
``python df.groupby(['region', 'year'])['sales'].sum() ``
Для доступа к подгруппам используется метод get_group(), возвращающий DataFrame конкретной группы. Перекрёстное агрегирование разных столбцов по разным функциям выполняется через словарь в agg(). Сводные таблицы с несколькими измерениями удобнее строить через метод pivot_table(), который является высокоуровневой обёрткой над groupby.
¶Группировка по времени
Для временных рядов groupby часто комбинируют с pd.Grouper, позволяющим группировать по частотам времени:
``python df.groupby(pd.Grouper(key='date', freq='M'))['value'].sum() ``
Такой подход используется для пересэмплирования данных — расчёта сумм, средних или других показателей за день, месяц, квартал или год. Также возможна группировка по компонентам даты через свойство .dt (например, df.groupby(df['date'].dt.month)).
¶Производительность
На больших объёмах данных скорость работы groupby зависит от числа групп, типа ключей и выбранной операции. Рекомендации по оптимизации включают: отключение сортировки (sort=False), использование категориального типа данных для ключей группировки, применение встроенных агрегаций вместо apply(), а также выбор observed=True при группировке по категориальным переменным для исключения пустых групп.
¶Пример использования
Рассмотрим DataFrame с данными о продажах:
```python import pandas as pd
df = pd.DataFrame({ 'store': ['A', 'B', 'A', 'B', 'A', 'B'], 'product': ['phone', 'phone', 'laptop', 'laptop', 'tablet', 'tablet'], 'revenue': [100, 150, 300, 250, 80, 120] })
result = df.groupby('store')['revenue'].sum() print(result) ```
Результат: для магазина A — 480, для B — 520. Для расчёта средней выручки по каждому продукту в каждом магазине используется df.groupby(['store', 'product'])['revenue'].mean().
¶Отличия от SQL GROUP BY
Хотя groupby функционально схож с конструкцией GROUP BY в SQL, существуют различия: в pandas по умолчанию ключи группировки становятся индексом, а не отдельным столбцом (меняется параметром as_index=False); отсутствует встроенный аналог HAVING — вместо него применяется filter(); агрегация не ограничивается скалярными результатами, позволяя возвращать массивы через transform().
¶См. также
- Метод
pivot_table()— построение сводных таблиц на основе groupby. - Метод
resample()— группировка временных рядов по частотам. - Класс
pd.Grouper— задание правил группировки по времени. - Метод
cut()иqcut()— группировка непрерывных значений по интервалам.
}