Функция GroupBy в Pandas: объяснение на примерах
Узнайте, как использовать Pandas GroupBy для обобщения, сравнения и анализа сгруппированных данных на простых и практических примерах.

# Введение
Pandas — одна из самых популярных библиотек Python для анализа данных. Она предоставляет простые инструменты для очистки, преобразования, суммирования и исследования структурированных данных. Одна из самых полезных функций Pandas — это GroupBy . Она помогает отвечать на вопросы, требующие группировки строк по одной или нескольким категориям.
Например, при работе с данными о продажах вам может потребоваться рассчитать общую выручку по регионам, среднюю стоимость заказа по категориям товаров или количество заказов, обработанных каждым торговым представителем. Вместо того чтобы вручную фильтровать каждую категорию по отдельности, функция GroupBy позволяет выполнять эти вычисления простым и эффективным способом.
В этом уроке мы рассмотрим практические примеры использования Pandas GroupBy с небольшим набором данных о продажах. Я использую Deepnote в качестве среды разработки, поэтому некоторые результаты показаны в виде скриншотов блокнота непосредственно под блоками кода.
# Создание тестового набора данных
Перед использованием функции GroupBy мы сначала создадим небольшой набор данных о розничных продажах со столбцами, такими как order_id, region, category, sales_rep, units, unit_price, discount и order_date. Затем мы преобразуем словарь в DataFrame pandas и создадим два новых столбца: gross_sales и net_sales.
data = { «order_id»: [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], «region»: [«Север», «Юг», «Север», «Запад», «Юг», «Запад», «Север», «Юг», «Запад», «Север», «Юг», «Запад», «Север», «Юг», «Запад»], «category»: [«Электроника», «Мебель», «Электроника», «Мебель», «Одежда», «Электроника», «Одежда», «Мебель», «Одежда», «Мебель», «Электроника», «Одежда»], «sales_rep»: [«Айеша», «Билал», «Айеша», «Чен», «Билал», «Чен», «Айеша», «Билал», «Чен», «Айеша», «Билал», «Чен»], «единицы»: [2, 1, 3, 2, 5, 4, 6, 2, 7, 1, 2, 8], «цена за единицу»: [500, 800, 450, 700, 60, 550, 55, 850, 65, 750, 520, 70], «скидка»: [0.05, 0.10, 0.00, 0.08, 0.00, 0.12, 0.05, 0.10, 0.00, 0.07, 0.03, 0.00], «дата заказа»: pd.to_datetime([ «2026-01-05», «2026-01-06», «2026-01-08», «2026-01-10», «2026-01-12», «2026-01-15», «2026-02-02», «2026-02-05», «2026-02-08», «2026-02-12», «2026-02-15», «2026-02-20» ]) } df = pd.DataFrame(data) df[«gross_sales»] = df[«units»] * df[«unit_price»] df[«net_sales»] = df[«gross_sales»] * (1 — df[«discount»]) df
Столбец gross_sales рассчитывается путем умножения количества единиц на цену за единицу, а net_sales корректирует это значение после применения скидки. Это позволяет получить чистый набор данных, который можно использовать во всех примерах группировки.

# Использование базового синтаксиса группировки
Простейшая операция группировки (GroupBy) выполняется по простой схеме: выбирается столбец для группировки, выбирается столбец со значениями и применяется функция агрегирования. В этом примере мы группируем данные по регионам и вычисляем общую сумму чистых продаж для каждого региона.
df.groupby(«region»)[«net_sales»].sum()
Результат показывает, что Север, Юг и Запад имеют свои собственные общие объемы продаж. Это самый простой и распространенный вариант использования функции GroupBy при суммировании данных.
регион Север 3311.0 Юг 3558.8 Запад 4239.0 Имя: net_sales, тип данных: float64
# Использование GroupBy с as_index=False
По умолчанию pandas использует сгруппированный столбец в качестве индекса в выходных данных. Хотя это полезно в некоторых случаях, часто проще работать с обычным DataFrame, где сгруппированный столбец остается обычным столбцом. Именно здесь пригодится параметр as_index=False.
df.groupby(«region», as_index=False)[«net_sales»].sum()
В этом примере мы снова рассчитываем общую чистую выручку по регионам, но результат возвращается в виде чистого DataFrame, который проще экспортировать, объединять или использовать в отчетах.

# Применение нескольких агрегаций к одному столбцу
Функция GroupBy не ограничивается одним вычислением. Вы можете применять несколько агрегирующих функций к одному и тому же столбцу, используя agg().
В этом примере мы вычисляем сумму, среднее значение, минимум, максимум и количество чистых продаж для каждого региона.
Это позволяет нам быстро получить статистическую сводку показателей региональных продаж и сравнить не только общую выручку, но и средний размер заказа и объем заказов.
df.groupby(«region»)[«net_sales»].agg([«sum», «mean», «min», «max», «count»])

