Привет! Ты уже умеешь фильтровать данные, добавлять колонки и заменять значения. Но часто нужно не просто смотреть на строки по отдельности, а собирать их в группы и вычислять общие статистики. Например, «какая средняя зарплата в каждом городе» или «сколько продаж было по месяцам».
В этой статье мы разберём:
- Что такое
groupby()и зачем он нужен - Группировка по одной и нескольким колонкам
- Агрегация данных с
agg()и встроенными функциями - Несколько агрегаций одновременно
- Создание своих агрегаций
- Что нужно знать перед началом
- Основная часть
- Подготовка данных
- Основы groupby()
- Группировка по одной колонке
- Группировка с несколькими агрегациями
- Агрегация с agg()
- Разные агрегации для разных колонок
- Пользовательские агрегации через agg()
- Группировка по нескольким колонкам
- Преобразование в DataFrame
- Агрегация с pivot_table()
- Применение apply() после группировки
- transform() — добавление агрегатов в исходную таблицу
- Практический пример: анализ продаж по категориям
- Задачи для закрепления
- Нюансы и подводные камни
- Группировка с пропусками
- Производительность
- Сортировка результата
- Частые ошибки и как их избежать
- Ошибка 1: Забыл указать колонку для агрегации
- Ошибка 2: Неправильный синтаксис agg()
- Ошибка 3: Использование apply() вместо agg()
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный Pandas (
pip install pandas) - Базовое понимание DataFrame и колонок
- Желание агрегировать данные
Совет:
groupby()— это аналогGROUP BYв SQL. Если ты работал с базами данных, ты уже понимаешь логику. Если нет — это очень полезный инструмент для анализа данных.
Основная часть
Подготовка данных
import pandas as pd
import numpy as np
np.random.seed(42)
# Создаём данные о продажах
data = {
'Товар': ['Ноутбук', 'Телефон', 'Планшет', 'Ноутбук', 'Телефон', 'Планшет'] * 3,
'Продажи': np.random.randint(1, 20, 18),
'Цена': [50000, 30000, 15000] * 6,
'Город': ['Москва'] * 6 + ['СПб'] * 6 + ['Казань'] * 6,
'Магазин': ['A'] * 9 + ['B'] * 9
}
df = pd.DataFrame(data)
df['Выручка'] = df['Продажи'] * df['Цена']
print("Исходные данные:")
print(df.head(10))Результат:
Товар Продажи Цена Город Магазин Выручка
0 Ноутбук 7 50000 Москва A 350000
1 Телефон 10 30000 Москва A 300000
2 Планшет 11 15000 Москва A 165000
3 Ноутбук 14 50000 Москва A 700000
4 Телефон 6 30000 Москва A 180000
5 Планшет 10 15000 Москва A 150000
6 Ноутбук 8 50000 СПб A 400000
7 Телефон 4 30000 СПб A 120000
8 Планшет 9 15000 СПб A 135000
9 Ноутбук 4 50000 СПб B 200000Совет: Мы создали данные с тремя городами, двумя магазинами и тремя товарами. Это идеальный набор для изучения группировки.
Основы groupby()
groupby() группирует строки по значениям в указанной колонке. После группировки к каждой группе можно применить агрегирующую функцию.
Группировка по одной колонке
# Группируем по товару и считаем сумму продаж
grouped = df.groupby('Товар')['Продажи'].sum()
print(grouped)Результат:
Товар
Ноутбук 45
Планшет 55
Телефон 47
Name: Продажи, dtype: int64Группировка с несколькими агрегациями
# Группируем по товару и считаем сумму, среднее и количество
grouped = df.groupby('Товар')['Продажи'].agg(['sum', 'mean', 'count'])
print(grouped)Результат:
sum mean count
Товар
Ноутбук 45 7.500000 6
Планшет 55 9.166667 6
Телефон 47 7.833333 6Совет: После группировки у тебя появляется объект
DataFrameGroupBy. Ты можешь применять к нему разные агрегирующие функции.
Агрегация с agg()
agg() — самый гибкий способ агрегации. Он позволяет указать несколько функций сразу.
Разные агрегации для разных колонок
# Для колонки 'Продажи' считаем сумму и среднее, для 'Цена' — максимум
result = df.groupby('Товар').agg({
'Продажи': ['sum', 'mean'],
'Цена': 'max'
})
print(result)Результат:
Продажи Цена
sum mean max
Товар
Ноутбук 45 7.500000 50000
Планшет 55 9.166667 15000
Телефон 47 7.833333 30000Пользовательские агрегации через agg()
# Создаём свою функцию
def price_range(x):
return x.max() - x.min()
result = df.groupby('Город')['Цена'].agg(price_range)
print(result)Совет: В
agg()можно передать и лямбда-функции. Это удобно для быстрых расчётов.
Группировка по нескольким колонкам
# Группируем по Городу и Товару
grouped = df.groupby(['Город', 'Товар'])['Продажи'].sum()
print(grouped)Результат:
Город Товар
Казань Ноутбук 10
Планшет 15
Телефон 9
СПб Ноутбук 16
Планшет 19
Телефон 12
Москва Ноутбук 19
Планшет 21
Телефон 26
Name: Продажи, dtype: int64Преобразование в DataFrame
# .reset_index() превращает результат обратно в DataFrame
grouped_df = df.groupby(['Город', 'Товар'])['Продажи'].sum().reset_index()
print(grouped_df)Результат:
Город Товар Продажи
0 Казань Ноутбук 10
1 Казань Планшет 15
2 Казань Телефон 9
3 СПб Ноутбук 16
4 СПб Планшет 19
5 СПб Телефон 12
6 Москва Ноутбук 19
7 Москва Планшет 21
8 Москва Телефон 26Совет:
reset_index()превращает мультииндекс в обычные колонки. Это часто удобно для дальнейшей работы.
Агрегация с pivot_table()
pivot_table() — это более мощная альтернатива groupby(), которая строит сводные таблицы.
# Строим сводную таблицу: Город vs Товар, значения — продажи
pivot = df.pivot_table(
values='Продажи',
index='Город',
columns='Товар',
aggfunc='sum'
)
print(pivot)Результат:
Товар Ноутбук Планшет Телефон
Город
Казань 10 15 9
СПб 16 19 12
Москва 19 21 26Применение apply() после группировки
apply() позволяет применять более сложные функции к каждой группе.
# Для каждой группы (города) вычисляем среднее и создаём колонку с процентом
def add_percent(group):
group['Процент'] = (group['Продажи'] / group['Продажи'].sum()) * 100
return group
result = df.groupby('Город').apply(add_percent)
print(result[['Город', 'Товар', 'Продажи', 'Процент']])Результат:
Город Товар Продажи Процент
0 Москва Ноутбук 7 12.500000
1 Москва Телефон 10 17.857143
2 Москва Планшет 11 19.642857
3 Москва Ноутбук 14 25.000000
4 Москва Телефон 6 10.714286
5 Москва Планшет 10 17.857143
...Совет:
apply()мощнееagg(), но может быть медленнее для больших данных. Используй его, когда нужна сложная логика.
transform() — добавление агрегатов в исходную таблицу
transform() возвращает результат той же формы, что и исходные данные. Это удобно для добавления агрегированных значений в таблицу.
# Добавляем средние продажи для каждого города в исходную таблицу
df['Средние_продажи_по_городу'] = df.groupby('Город')['Продажи'].transform('mean')
print(df[['Город', 'Товар', 'Продажи', 'Средние_продажи_по_городу']])Результат:
Город Товар Продажи Средние_продажи_по_городу
0 Москва Ноутбук 7 11.333333
1 Москва Телефон 10 11.333333
2 Москва Планшет 11 11.333333
3 Москва Ноутбук 14 11.333333
4 Москва Телефон 6 11.333333
5 Москва Планшет 10 11.333333
6 СПб Ноутбук 8 12.333333
7 СПб Телефон 4 12.333333
8 СПб Планшет 9 12.333333
9 СПб Ноутбук 4 12.333333
...Практический пример: анализ продаж по категориям
import pandas as pd
import numpy as np
np.random.seed(42)
# Данные о продажах
data = {
'Товар': ['Ноутбук', 'Телефон', 'Планшет'] * 20,
'Продажи': np.random.randint(1, 20, 60),
'Цена': [50000, 30000, 15000] * 20,
'Город': np.random.choice(['Москва', 'СПб', 'Казань'], 60),
'Магазин': np.random.choice(['A', 'B'], 60)
}
df = pd.DataFrame(data)
df['Выручка'] = df['Продажи'] * df['Цена']
print("=== 1. Общая статистика по товарам ===")
print(df.groupby('Товар')['Выручка'].agg(['sum', 'mean', 'count']))
print("\n=== 2. Продажи по городам ===")
print(df.groupby('Город')['Выручка'].sum())
print("\n=== 3. Лучший товар в каждом городе ===")
best = df.groupby(['Город', 'Товар'])['Выручка'].sum().reset_index()
best = best.loc[best.groupby('Город')['Выручка'].idxmax()]
print(best)
print("\n=== 4. Сводная: Город vs Товар ===")
pivot = df.pivot_table(
values='Выручка',
index='Город',
columns='Товар',
aggfunc='sum'
)
print(pivot)
print("\n=== 5. Добавляем средние выручки в данные ===")
df['Средняя_выручка_по_товару'] = df.groupby('Товар')['Выручка'].transform('mean')
print(df[['Товар', 'Выручка', 'Средняя_выручка_по_товару']].head())Задачи для закрепления
Задача 1. Сгруппируй данные по колонке Город и посчитай среднюю зарплату.
Задача 2. Сгруппируй по двум колонкам (Город, Статус) и посчитай сумму зарплат.
Задача 3. С помощью agg() посчитай минимум, максимум и среднее для зарплат по городам.
Задача 4. Добавь в исходные данные колонку со средним возрастом для каждой группы (используй transform).
Задача 5. Построй сводную таблицу с помощью pivot_table().
Ответы:
Задача 1.
df.groupby('Город')['Зарплата'].mean()Задача 2.
df.groupby(['Город', 'Статус'])['Зарплата'].sum()Задача 3.
df.groupby('Город')['Зарплата'].agg(['min', 'max', 'mean'])Задача 4.
df['Средний_возраст_по_группе'] = df.groupby('Город')['Возраст'].transform('mean')Задача 5.
pivot = df.pivot_table(values='Зарплата', index='Город', columns='Статус', aggfunc='mean')Нюансы и подводные камни
Группировка с пропусками
Если в колонке есть NaN, строки с ними не попадают в группы. Чтобы включить их, используй dropna=False.
df.groupby('Колонка', dropna=False)['Значение'].mean()Производительность
Для больших данных groupby() может быть медленным. Используй agg() с векторизованными функциями (например, встроенными) вместо apply().
Сортировка результата
По умолчанию groupby() сортирует группы по ключам. Отключить можно с помощью sort=False.
df.groupby('Колонка', sort=False)['Значение'].sum()Частые ошибки и как их избежать
Ошибка 1: Забыл указать колонку для агрегации
# Ошибка
df.groupby('Город').sum()
# Правильно — указываем колонку
df.groupby('Город')['Зарплата'].sum()Ошибка 2: Неправильный синтаксис agg()
# Ошибка
df.groupby('Город').agg('sum', 'mean')
# Правильно
df.groupby('Город')['Зарплата'].agg(['sum', 'mean'])Ошибка 3: Использование apply() вместо agg()
# Медленно для простых операций
df.groupby('Город')['Зарплата'].apply(lambda x: x.sum())
# Быстро для встроенных функций
df.groupby('Город')['Зарплата'].sum()Шпаргалка
| Что нужно | Как пишется |
|---|---|
| Группировка по одной колонке | df.groupby('Колонка')['Значение'].sum() |
| Группировка по нескольким колонкам | df.groupby(['Кол1', 'Кол2'])['Значение'].sum() |
| Несколько агрегаций | df.groupby('Колонка')['Значение'].agg(['sum', 'mean']) |
| Разные агрегации для разных колонок | df.groupby('Колонка').agg({'Кол1': 'sum', 'Кол2': 'mean'}) |
| Пользовательская агрегация | df.groupby('Колонка')['Значение'].agg(функция) |
| Добавление агрегата в данные | df.groupby('Колонка')['Значение'].transform('mean') |
| Сложная логика | df.groupby('Колонка').apply(функция) |
| Сводная таблица | df.pivot_table(values='x', index='Кол1', columns='Кол2', aggfunc='sum') |
Заключение
Сегодня мы научились:
- Группировать данные по одной и нескольким колонкам
- Применять агрегирующие функции с
agg() - Использовать встроенные и пользовательские агрегации
- Строить сводные таблицы с
pivot_table() - Добавлять агрегированные значения в данные с
transform()






![Выбор колонок и строк: [] vs loc vs iloc](https://imi-ds.ru/wp-content/uploads/2026/08/vybor-kolonok-i-strok-vs-loc-vs-iloc-335x220.webp)

