← Назад к вопросам
Как рассчитать Retention Rate на 3 и 7 день?
2.0 Middle🔥 131 комментариев
#Аналитика и метрики
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Расчёт Retention Rate на 3 и 7 день
Retention Rate (коэффициент удержания) — это процент пользователей, которые вернулись в приложение на определённый день после первого использования. Это критическая метрика для оценки здоровья приложения. Я расскажу, как её считать.
Понимание Retention Rate
Определение:
- Cohort: Группа пользователей, которые установили приложение в один день
- Retention Day 1 (D1): % пользователей из cohortа, которые вернулись на день 1
- Retention Day 3 (D3): % пользователей, которые были активны на день 3 после установки
- Retention Day 7 (D7): % пользователей, активные на день 7 после установки
Формула:
Retention Day N = (Количество уникальных пользователей активных на день N) / (Общее количество пользователей в cohortе) × 100%
Шаг 1: Подготовка данных
Нужные события:
- Событие установки/первого запуска (install_date, first_open_date)
- События активности (app_open, click, purchase и т.д.)
SQL для получения данных:
-- Таблица с первым открытием приложения по пользователям
CREATE TABLE IF NOT EXISTS user_first_open AS
SELECT
user_id,
MIN(event_date) as install_date,
EXTRACT(DATE FROM MIN(event_timestamp)) as install_day
FROM events
WHERE event_name = first_open
GROUP BY user_id;
-- Таблица со всеми днями активности пользователей
CREATE TABLE IF NOT EXISTS user_daily_activity AS
SELECT DISTINCT
user_id,
EXTRACT(DATE FROM event_timestamp) as activity_date
FROM events
WHERE event_name IN (app_open, click, purchase, view)
GROUP BY user_id, activity_date;
Шаг 2: Расчёт Day 3 Retention
Логика:
- Найти всех пользователей, которые были активны в день 0 (install_date)
- Для каждого пользователя проверить, был ли он активен в день 3 (install_date + 3 дня)
- Посчитать процент активных пользователей на день 3
SQL запрос:
WITH install_cohorts AS (
-- Пользователи по дате установки
SELECT
user_id,
install_date
FROM user_first_open
WHERE install_date BETWEEN 2024-01-01 AND 2024-03-26
),
day3_retention AS (
-- Проверяем активность на день 3
SELECT
install_cohorts.user_id,
install_cohorts.install_date,
CASE
WHEN user_daily_activity.user_id IS NOT NULL THEN 1
ELSE 0
END as is_retained_day3
FROM install_cohorts
LEFT JOIN user_daily_activity
ON install_cohorts.user_id = user_daily_activity.user_id
AND install_cohorts.install_date + INTERVAL 3 days = user_daily_activity.activity_date
)
SELECT
install_date,
COUNT(*) as total_users,
SUM(is_retained_day3) as retained_users_day3,
ROUND(SUM(is_retained_day3)::NUMERIC / COUNT(*) * 100, 2) as retention_rate_day3
FROM day3_retention
GROUP BY install_date
ORDER BY install_date DESC;
Шаг 3: Расчёт Day 7 Retention
Та же логика, но проверяем активность на день 7:
WITH install_cohorts AS (
SELECT
user_id,
install_date
FROM user_first_open
WHERE install_date BETWEEN 2024-01-01 AND 2024-03-26
),
day7_retention AS (
-- Проверяем активность на день 7
SELECT
install_cohorts.user_id,
install_cohorts.install_date,
CASE
WHEN user_daily_activity.user_id IS NOT NULL THEN 1
ELSE 0
END as is_retained_day7
FROM install_cohorts
LEFT JOIN user_daily_activity
ON install_cohorts.user_id = user_daily_activity.user_id
AND install_cohorts.install_date + INTERVAL 7 days = user_daily_activity.activity_date
)
SELECT
install_date,
COUNT(*) as total_users,
SUM(is_retained_day7) as retained_users_day7,
ROUND(SUM(is_retained_day7)::NUMERIC / COUNT(*) * 100, 2) as retention_rate_day7
FROM day7_retention
GROUP BY install_date
ORDER BY install_date DESC;
Шаг 4: Объединённый отчёт (D3 и D7 вместе)
WITH install_cohorts AS (
SELECT
user_id,
install_date
FROM user_first_open
WHERE install_date BETWEEN 2024-01-01 AND 2024-03-26
),
day3_users AS (
SELECT DISTINCT user_id, install_date
FROM install_cohorts ic
INNER JOIN user_daily_activity ua
ON ic.user_id = ua.user_id
AND ic.install_date + INTERVAL 3 days = ua.activity_date
),
day7_users AS (
SELECT DISTINCT user_id, install_date
FROM install_cohorts ic
INNER JOIN user_daily_activity ua
ON ic.user_id = ua.user_id
AND ic.install_date + INTERVAL 7 days = ua.activity_date
)
SELECT
ic.install_date,
COUNT(DISTINCT ic.user_id) as total_users,
COUNT(DISTINCT d3.user_id) as retained_day3,
COUNT(DISTINCT d7.user_id) as retained_day7,
ROUND(COUNT(DISTINCT d3.user_id)::NUMERIC / COUNT(DISTINCT ic.user_id) * 100, 2) as retention_day3_percent,
ROUND(COUNT(DISTINCT d7.user_id)::NUMERIC / COUNT(DISTINCT ic.user_id) * 100, 2) as retention_day7_percent
FROM install_cohorts ic
LEFT JOIN day3_users d3 ON ic.user_id = d3.user_id AND ic.install_date = d3.install_date
LEFT JOIN day7_users d7 ON ic.user_id = d7.user_id AND ic.install_date = d7.install_date
GROUP BY ic.install_date
ORDER BY ic.install_date DESC;
Шаг 5: Реализация на Python (PySpark)
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count, sum, round, date_add, lit
from datetime import datetime, timedelta
spark = SparkSession.builder.appName("retention_analysis").getOrCreate()
# Чтение событий
events_df = spark.read.parquet("s3://bucket/events/")
# Шаг 1: Получить первое открытие каждого пользователя
first_opens = events_df.filter(
col("event_name") == "first_open"
).groupBy("user_id").agg(
F.min("event_date").alias("install_date")
).cache()
# Шаг 2: Получить все дни активности
user_activity = events_df.filter(
col("event_name").isin(["app_open", "click", "purchase", "view"])
).select("user_id", "event_date").distinct()
# Шаг 3: Расчёт Day 3 Retention
day3_retention = first_opens.join(
user_activity,
on=[
(first_opens.user_id == user_activity.user_id),
(date_add(first_opens.install_date, 3) == user_activity.event_date)
],
how="left"
).select(
first_opens.user_id,
first_opens.install_date,
(col("event_date").isNotNull()).alias("retained_day3")
)
# Шаг 4: Расчёт Day 7 Retention
day7_retention = first_opens.join(
user_activity,
on=[
(first_opens.user_id == user_activity.user_id),
(date_add(first_opens.install_date, 7) == user_activity.event_date)
],
how="left"
).select(
first_opens.user_id,
first_opens.install_date,
(col("event_date").isNotNull()).alias("retained_day7")
)
# Шаг 5: Объединить и посчитать процент
result = first_opens.join(
day3_retention.drop("install_date"),
on="user_id",
how="left"
).join(
day7_retention.drop("install_date"),
on="user_id",
how="left"
).groupBy("install_date").agg(
count("user_id").alias("total_users"),
sum("retained_day3").alias("retained_day3_count"),
sum("retained_day7").alias("retained_day7_count"),
round(sum("retained_day3") / count("user_id") * 100, 2).alias("retention_day3_percent"),
round(sum("retained_day7") / count("user_id") * 100, 2).alias("retention_day7_percent")
).orderBy(col("install_date").desc())
result.show()
# Сохранить результат
result.write.format("parquet").mode("overwrite").save("s3://bucket/retention_metrics/")
Важные замечания
1. Временные зоны:
- Убедись, что все даты в одной временной зоне (UTC)
- День определяется как midnight-to-midnight в нужной зоне (часто Moscow Time)
# ✅ Правильно: конвертируем в нужную зону
from pyspark.sql.functions import from_utc_timestamp
events_df = events_df.withColumn(
"event_date_msk",
from_utc_timestamp(col("event_timestamp"), "Europe/Moscow")
)
2. Граничные условия:
- D3 retention можно считать только для пользователей, установивших приложение 3+ дня назад
- Например, если сегодня 26 марта, можно считать D7 только для пользователей, установивших до 19 марта
# Фильтруем по дате установки
cutoff_date_d7 = datetime.now() - timedelta(days=7)
first_opens_valid = first_opens.filter(col("install_date") <= cutoff_date_d7)
3. Различные определения активности:
- Strictest: пользователь открыл приложение (app_open)
- Moderate: пользователь совершил любое действие (click, view)
- Loosest: пользователь был в сессии (даже безактивно)
Типичные значения Retention Rate
| День | Здоровое приложение | Среднее | Низкое |
|---|---|---|---|
| D1 | 40-60% | 20-40% | <20% |
| D3 | 25-35% | 15-25% | <15% |
| D7 | 15-25% | 10-15% | <10% |
Вывод
Расчёт Retention Rate — стандартная задача в аналитике. Ключ — правильно определить когорту (по дате первого открытия) и проверить активность в определённые дни. SQL и PySpark реализации позволяют масштабировать эту метрику для млн пользователей.