Короткий ответ
Нужно для каждого пользователя найти дату регистрации и проверить, есть ли у него событие в интересующий день (например, day+7), а затем усреднить этот признак по всем пользователям когорты.
Как это работает подробнее
объединяем таблицу регистраций с таблицей событий, вычисляем разницу в днях между датой события и датой регистрации, создаём булев признак "был активен на day N" и усредняем по когорте.
Пример кода
retention.py
import pandas as pd
users = pd.DataFrame({
'user_id': [1, 2, 3, 4],
'reg_date': pd.to_datetime(['2024-03-01']*4)
})
events = pd.DataFrame({
'user_id': [1, 1, 2, 4],
'event_date': pd.to_datetime(['2024-03-01', '2024-03-08', '2024-03-02', '2024-03-08'])
})
merged = users.merge(events, on='user_id', how='left')
merged['day_diff'] = (merged['event_date'] - merged['reg_date']).dt.days
d7_active = merged.loc[merged['day_diff'] == 7, 'user_id'].unique()
d7_retention = len(d7_active) / users['user_id'].nunique()
print(d7_retention) # 0.5 (пользователи 1 и 4 из 4)Что использовать на практике
- Применение. в pandas 2.x при работе с датами важно явно приводить столбцы к
datetime64, а при объединении больших таблиц проверять, не дублируются ли строки после merge (это завышает метрику); в pandas 2.x с включённым copy-on-write операции присваивания на срезах ведут себя иначе, чем в pandas 1.x — лучше избегать cepnых chained assignments. - Проверка или пример. Проверка: d7_retention должен лежать в [0;1]; пересчитать вручную по небольшому датасету.
Подводные камни
- Частая ошибка. считают retention как долю от общего числа событий, а не от числа уникальных пользователей когорты; не фильтруют дубликаты событий на один день для одного пользователя, из-за чего один активный пользователь может задвоиться после merge.