Условие
Трафовые пользователи — привлечённые рекламными кампаниями (за каждого заплачено $X). Органические пользователи — пришли сами (бесплатные).
Подозрение: часть органики приходит от купленного трафа через виральные инструменты, word-of-mouth и т.п.
k-фактор — число людей, привлечённых одним пользователем.
Задачи:
- Посчитать k-фактор от трафовых пользователей — сколько органики они привлекают.
- Если k-фактор отличен от 0, посчитать k-фактор для денег — сколько трафового пользователя.
- Творческая часть: интересные закономерности в данных.
Данные:
ms— канал (ORGANIC/UA),cohort— дата привлечения,user_cnt— число новых пользователей в когорте,gross— суммарный доход.
Решение
Подход
Это классическая задача attribution lift. Прямое наблюдение «один UA-юзер привёл X органиков» невозможно (они не помечены как relate). Но можно через корреляцию между UA-objemamy и organic-объёмами по дням:
- Если UA→organic причинно: рост UA вчера → рост organic сегодня/завтра.
- В равновесии:
organic = base + k * UA, гдеbase— «чистая» органика без UA.
Реализация
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
df = pd.read_csv("data.csv", parse_dates=["cohort"])
# Pivot: дата × канал → user_cnt
piv = df.pivot_table(index="cohort", columns="ms", values="user_cnt", aggfunc="sum").fillna(0)
piv.columns = ["organic", "ua"] if list(piv.columns) == ["ORGANIC", "UA"] else piv.columns
piv = piv.sort_index()
# Визуализация
plt.figure(figsize=(14, 4))
plt.plot(piv.index, piv["UA"], label="UA")
plt.plot(piv.index, piv["ORGANIC"], label="Organic")
plt.legend(); plt.show()Регрессия для k-фактора
Простейшая модель: organic_t = a + k * UA_t + ε.
y = piv["ORGANIC"]
X = sm.add_constant(piv["UA"])
model = sm.OLS(y, X).fit()
print(model.summary())
# k-фактор = коэффициент при UA
k = model.params["UA"]
print(f"k-factor (organic per UA) = {k:.3f}")Если k > 0 статзначимо → каждый UA-юзер «приводит» k органических.
С лагом
Виральность — не моментальная. Юзер пришёл сегодня, привёл друга через 1–7 дней.
# UA с лагом 0..7 дней
for lag in range(0, 8):
piv[f"UA_lag{lag}"] = piv["UA"].shift(lag)
# Регрессия с распределённым лагом
lag_cols = [f"UA_lag{l}" for l in range(0, 8)]
X = sm.add_constant(piv[lag_cols].dropna())
y = piv["ORGANIC"].loc[X.index]
model_lag = sm.OLS(y, X).fit()
print(model_lag.summary())
total_k = sum(model_lag.params[c] for c in lag_cols if model_lag.params[c] > 0)
print(f"Total k-factor (sum across lags) = {total_k:.3f}")k-фактор для денег
piv_gross = df.pivot_table(index="cohort", columns="ms", values="gross", aggfunc="sum").fillna(0)
y_money = piv_gross["ORGANIC"]
X_money = sm.add_constant(piv_gross["UA"])
model_money = sm.OLS(y_money, X_money).fit()
k_money = model_money.params["UA"]
print(f"k-factor (organic gross per UA gross) = {k_money:.3f}")Интерпретация: на каждый органики.
Интересные закономерности (творческая часть)
-
Сезонность: organic в выходные часто выше, UA — стабильный (запускается «по бюджету»). Если корреляция UA→organic не учитывает день недели, она может быть искажена.
-
Декомпозиция: organic = base + viral + seasonal + noise. Виральная компонента — то, что коррелирует с UA с лагом.
-
CAC (customer acquisition cost) с учётом виральности:
- Без k-фактора:
CAC = UA_spend / UA_users. - С k-фактором:
effective_CAC = UA_spend / (UA_users + k * UA_users) = UA_spend / (UA_users * (1+k)). - Если k = 0.3, эффективный CAC на 23% ниже декларируемого.
- Без k-фактора:
-
ROAS-увеличение. Если
k > 0, тогда возврат на маркетинг растёт пропорционально, потому что считаем доход и от UA, и от привлечённой ими органики. -
Изменение k во времени. Сравнить
kза первое полугодие и за второе. Если k уменьшился — продукт теряет виральность (типичный знак увядания). -
Зависимость k от объёма: при больших UA-объёмах k может падать (saturation): «друзей у новых юзеров кончились», или «все потенциально интересующиеся уже зашли». Регрессия с логарифмическими преобразованиями.
Анализ / интерпретация
Возможный вывод:
k-фактор по людям ≈ 0.25 (на 1 UA-юзера приходит ~0.25 органика), статзначимо при p < 0.05. С учётом лага 0–7 дней, виральная attribution = 0.32. k-фактор по деньгам ≈ 0.18 — органические юзеры платят меньше, чем привлекаемые UA.
Ценовая корректировка CAC: эффективный CAC ниже декларируемого на ~25%. Это значит, что ROAS / LTV-CAC соотношения пересматриваются: можно покупать дороже.
Творческая находка: k-фактор падает с ростом UA-объёмов — saturation. На малых бюджетах k=0.4, на крупных k=0.15. Это означает, что наращивание UA дальше определённого уровня даёт диминишинг returns на органику.
Подводные камни
- Корреляция не причина. UA и organic могут оба коррелировать с третьим фактором (сезонность, релиз, новости). Нужны контроли — день недели, праздники, события.
- Reverse causality. Может быть, organic растёт → UA-команда делает выводы и тоже наращивает UA. Тогда корреляция искажена.
- Эндогенность UA-объёма: бюджет UA меняем мы по бизнес-логике, не случайно.
- Нестабильность регрессии при коллинеарности lag-переменных. Используйте Almon-lag или ridge.
- «Базовая органика» (без UA). Без неё k-фактор не вычленяется. Если у вас нет периодов с UA = 0 — модель будет переоценивать k.
- k > 0 не достаточен — нужен test of significance. На малых выборках значимости может не быть.
- k-фактор ≠ MAU multiplier. Это число new users per UA, не «насколько игра больше».
- Гетерогенность между UA-каналами. Facebook привлекает другую аудиторию, чем Google. k разные.
Альтернативы
- Difference-in-differences на двух регионах с разной UA-активностью.
- Synthetic control: построить «контрольный регион» без UA как взвешенную комбинацию других.
- Geo-experiments: остановить UA в одном регионе на 2 недели и сравнить organic — это истинная оценка k.
Эталонный ответ
k-фактор: регрессия organic ~ UA (с лагами 0–7 дней). Коэффициент при UA = k.
k-фактор для денег: то же, но на gross-данных.
Интерпретация: k показывает «бесплатных» юзеров, привлекаемых UA. Эффективный CAC = spend / ((1+k) * UA_users).
Главное предостережение: корреляция ≠ причина. Для honest k-фактора нужен geo-experiment (остановить UA в части регионов и сравнить organic).