Когортный анализ — что это, формула, пример SQL и Python

Когортный анализ — метод группировки пользователей по дате первой активности (когорте) и отслеживание их retention во времени. Главная техника продуктовой аналитики. На собесе спросят: «напиши SQL для cohort retention». Здесь — полный гайд с примерами SQL и Python.
Содержание (7 разделов)
  1. Что такое когорта
  2. Зачем нужен когортный анализ
  3. Формула retention
  4. SQL: cohort retention за 3 месяца
  5. Python pandas: тот же расчёт
  6. Типичные ошибки
  7. Визуализация cohort retention

Что такое когорта

Когорта — группа пользователей объединённая по дате первой активности (регистрации, первого заказа, установки app). Обычно — месячные когорты (январская когорта = все кто зарегался в январе).

Зачем нужен когортный анализ

Без когорт ты видишь усреднённую картину. С когортами — видишь паттерн:

Формула retention

Retention(t) для когорты C = доля юзеров когорты C активных в период t (с момента acquisition):

Retention(cohort=C, month_since=t) =
    (active_users_in_cohort_C_at_month_t) /
    (cohort_size_C)
    * 100%

Пример:
Январская когорта = 1000 юзеров (cohort_size)
Через 1 месяц активны = 400 → Retention_M1 = 40%
Через 3 месяца активны = 200 → Retention_M3 = 20%
Через 6 месяцев активны = 120 → Retention_M6 = 12%

SQL: cohort retention за 3 месяца

Самый частый SQL-вопрос с собеса. Считаем retention для каждой когорты по месяцам:

WITH cohorts AS (
  -- Cohort month = месяц первой активности
  SELECT
    user_id,
    DATE_TRUNC('month', MIN(event_date)) AS cohort_month
  FROM events
  GROUP BY user_id
),
activity AS (
  -- Все активные месяцы каждого юзера
  SELECT
    e.user_id,
    DATE_TRUNC('month', e.event_date) AS event_month,
    c.cohort_month,
    EXTRACT(MONTH FROM AGE(
      DATE_TRUNC('month', e.event_date),
      c.cohort_month
    )) AS months_since_acq
  FROM events e
  JOIN cohorts c USING (user_id)
)
SELECT
  cohort_month,
  months_since_acq,
  COUNT(DISTINCT user_id) AS active_users,
  ROUND(
    COUNT(DISTINCT user_id) * 100.0 /
    FIRST_VALUE(COUNT(DISTINCT user_id))
      OVER (PARTITION BY cohort_month ORDER BY months_since_acq),
    2
  ) AS retention_pct
FROM activity
WHERE months_since_acq <= 6
GROUP BY cohort_month, months_since_acq
ORDER BY cohort_month, months_since_acq;

Python pandas: тот же расчёт

Аналог на pandas — через groupby + transform + pivot:

import pandas as pd

def cohort_retention(events: pd.DataFrame) -> pd.DataFrame:
    # 1. Cohort month для каждого юзера
    events['cohort_month'] = events.groupby('user_id')['event_date'].transform('min').dt.to_period('M')
    events['event_month'] = events['event_date'].dt.to_period('M')

    # 2. Месяцев с момента acquisition
    events['months_since'] = (events['event_month'] - events['cohort_month']).apply(lambda x: x.n)

    # 3. Pivot: cohort × months_since → unique users
    cohort_table = events.groupby(['cohort_month', 'months_since'])['user_id'] \
        .nunique() \
        .unstack(fill_value=0)

    # 4. Retention % от cohort size (M0)
    cohort_sizes = cohort_table.iloc[:, 0]
    retention = cohort_table.divide(cohort_sizes, axis=0) * 100

    return retention.round(2)

Типичные ошибки

Что новички делают не так:

Визуализация cohort retention

Стандартное представление — cohort heatmap: строки = когорты, колонки = месяцы с момента acquisition, цвет = retention %. Темнее = лучше. Видишь паттерны: одни когорты лучше, другие хуже.

Частые вопросы

Зачем когорты вместо обычного retention?

Обычный retention — усреднённый по всем юзерам. Когорты показывают паттерн во времени: стало лучше или хуже для новых юзеров.

Какой период когорт выбрать?

Месячные — стандарт. Недельные — для быстрорастущих стартапов или анализа фич. Дневные — для коротких циклов (новости, app drop).

Что такое N1-retention?

Retention на N-й день / неделю / месяц после первой активности. N1 = retention на 1-й день после регистрации (стандарт mobile-приложений).

Когорты — это только для продукта?

Нет, применяется везде где есть пользователи и время: маркетинг (cohort LTV по каналам), кредиты (vintage analysis — когорты выдачи), HR (когорты сотрудников по месяцу найма).

Как считать retention если юзер делает 0 events некоторое время потом возвращается?

Зависит от definition. Чаще всего: активность в конкретном месяце N после acquisition. Returning user после паузы — считается активным в месяц возврата.

Начать практику бесплатно →