# Использование именованных агрегаций
Именованные агрегации упрощают чтение и использование результатов GroupBy. Вместо возврата общих имен столбцов, таких как сумма или среднее значение, мы определяем собственные имена, например, total_sales, average_order_value, total_units и number_of_orders.
Это особенно полезно при подготовке аналитических данных для информационных панелей, отчетов или обучающих материалов, поскольку названия выходных столбцов четко объясняют, что представляет собой каждый показатель.
region_summary = ( df.groupby(«region», as_index=False) .agg( total_sales=(«net_sales», «sum»), average_order_value=(«net_sales», «mean»), total_units=(«units», «sum»), number_of_orders=(«order_id», «count») ) ) region_summary

# Группировка по нескольким столбцам
Вы также можете группировать данные по нескольким столбцам. В этом примере мы группируем данные по региону и категории, чтобы рассчитать общую чистую выручку для каждой категории товаров в каждом регионе.
Это позволяет получить более детальное представление о данных по сравнению с группировкой только по регионам. Многоколоночная группировка полезна, когда необходимо анализировать производительность по различным параметрам, таким как регион и продукт, отдел и сотрудник, или месяц и сегмент клиентов.
df.groupby([«region», «category»], as_index=False)[«net_sales»].sum()

# Сортировка результатов по группировке
После группировки и агрегирования данных часто возникает необходимость отсортировать результаты, чтобы найти самые высокие или самые низкие значения.
В этом примере мы рассчитываем общий объем продаж по категориям товаров, а затем сортируем результаты в порядке убывания.
Это позволяет легко определить, какая категория принесла наибольший доход. Сортировка сгруппированных результатов — простой, но эффективный шаг при преобразовании необработанных сводок в полезные аналитические данные.
category_sales = ( df.groupby(«category», as_index=False) .agg(total_sales=(«net_sales», «sum»)) .sort_values(«total_sales», ascending=False) ) category_sales

