Собесов

Сценарий: groupby с несколькими агрегациями и переименованием колонок

PythonPandas базовый workflowЛёгкаяJunior

Условие

Дан датафрейм orders с колонками user_id, order_id, amount, city, ts. Нужно за один проход получить по каждому пользователю: число заказов, средний чек, медианный чек, сумму, дату последнего заказа и число уникальных городов. Колонки должны называться n_orders, mean_check, median_check, total, last_ts, n_cities.

Решение

Подход

groupby(...).agg(...) через named aggregation (синтаксис new_col=('source_col', 'func')). Это рекомендованный с pandas 0.25+ способ — он сразу даёт плоский индекс колонок без MultiIndex.

Реализация

import pandas as pd
 
result = (
    orders
    .groupby('user_id', as_index=False)
    .agg(
        n_orders=('order_id', 'nunique'),
        mean_check=('amount', 'mean'),
        median_check=('amount', 'median'),
        total=('amount', 'sum'),
        last_ts=('ts', 'max'),
        n_cities=('city', 'nunique'),
    )
)

Если нужна кастомная функция, передаём lambda:

.agg(p95=('amount', lambda s: s.quantile(0.95)))

Подводные камни

  1. Если использовать словарь agg({'amount': ['mean','sum']}) — получится MultiIndex колонок, и его придётся выравнивать result.columns = ['_'.join(c) for c in result.columns].
  2. nunique по order_id важно, если строки задвоены (например, после join-а с товарами); count посчитает позиции, а не уникальные заказы.
  3. as_index=False чтобы user_id остался колонкой, а не индексом.
  4. NaN в amount молча игнорируются mean/median/sum — если важно, заранее dropna или fillna(0).
  5. Для строковых дат max даст лексикографический максимум, а не хронологический — pd.to_datetime обязателен.

Эталонный ответ

groupby('user_id').agg(n_orders=('order_id','nunique'), mean_check=('amount','mean'), ...) — named aggregation даёт плоские колонки за один проход.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти