Задачи на когортный анализ на собеседовании

Зачем на собесе спрашивают когорты

Когортный анализ — главный инструмент продуктовой аналитики. Среднее врёт, когорты — нет. Если вы не умеете построить когортную таблицу в SQL / pandas — для продуктовой команды это дисквалификация.

Базовые понятия

  • Cohort — группа пользователей с общим началом (неделя регистрации, месяц первой покупки).
  • Cohort size — количество пользователей в когорте.
  • Cohort index / period — сколько времени прошло с когортного дня.
  • Retention table — матрица: строки — когорты, столбцы — периоды, значения — % удержанных.

Задача 1. Определение когорты

Как бы вы определили когорту для SaaS / e-commerce / игры?

  • SaaS: месяц первого платежа или неделя активации trial.
  • E-commerce: неделя первой покупки.
  • Игра: день регистрации (обычно короткий жизненный цикл).

На собесе: «когорта — это группировка по точке начала жизненного цикла. Выбор зависит от продукта».

Задача 2. Построить когортную таблицу retention в SQL

WITH cohort AS (
    SELECT user_id,
        DATE_TRUNC('month', MIN(event_time))::DATE AS cohort_month
    FROM events
    GROUP BY user_id
),
activity AS (
    SELECT c.user_id, c.cohort_month,
        DATE_TRUNC('month', e.event_time)::DATE AS active_month
    FROM cohort c
    JOIN events e USING (user_id)
),
labeled AS (
    SELECT cohort_month, active_month, user_id,
        EXTRACT(MONTH FROM AGE(active_month, cohort_month))::int AS period_num
    FROM activity
)
SELECT cohort_month, period_num, COUNT(DISTINCT user_id) AS active
FROM labeled
GROUP BY 1, 2
ORDER BY 1, 2;

Получаем long-format. Pivot на столбцы — через pandas или приложение.

Задача 3. Pandas-версия когортной таблицы

df['cohort'] = df.groupby('user_id')['date'].transform('min').dt.to_period('M')
df['period'] = df['date'].dt.to_period('M')
df['period_num'] = (df['period'] - df['cohort']).apply(lambda x: x.n)

cohort_pivot = (
    df.groupby(['cohort', 'period_num'])['user_id']
      .nunique()
      .unstack()
)
retention = cohort_pivot.divide(cohort_pivot[0], axis=0)

Получаем матрицу с retention в %.

Прокачать тему на реальных задачах удобно в боте @kariernik_bot — база вопросов собрана с собеседований в Яндексе, Авито, Ozon, Тинькофф.

Задача 4. LTV по когортам

WITH cohort AS (
    SELECT user_id, DATE_TRUNC('month', MIN(order_time))::DATE AS cohort_month
    FROM orders GROUP BY user_id
),
revenue AS (
    SELECT c.cohort_month,
        DATE_TRUNC('month', o.order_time)::DATE AS period_month,
        SUM(o.amount) AS rev,
        COUNT(DISTINCT c.user_id) OVER (PARTITION BY c.cohort_month) AS cohort_size
    FROM cohort c
    JOIN orders o USING (user_id)
    GROUP BY 1, 2, c.user_id
)
SELECT cohort_month,
    EXTRACT(MONTH FROM AGE(period_month, cohort_month))::int AS m,
    SUM(SUM(rev)) OVER (PARTITION BY cohort_month ORDER BY period_month) / MAX(cohort_size) AS ltv
FROM revenue
GROUP BY cohort_month, period_month;

Задача 5. Сравнение когорт до и после релиза

В марте 2026 выкатили редизайн онбординга. Сравните retention когорт до и после.

cohort_before = df[df['cohort'] < '2026-03-01']
cohort_after = df[df['cohort'] >= '2026-03-01']

for c in [cohort_before, cohort_after]:
    retention = calc_retention(c)
    print(retention.mean(axis=0))  # среднее по когортам

На собесе интерпретируют: «если retention D7 у новых когорт выше на 5 п.п. — релиз сработал».

Задача 6. Weekly cohorts vs Monthly cohorts

Для молодого продукта (3 месяца) лучше weekly — больше детализации. Для зрелого (2+ года) — monthly или quarterly, чтобы не шуметь.

Задача 7. Тепловая карта когорт

import seaborn as sns
import matplotlib.pyplot as plt

plt.figure(figsize=(12, 8))
sns.heatmap(retention, annot=True, fmt='.0%', cmap='YlGnBu')
plt.title('Cohort Retention')
plt.show()

На собесе просят: «как визуализировать?» Ответ — тепловая карта.

Задача 8. Когорты по каналу привлечения

SELECT channel, period_num, AVG(retention) AS avg_retention
FROM cohort_table
GROUP BY channel, period_num
ORDER BY channel, period_num;

Сразу видно — Organic обычно удерживает лучше, Performance — хуже.

На собесе такие штуки часто спрашивают. Быстрый способ довести до автоматизма — тренажёр в Telegram с задачами из реальных интервью.

Задача 9. Диагональ в когортной таблице

Если retention ухудшается по диагонали (одинаковая позиция в разных когортах) — это внешний эффект (сезонность, событие, кризис). Если только определённые когорты — это связанный с когортой триггер (например, рекламная кампания плохого качества).

Задача 10. Когорты для A/B

# Разделим пользователей на A/B по дате регистрации ИЛИ по назначению
df['group'] = df['user_id'].apply(assign_group)  # 'A' или 'B'

for g in ['A', 'B']:
    cohort_ret = calc_retention(df[df['group'] == g])
    print(f"Group {g} D7: {cohort_ret[7].mean():.1%}")

Как тренироваться

Когортный анализ — на собесе любимая тема. Его спрашивают в Авито, Яндексе, Ozon, Wildberries. Нужно уметь построить и интерпретировать.

Тренажёр Карьерник содержит задачи на когорты: построение, сравнение, LTV по когортам, интерпретация. Каждая с разбором типичных ошибок.

Совет: всегда проговаривайте вслух «когорта у меня — месяц первой покупки» или другое. Это страхует от главной ошибки — неправильного определения когорты.

Читайте также

FAQ

Когорты по регистрации или по первой покупке?

Зависит от продукта. Для e-commerce обычно первая покупка (важен именно платёжный лайф-сайкл). Для freemium-SaaS — регистрация или активация trial. Главное — зафиксировать один тип и придерживаться.

Weekly или monthly cohorts?

Weekly для молодых продуктов (первые 1-2 года). Monthly для зрелых. Weekly даёт больше данных, monthly — стабильнее.

Сколько месяцев смотреть?

Хотя бы 3-6 месяцев для SaaS/e-commerce. Для игр обычно достаточно D1-D30. Чем длиннее временной горизонт, тем больше доверия к retention curve.

Как визуализировать когорты?

Тепловая карта — стандарт. Линии retention по когортам — альтернатива. На собесе ответ «heatmap with cohorts as rows» — правильный.