# Понимание соотношения количества и размера
В библиотеке Pandas есть функции count() и size(), но они не совсем одинаковы. Метод size() подсчитывает общее количество строк в каждой группе, включая строки с пропущенными значениями. Метод count() подсчитывает только непропущенные значения в выбранном столбце.
В этом примере мы намеренно добавляем пропущенное значение в столбец sales_rep. Результат показывает, что функция size() по-прежнему считает четыре строки для каждого региона, в то время как функция count() возвращает три для Севера, поскольку одно значение sales_rep отсутствует.
import numpy as np df_missing = df.copy() df_missing.loc[2, «sales_rep»] = np.nan print(«Используется size():») display(df_missing.groupby(«region»).size()) print(«Используется count() для sales_rep:») display(df_missing.groupby(«region»»[«sales_rep»].count())
Выход:
Использование функции size(): регион Север 4 Юг 4 Запад 4 тип данных: int64 Использование функции count() для sales_rep: регион Север 3 Юг 4 Запад 4 Имя: sales_rep, тип данных: int64
# Использование функции transform() для объектов группового уровня
Метод transform() полезен, когда необходимо вычислить значение на уровне группы и добавить его обратно в исходный DataFrame.
В этом примере мы рассчитываем общий объем продаж для каждого региона и сохраняем его в новом столбце под названием region_total_sales.
Затем мы вычисляем долю каждого заказа в общем объеме продаж соответствующего региона. В отличие от функции agg(), которая сводит данные к одной строке на группу, функция transform() возвращает значения, выровненные по исходным строкам, что делает ее очень полезной для проектирования признаков.
df[«region_total_sales»] = df.groupby(«region»»[«net_sales»].transform(«sum») df[«order_share_of_region»] = df[«net_sales»] / df[«region_total_sales»] df[[«order_id», «region», «net_sales», «region_total_sales», «order_share_of_region»]]

# Фильтрация групп с помощью функции filter()
Метод filter() позволяет сохранять или удалять целые группы на основе заданного условия. В этом примере мы сохраняем только те регионы, где общий объем чистых продаж превышает 3000.
Вместо возврата одной сводной строки для каждой группы, функция filter() возвращает исходные строки из групп, удовлетворяющих условию. Это полезно, когда нужно удалить группы с низкой производительностью или оставить только группы, удовлетворяющие бизнес-правилу.
high_sales_regions = df.groupby(«region»).filter(lambda group: group[«net_sales»].sum() > 3000) high_sales_regions

# Применение пользовательской логики с помощью функции apply()
Метод apply() предоставляет большую гибкость, поскольку позволяет применять пользовательскую логику к каждой группе.
В этом примере мы используем функцию apply() с функцией nlargest() для поиска позиций с наибольшим объемом чистых продаж в каждом регионе. Это полезно, когда встроенных агрегирующих функций недостаточно для вашего анализа.
Однако метод apply() может быть медленнее, чем встроенные методы, такие как sum(), mean(), agg() и transform(), поэтому лучше использовать его только тогда, когда вам нужны пользовательские операции группировки.
top_order_by_region = ( df.groupby(«region», group_keys=False) .apply(lambda group: group.nlargest(1, «net_sales»)) ) top_order_by_region

# Группировка по датам
Функция GroupBy также очень полезна для анализа по времени.
В этом примере мы извлекаем месяц из столбца order_date и группируем данные по месяцам.
Затем мы рассчитываем общий объем продаж и общее количество заказов за каждый месяц. Такой подход полезен при анализе тенденций во времени, таких как ежемесячные продажи, еженедельная активность пользователей или годовой рост выручки.
df[«month»] = df[«order_date»].dt.to_period(«M»).astype(str) monthly_sales = ( df.groupby(«month», as_index=False) .agg(total_sales=(«net_sales», «sum»), total_orders=(«order_id», «count»)) ) monthly_sales

# Группировка по датам с помощью pd.Grouper
pd.Grouper предоставляет более удобный способ группировки данных временных рядов без необходимости вручную создавать отдельный столбец для каждого месяца.
В этом примере мы группируем DataFrame по дате заказа, используя ежемесячную частоту, и вычисляем общую сумму продаж и общее количество заказов.
Это особенно полезно при работе с реальными наборами данных, содержащими временные метки, и когда необходимо обобщить данные по дням, неделям, месяцам, кварталам или годам.
monthly_sales_grouper = ( df.groupby(pd.Grouper(key=»order_date», freq=»M»)) .agg(total_sales=(«net_sales», «sum»), total_orders=(«order_id», «count»)) .reset_index() ) monthly_sales_grouper

# Создание сводной таблицы с группировкой
Вы можете объединить функции groupby() и unstack() для создания сводной таблицы в виде сводной таблицы.
В этом примере мы группируем данные по регионам и категориям, рассчитываем общую чистую выручку, а затем преобразуем результат таким образом, чтобы категории стали столбцами. Это упрощает сравнение результатов по регионам и категориям. Это отличный метод, когда вам нужна компактная таблица для отчетов или быстрого анализа.
region_category_table = ( df.groupby([«region», «category»])[«net_sales»] .sum() .unstack(fill_value=0) ) region_category_table

# Заключение
Pandas GroupBy — один из самых мощных инструментов для анализа данных в Python. Он помогает обобщать данные, сравнивать группы, создавать новые признаки, фильтровать результаты и применять пользовательские вычисления без написания лишней ручной логики.
В процессе работы над этим руководством я осознал, насколько глубока функциональность GroupBy. Даже после многолетней работы с данными я узнал новые и более эффективные способы решения распространенных проблем. Такие функции, как pd.Grouper, пользовательские функции агрегирования и transform(), особенно запомнились, поскольку они делают многие задачи быстрее, чище и проще в обслуживании.
Именно поэтому важно понимать возможности встроенных инструментов. Заманчиво полагаться на код, написанный с помощью Vibe, или на быстрые пользовательские решения, но зачастую это приводит к более медленному и сложному коду. Зная, что уже предоставляет pandas, вы можете писать более эффективные, многократно используемые и практичные решения для анализа данных в реальных условиях.
В этом руководстве мы рассмотрели наиболее полезные операции GroupBy, включая базовую агрегацию, именованную агрегацию, многоколоночную группировку, сортировку, разницу между count() и size(), transform(), filter(), apply(), группировку по датам и сводные таблицы. Поняв эти принципы, вы сможете использовать GroupBy для быстрого и уверенного решения множества реальных задач анализа данных.
Абид Али Аван (@1abidaliawan) — сертифицированный специалист по анализу данных, увлеченный созданием моделей машинного обучения. В настоящее время он занимается созданием контента и написанием технических блогов о технологиях машинного обучения и анализа данных. Абид имеет степень магистра в области управления технологиями и степень бакалавра в области телекоммуникационной инженерии. Его цель — создать продукт на основе искусственного интеллекта с использованием графовой нейронной сети для студентов, страдающих психическими заболеваниями.
Источник: www.kdnuggets.com

Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.