Группировка и агрегация в pandas: превращение хаоса в инсайты
Для кого эта статья:
- Аналитики данных и начинающие специалисты в области анализа данных
- Студенты и профессионалы, которые хотят улучшить свои навыки работы с pandas
Руководители и специалисты, занимающиеся бизнес-аналитикой и принятием решений на основе данных
Представьте себе огромный массив данных, где скрыты критически важные инсайты для вашего бизнеса. Эта неструктурированная информация — как запертая сокровищница без ключа. Именно здесь в игру вступают методы группировки и агрегации в библиотеке pandas — мощнейшие инструменты превращения хаоса в порядок. Они позволяют трансформировать сырые таблицы в кристально чистые выводы, сокращая время анализа с часов до секунд. Овладение этими техниками — определяющий фактор, отличающий начинающего аналитика от профессионала высокого класса. 🔍📊
Хотите освоить группировку и агрегацию данных в pandas на профессиональном уровне? Курс Профессия аналитик данных от Skypro погружает вас в практический мир анализа данных. Вы не просто изучите синтаксис — вы научитесь мыслить как эксперт по данным, решая реальные бизнес-задачи с применением pandas и других инструментов аналитики. Преобразите свою карьеру с помощью навыков, востребованных на рынке уже сегодня.
Группировка и агрегация данных в pandas: основы методологии
Группировка и агрегация в pandas — фундаментальные операции при работе с табличными данными, позволяющие извлекать ценные инсайты из массивов информации. Эти методы трансформируют исходные данные в структурированные сводки, делая анализ более эффективным и понятным.
Концептуально процесс группировки и агрегации в pandas можно разделить на три ключевых этапа:
- Разделение (Split) — данные разбиваются на группы по заданному критерию
- Применение (Apply) — к каждой группе применяется определённая функция
- Комбинирование (Combine) — результаты объединяются в новую структуру данных
Эта концепция "split-apply-combine" лежит в основе большинства операций с данными и является мощной парадигмой для решения аналитических задач.
При работе с группировкой и агрегацией в pandas необходимо понимать несколько ключевых компонентов:
| Компонент | Описание | Пример в pandas |
|---|---|---|
| Группирующие ключи | Столбцы, по которым производится группировка | df.groupby(['region', 'product']) |
| Агрегирующие функции | Функции для расчёта итоговых значений | sum(), mean(), count(), max() |
| Результат группировки | Объект GroupBy, содержащий сгруппированные данные | grouped = df.groupby('category') |
| Результат агрегации | DataFrame с агрегированными значениями | grouped.agg({'sales': 'sum'}) |
Основные преимущества группировки и агрегации данных:
- Сжатие больших объёмов данных в компактные сводки 📊
- Выявление паттернов и трендов, скрытых в исходных данных
- Ускорение анализа за счёт работы с предварительно обработанными данными
- Возможность быстрого сравнения показателей между различными категориями
- Подготовка данных для визуализации и построения отчётов
Наиболее распространённые сценарии использования группировки и агрегации включают:
- Расчёт суммарных продаж по регионам или категориям товаров
- Вычисление среднего чека для различных сегментов клиентов
- Анализ временных рядов с группировкой по временным интервалам
- Построение сводных отчётов с несколькими уровнями детализации
- Подготовка данных для дальнейшего статистического анализа
Алексей Петров, Lead Data Analyst
Когда я пришёл работать в крупный e-commerce, столкнулся с классической проблемой — ежедневно генерировалось более 10 миллионов строк данных о транзакциях. Руководство требовало еженедельные отчёты о продажах по категориям и регионам, но обработка такого объёма данных занимала почти 2 дня работы.
Решение пришло с оптимизацией методов группировки и агрегации в pandas. Вместо последовательной обработки я реализовал параллельный подход:
PythonСкопировать код# Раньше использовал простую группировку sales_summary = transactions.groupby(['region', 'category']).agg({'amount': 'sum'}) # Оптимизировал процесс с предварительной фильтрацией и параллельной обработкой def process_chunk(chunk): return chunk.groupby(['region', 'category']).agg({'amount': 'sum'}) chunks = np.array_split(transactions, 8) # Разбиваем на части для параллельной обработки with Pool(8) as p: results = p.map(process_chunk, chunks) sales_summary = pd.concat(results).groupby(level=['region', 'category']).sum()Время обработки сократилось до 1.5 часов, а после дополнительной оптимизации типов данных и индексации — до 20 минут. Группировка и агрегация в pandas превратили непосильную задачу в рутинную операцию, освободив время для более глубокого анализа данных.

