Собесов

Сценарий: построение когортной retention-таблицы в pandas

PythonАнализ событийСредняяMiddle

Условие

Дан events(user_id, ts). Построить когортный retention по неделям регистрации: процент пользователей, вернувшихся в неделю 1, 2, …, 12 после первой активности.

Решение

Подход

  1. Для каждого юзера — неделя его первой активности (cohort).
  2. Для каждой активности — её неделя.
  3. Разница недель = «возраст когорты».
  4. Pivot: cohort × week_offset → unique users / cohort_size.

Реализация

import pandas as pd
 
events['week'] = events['ts'].dt.to_period('W').dt.start_time
events['cohort'] = events.groupby('user_id')['week'].transform('min')
events['offset'] = ((events['week'] - events['cohort']).dt.days // 7).astype(int)
 
cohort_users = (
    events.groupby(['cohort', 'offset'])['user_id']
          .nunique()
          .reset_index(name='active')
)
 
cohort_size = cohort_users[cohort_users['offset'] == 0][['cohort', 'active']] \
                .rename(columns={'active': 'cohort_size'})
 
cohort_users = cohort_users.merge(cohort_size, on='cohort')
cohort_users['retention'] = cohort_users['active'] / cohort_users['cohort_size']
 
retention_matrix = cohort_users.pivot(index='cohort', columns='offset', values='retention')

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

import seaborn as sns
sns.heatmap(retention_matrix, annot=True, fmt='.0%', cmap='YlGnBu')

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

  1. Cohort = неделя первой активности; если в первой неделе у юзера 5 событий, retention в offset=0 всё равно 100% (он там по определению).
  2. Survivorship bias: для свежих когорт ещё мало недель пройдено — нижний треугольник пуст, но это не «упал retention», это «не дожило».
  3. Граница недели зависит от tz и от dt.to_period('W') (по умолчанию W-SUN). Зафиксируйте to_period('W-MON') для понедельной.
  4. nunique важно — пользователь, заглянувший дважды, считается раз.
  5. Для очень больших данных pivot может взорвать память — используйте polars или уменьшайте до интересующего слайса.

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

Cohort = неделя первого ивента, offset = (week − cohort)/7. Pivot cohort × offset с nunique(user_id), делить на cohort_size.

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

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

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