Задачи на агрегацию в pandas
Карьерник — квиз-тренажёр в Telegram с 1500+ задач и вопросов для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Зачем эти задачи
Группировка — ежедневная работа аналитика в pandas: сумма по категориям, среднее по когортам, процентили по сегментам, running totals для отчётов. groupby + agg / transform / apply — одна из тем, которую 100% спросят на собесе по Python.
На собеседованиях любят проверять нюансы: разница agg и transform (первая возвращает N_groups строк, вторая — len(df)), когда медленно работает apply vs встроенные функции, как применить разные агрегации к разным колонкам, как отфильтровать группы по условию (groupby().filter).
Ниже — 12 задач с решениями на типовом датасете (user_id, category, amount, date). От простых groupby().sum() до продвинутых паттернов (топ-N в группе, running total, доля в категории через transform, conditional aggregation).
Dataset
import pandas as pd
df = pd.DataFrame({
'user_id': [1, 1, 2, 2, 3, 3, 3],
'category': ['A', 'B', 'A', 'A', 'B', 'B', 'A'],
'amount': [100, 200, 150, 250, 300, 100, 200],
'date': pd.to_datetime(['2026-01-01', '2026-01-02', '2026-01-01',
'2026-02-01', '2026-02-01', '2026-03-01', '2026-03-02'])
})Задача 1. Сумма по пользователю
df.groupby('user_id')['amount'].sum()Задача 2. Количество заказов на пользователя
df.groupby('user_id').size()
# или
df.groupby('user_id')['amount'].count()Задача 3. Несколько агрегатов одновременно
df.groupby('user_id').agg(
total=('amount', 'sum'),
avg=('amount', 'mean'),
count=('amount', 'count')
)Задача 4. Средний amount по (user_id, category)
df.groupby(['user_id', 'category'])['amount'].mean()Задача 5. Pivot по месяцу × категории
df['month'] = df['date'].dt.to_period('M')
df.pivot_table(
values='amount',
index='month',
columns='category',
aggfunc='sum',
fill_value=0
)Задача 6. Пользователи с 2+ заказами
counts = df.groupby('user_id').size()
df[df['user_id'].isin(counts[counts >= 2].index)]
# или через filter
df.groupby('user_id').filter(lambda g: len(g) >= 2)Задача 7. Топ-2 заказа в каждой категории
df.sort_values(['category', 'amount'], ascending=[True, False]) \
.groupby('category') \
.head(2)Задача 8. Running total в группе
df['running_total'] = df.sort_values('date') \
.groupby('user_id')['amount'].cumsum()Задача 9. Доля пользователя в категории
df['share_in_category'] = df['amount'] / \
df.groupby('category')['amount'].transform('sum')Задача 10. Первое и последнее значение в группе
df.groupby('user_id').agg(
first_date=('date', 'min'),
last_date=('date', 'max'),
first_amount=('amount', 'first'),
last_amount=('amount', 'last')
)Но first/last работает только на отсортированных данных. Используйте head(1) / tail(1):
df.sort_values('date').groupby('user_id').first()
df.sort_values('date').groupby('user_id').last()Задача 11. Custom aggregation
def range_func(s):
return s.max() - s.min()
df.groupby('user_id')['amount'].agg(range_func)Задача 12. Conditional aggregation
# сколько у каждого user заказов дороже 100
df.groupby('user_id').apply(lambda g: (g['amount'] > 100).sum())
# или
df.assign(over_100=df['amount'] > 100).groupby('user_id')['over_100'].sum()Частые ошибки
- Забыть колонку после groupby → агрегирует все числовые
- transform vs agg — разные результаты по размеру
- Slow apply — для простых операций быстрее встроенные
- Забыть reset_index — MultiIndex потом путает
Связанные темы
FAQ
groupby или pivot_table?
Для одной агрегации — groupby. Для wide-формата — pivot_table.
transform vs agg?
Transform возвращает len(df). Agg — len(groups).
Тренируйте pandas — откройте тренажёр с 1500+ задач для собесов.