Метод groupby() в pandas: практические аспекты группировки
Метод groupby() — краеугольный камень процесса группировки в pandas. Он создает объект GroupBy, который служит основой для последующих операций агрегации, фильтрации и трансформации данных.
Базовый синтаксис метода выглядит следующим образом:
df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False)
Ключевые параметры метода groupby():
- by — столбцы или функции для группировки (можно указать один столбец или список столбцов)
- axis — ось, по которой производится группировка (0 для строк, 1 для столбцов)
- as_index — использовать ли группирующие столбцы как индекс результата
- sort — сортировать ли результат по группирующим ключам
Группировку можно выполнять различными способами:
- По одному столбцу:
df.groupby('country') - По нескольким столбцам:
df.groupby(['country', 'product']) - По уровням индекса:
df.groupby(level=0) - С использованием функции маппинга:
df.groupby(df['date'].dt.year) - По результатам вызова функции:
df.groupby(lambda x: x[0])(группировка по первой букве)
После создания объекта GroupBy можно применять различные методы для работы с группами:
| Метод | Описание | Пример использования |
|---|---|---|
| get_group() | Получение одной конкретной группы данных | grouped.get_group('USA') |
| groups | Словарь групп с соответствующими индексами | grouped.groups |
| ngroups | Количество групп | grouped.ngroups |
| indices | Словарь индексов каждой группы | grouped.indices |
| size() | Размер каждой группы | grouped.size() |
Практические примеры использования метода groupby():
# Группировка по одному столбцу с подсчётом количества элементов в группе
sales_count = df.groupby('region').size()
# Группировка по нескольким столбцам с расчётом среднего значения
avg_sales = df.groupby(['region', 'product'])['sales'].mean()
# Группировка с исключением NA значений
sales_by_region = df.groupby('region', dropna=False)['sales'].sum()
# Группировка по временным интервалам
sales_by_month = df.groupby(pd.Grouper(key='date', freq='M'))['sales'].sum()
# Группировка с использованием пользовательской функции
df.groupby(lambda x: 'High' if x > 1000 else 'Low')['sales'].mean()
При работе с методом groupby() следует учитывать несколько важных аспектов:
- Группировка может быть ресурсоёмкой операцией на больших датасетах 📉
- Параметр
as_index=Falseпозволяет получить результат в более привычном табличном формате - Для временных данных эффективнее использовать специальный объект Grouper
- При группировке по нескольким столбцам создаётся многоуровневый индекс
- Методы
unstack()иreset_index()помогают преобразовать многоуровневый индекс в более читаемую форму
Итерация по группам — ещё один мощный механизм для применения сложной логики к каждой группе данных:
# Итерация по группам с выполнением операций для каждой группы
for name, group in df.groupby('region'):
print(f"Region: {name}")
print(f"Max sales: {group['sales'].max()}")
print(f"Avg sales: {group['sales'].mean():.2f}")
print("---")
Агрегационные функции pandas для обработки таблиц
После группировки данных с помощью groupby() необходимо применить агрегацию для получения итоговых значений. Pandas предоставляет богатый набор агрегационных функций, позволяющих эффективно анализировать сгруппированные данные.
Мария Соколова, Chief Data Scientist
Работая с финансовыми данными для инвестиционного фонда, мы столкнулись с проблемой — требовалось проанализировать портфель из 5000+ инструментов по десяткам метрик одновременно. Традиционный подход с последовательным вычислением каждого показателя занимал около 4 часов.
Решение нашлось в продвинутом использовании агрегационных функций pandas:
PythonСкопировать код# Вместо последовательного вычисления каждой метрики portfolio_stats = {} portfolio_stats['total_value'] = portfolio.groupby('sector')['value'].sum() portfolio_stats['avg_return'] = portfolio.groupby('sector')['return'].mean() portfolio_stats['risk'] = portfolio.groupby('sector')['volatility'].std() portfolio_stats['count'] = portfolio.groupby('sector').size() # Мы перешли к единой агрегации с именованными функциями portfolio_stats = portfolio.groupby('sector').agg({ 'value': 'sum', 'return': ['mean', 'median', lambda x: x.quantile(0.75) – x.quantile(0.25)], 'volatility': ['std', 'min', 'max'], 'instrument_id': 'count' }).rename(columns={ 'value': 'total_value', 'return': 'performance_metrics', 'volatility': 'risk_metrics', 'instrument_id': 'instrument_count', '<lambda>': 'return_iqr' })Это снизило время вычислений до 15 минут и сделало код намного читабельнее. А главное — появилась возможность быстро добавлять новые метрики без переписывания логики. Агрегационные функции pandas стали нашим секретным оружием для быстрой обработки данных в стрессовых рыночных условиях.
Основные методы агрегации, доступные для объекта GroupBy, включают:
- sum() — сумма значений
- mean() — среднее арифметическое
- median() — медиана
- min(), max() — минимальное и максимальное значения
- count() — количество непустых значений
- std(), var() — стандартное отклонение и дисперсия
- first(), last() — первое и последнее значения в группе
- quantile() — квантили распределения
- agg() — универсальный метод для применения произвольных функций агрегации
Метод agg() заслуживает особого внимания, так как он предоставляет наибольшую гибкость при агрегации данных. С его помощью можно применять:
- Встроенные функции:
grouped.agg('sum') - Несколько функций к одному столбцу:
grouped['sales'].agg(['sum', 'mean', 'count']) - Разные функции к разным столбцам:
grouped.agg({'sales': 'sum', 'profit': 'mean'}) - Пользовательские функции:
grouped.agg(lambda x: x.max() – x.min()) - Комбинации всех вышеперечисленных подходов
Примеры комплексной агрегации с использованием различных функций:
# Применение нескольких агрегаций к разным столбцам
result = df.groupby('region').agg({
'sales': ['sum', 'mean', 'count'],
'profit': ['mean', 'max'],
'customer_id': 'nunique' # Уникальное количество клиентов
})
# Использование именованных агрегаций
result = df.groupby('region').agg(
total_sales=('sales', 'sum'),
avg_sales=('sales', 'mean'),
transaction_count=('transaction_id', 'count'),
unique_customers=('customer_id', 'nunique')
)
# Применение пользовательских функций в агрегации
def profit_margin(x):
return (x['profit'].sum() / x['sales'].sum()) * 100
result = df.groupby('region').apply(profit_margin).rename('profit_margin')
Помимо стандартных агрегаций, pandas предлагает несколько специализированных методов для работы с сгруппированными данными:
- transform() — применяет функцию к каждой группе и возвращает результат того же размера, что и исходный DataFrame
- filter() — фильтрует группы на основе заданного условия
- apply() — применяет произвольную функцию к каждой группе
Разница между этими методами:
| Метод | Размерность результата | Типичное применение | Пример |
|---|---|---|---|
| agg() | Одна строка на группу | Сводная статистика | grouped.agg('mean') |
| transform() | Соответствует исходному DataFrame | Вычисление отклонений от среднего по группе | grouped.transform(lambda x: x – x.mean()) |
| filter() | Подмножество исходного DataFrame | Отбор групп по условию | grouped.filter(lambda x: x['sales'].mean() > 1000) |
| apply() | Может быть любой | Сложные преобразования | grouped.apply(custom_function) |
Часто возникает необходимость вычислять относительные показатели внутри групп, например, долю продаж каждого товара в общих продажах категории:
# Вычисление доли продаж каждого товара в категории
df['category_share'] = df['sales'] / df.groupby('category')['sales'].transform('sum')
# Вычисление отклонения от среднего по группе (z-score)
df['z_score'] = df.groupby('category')['sales'].transform(lambda x: (x – x.mean()) / x.std())
Такой подход позволяет обогатить исходные данные контекстуальной информацией без необходимости использования дополнительных операций объединения (join).
Продвинутые техники группировки и агрегации больших данных
Когда объёмы данных растут, а аналитические задачи усложняются, приходится выходить за рамки базовых методов группировки и агрегации в pandas. Продвинутые техники позволяют эффективно работать с большими массивами информации и решать нестандартные задачи.
Иерархическая группировка (группировка с несколькими уровнями) — одна из таких техник, позволяющая анализировать данные с различными уровнями детализации:
# Иерархическая группировка с тремя уровнями
sales_summary = df.groupby(['year', 'region', 'product']).agg({
'sales': 'sum',
'profit': 'sum',
'transactions': 'count'
})
# Получение частичных итогов с помощью функции groupby.sum()
region_summary = sales_summary.groupby(level=['year', 'region']).sum()
# Использование метода unstack для преобразования многоуровневого индекса в столбцы
pivoted_summary = sales_summary.unstack(level='product')
Продвинутая группировка с использованием временных данных открывает широкие возможности для анализа временных рядов:
- Группировка по временным периодам (день, неделя, месяц, квартал)
- Скользящие окна для расчёта динамических метрик
- Сезонный анализ данных
# Группировка по месяцам
monthly_sales = df.groupby(pd.Grouper(key='date', freq='M'))['sales'].sum()
# Группировка по дням недели
weekday_sales = df.groupby(df['date'].dt.dayofweek)['sales'].mean()
# Скользящее среднее по группам
df.groupby('product')['sales'].rolling(window=7).mean()
# Группировка по смешанным временным критериям
df.groupby([df['date'].dt.year, df['date'].dt.quarter])['sales'].sum()
Категориальные данные также можно эффективно группировать с использованием специальных техник:
- Группировка по интервалам числовых значений (бинам)
- Группировка по квантилям распределения
- Пользовательские функции маппинга для создания категорий
# Создание бинов для числовых данных
df['price_category'] = pd.cut(df['price'], bins=[0, 100, 500, 1000, np.inf],
labels=['Budget', 'Standard', 'Premium', 'Luxury'])
# Группировка по созданным категориям
category_stats = df.groupby('price_category')['sales'].sum()
# Группировка по квантилям
df['price_quantile'] = pd.qcut(df['price'], q=4, labels=['Q1', 'Q2', 'Q3', 'Q4'])
quantile_stats = df.groupby('price_quantile')['sales'].mean()
Для работы с большими объёмами данных эффективны методы оптимизации группировки и агрегации:
- Использование параллельной обработки для ускорения вычислений
- Предварительная фильтрация данных перед группировкой
- Частичная агрегация с последующим объединением результатов
- Применение библиотек dask или vaex для работы с данными, не помещающимися в оперативную память
# Параллельная обработка групп данных
from multiprocessing import Pool
def process_group(group_data):
# Сложные вычисления для группы
return group_data['sales'].sum(), group_data['profit'].mean()
# Разбиение на группы и параллельная обработка
groups = [group for _, group in df.groupby('region')]
with Pool(processes=4) as pool:
results = pool.map(process_group, groups)
Комбинированные методы агрегации позволяют создавать сложные аналитические отчёты:
- Многоуровневая агрегация с различными функциями
- Смешанные агрегации (агрегация одних столбцов с группировкой по другим)
- Агрегация с фильтрацией и условными вычислениями
# Многоуровневая агрегация с различными функциями для разных столбцов
complex_report = df.groupby(['region', 'category']).agg({
'sales': ['sum', 'mean', 'count', lambda x: x.sum() / df['sales'].sum()],
'profit': ['sum', 'mean', lambda x: x.sum() / x.count()],
'date': ['min', 'max', lambda x: (x.max() – x.min()).days]
})
# Переименование столбцов для улучшения читаемости
complex_report.columns = ['_'.join(col).strip() for col in complex_report.columns.values]
Группировка и агрегация в pandas также могут использоваться для расширенных аналитических задач:
- Когортный анализ — группировка пользователей по дате первого взаимодействия
- RFM-анализ — сегментация клиентов по частоте, недавности и монетарной ценности
- Анализ воронки продаж с группировкой по этапам конверсии
- Географический анализ с группировкой по регионам и геокоординатам
Оптимизация кода при работе с группировкой в pandas
Эффективность кода при работе с группировкой и агрегацией в pandas имеет решающее значение, особенно при обработке больших массивов данных. Оптимизированный код не только выполняется быстрее, но и требует меньше ресурсов, что критично в продакшн-окружениях. 🚀
Рассмотрим ключевые стратегии оптимизации кода при работе с группировкой в pandas:
- Фильтрация данных перед группировкой — чем меньше данных подвергается группировке, тем быстрее выполняется операция
- Выбор только необходимых столбцов — исключение неиспользуемых столбцов сокращает объём обрабатываемых данных
- Преобразование типов данных — использование оптимальных типов данных существенно влияет на производительность
- Минимизация операций копирования — избегание излишних копирований DataFrame
- Использование оптимальных алгоритмов агрегации — выбор наиболее эффективных методов для конкретных задач
Сравнение производительности различных подходов:
| Подход | Время выполнения (отн. ед.) | Использование памяти | Применимость |
|---|---|---|---|
| Стандартная группировка | 1.0 (базовый) | Среднее | Общий случай |
| С предварительной фильтрацией | 0.6-0.8 | Низкое | Когда нужна часть данных |
| С оптимизацией типов | 0.7-0.9 | Низкое | Всегда |
| С параллельной обработкой | 0.3-0.5 | Высокое | Для больших датасетов |
| С использованием SQL/query() | 0.5-0.8 | Среднее | Для сложных запросов |
Конкретные техники оптимизации кода с примерами:
# Неоптимизированный код
result = df.groupby('category')['sales'].sum()
# Оптимизированный код с предварительной фильтрацией и выбором столбцов
result = df[df['sales'] > 0][['category', 'sales']].groupby('category')['sales'].sum()
# Оптимизация типов данных
df['category'] = df['category'].astype('category') # Существенно экономит память для повторяющихся строковых данных
result = df.groupby('category')['sales'].sum()
# Использование numba для ускорения пользовательских функций агрегации
from numba import jit
@jit(nopython=True)
def optimized_calculation(values):
# Сложные вычисления
return result
df.groupby('category')['values'].agg(optimized_calculation)
Важные приёмы оптимизации для различных сценариев:
- Для временных данных: использовать параметр
observed=Trueпри работе с категориальными данными, чтобы избежать создания групп для всех возможных категорий - Для строковых данных: преобразовывать в категориальный тип для ускорения группировки
- Для числовых данных: использовать более компактные типы (int32 вместо int64, float32 вместо float64)
- Для агрегаций: применять векторизованные операции вместо циклов и apply()
Эффективное использование параллелизма для ускорения группировки:
# Параллельная обработка с использованием Dask
import dask.dataframe as dd
# Преобразование pandas DataFrame в Dask DataFrame
dask_df = dd.from_pandas(df, npartitions=4)
# Параллельная группировка и агрегация
result = dask_df.groupby('category')['sales'].sum().compute()
# Альтернативный подход с использованием pandas и multiprocessing
from multiprocessing import Pool
import numpy as np
def process_partition(partition):
return partition.groupby('category')['sales'].sum()
# Разделение данных на части
partitions = np.array_split(df, 4)
# Параллельная обработка
with Pool(4) as pool:
results = pool.map(process_partition, partitions)
# Объединение результатов
final_result = pd.concat(results).groupby(level=0).sum()
Избегайте типичных ошибок, которые снижают производительность:
- Использование метода
apply()вместо более оптимизированных агрегационных функций - Повторное выполнение одних и тех же группировок (сохраняйте результаты промежуточных операций)
- Игнорирование индексов (правильное использование индексов может значительно ускорить операции)
- Чрезмерное усложнение логики группировки (иногда несколько простых операций эффективнее одной сложной)
Наконец, инструменты профилирования помогут выявить узкие места в коде:
# Профилирование производительности
import cProfile
cProfile.run('df.groupby("category")["sales"].agg(["sum", "mean", "count"])')
# Измерение времени выполнения
%timeit df.groupby('category')['sales'].sum()
# Отслеживание использования памяти
import tracemalloc
tracemalloc.start()
result = df.groupby('category')['sales'].sum()
current, peak = tracemalloc.get_traced_memory()
print(f"Current memory usage: {current / 10**6}MB; Peak: {peak / 10**6}MB")
tracemalloc.stop()
Группировка и агрегация в pandas — фундаментальные инструменты, преобразующие хаос данных в структурированное знание. Овладев этими методами, вы не просто ускоряете обработку информации — вы переходите на качественно новый уровень анализа. Техники, рассмотренные в этой статье, превращают рутинные задачи в элегантные решения, экономя часы работы. Помните: оптимальный код группировки — это искусство баланса между читаемостью, производительностью и масштабируемостью. Применяйте эти принципы, и ваши данные раскроют свой потенциал, превратившись из сырого материала в ценные бизнес-инсайты.
Читайте также
- Иерархическая кластеризация: методы, дендрограммы и применение
- Когортный анализ: как превратить данные в стратегическое оружие
- Pandas: мощный инструмент анализа данных для Python-разработчиков
- Python синтаксис для анализа данных: от основ к продвинутым техникам
- Зарплата data scientist и аналитика данных в Москве
- Средняя зарплата data scientist
- Обучение нейронных сетей на Python: пошаговое руководство
- Полиномиальная регрессия: моделирование нелинейных данных в Python
- Метод filter JavaScript: мощный способ поиска в массивах
- Jupyter Notebook и Google Colab: сравнение интерактивных сред анализа