Если две метрики двигаются вместе — это ещё не значит, что одна двигает другую. Корреляция сообщает только «эти числа связаны», а причинность отвечает на другой вопрос: «что произойдёт, если я вмешаюсь и поменяю одну из них». Разница между этими двумя утверждениями огромна, и именно на ней спотыкается большинство продуктовых решений. Нельзя выкатить фичу на основании «у тех, кто ей пользуется, retention выше», потому что за видимой связью почти всегда прячется одно из трёх: третья общая причина, обратный эффект или чистая случайность. Дальше разберу каждый случай на реальных продуктовых примерах и покажу, чем аналитик может подтверждать причинность, а не только рисовать красивые точки на графике.
Что вообще значит «корреляция»?
Корреляция — это мера того, насколько две величины меняются согласованно. Самый ходовой инструмент — коэффициент Пирсона: он лежит в диапазоне от -1 до +1, где +1 означает идеальную линейную связь вверх, -1 — идеальную вниз, а 0 — отсутствие линейной связи. Есть ещё Спирмен для монотонных, но не обязательно линейных зависимостей — он работает на рангах и устойчивее к выбросам.
Посчитать её — дело одной строчки. В pandas:
# df: одна строка на пользователя
corr = df['sessions_per_week'].corr(df['orders_count'])
print(round(corr, 3)) # например 0.61 — заметная положительная связь
И вот тут кроется ловушка. Число 0.61 выглядит убедительно, его легко вставить в презентацию и сказать «сессии влияют на заказы». Но коэффициент не знает ничего про механизм. Он видит только два столбца и считает их совместное поведение. Всё остальное — интерпретация, которую добавляем мы, и именно на этом шаге рождаются ошибки. Если хотите потренировать сам расчёт на данных, это удобно делать в Python-тренажёре — там можно гонять corr() на реальных датафреймах, а не на игрушечных примерах.
Почему связь двух метрик не доказывает причинность?
Потому что у наблюдаемой связи есть минимум три альтернативных объяснения, и ни одно из них не «A вызывает B».
Первое — конфаундер: есть третья переменная C, которая порождает и A, и B одновременно, а между собой они напрямую не связаны. Второе — обратная причинность: на самом деле B вызывает A, а не наоборот, и мы просто перепутали направление стрелки. Третье — совпадение: на большом количестве метрик всегда найдутся пары, которые случайно двигаются в такт, особенно если обе растут во времени.
Ключевая мысль: наблюдательные данные показывают, что происходит, когда мы ничего не делаем. Причинность — про то, что произойдёт, когда мы вмешаемся. Это разные вопросы, и второй почти никогда нельзя вытащить из первого без дополнительных допущений или без эксперимента. Аналитик, который держит это в голове, экономит компании кучу денег на фичах, которые «по данным работали», а после раскатки не дали ничего.
Что такое конфаундер и почему он всё ломает?
Конфаундер — это скрытая общая причина. Классический продуктовый пример: пользователи, которые включили какую-нибудь фичу вроде тёмной темы или расширенной аналитики, показывают retention на 15 пунктов выше остальных. Соблазн сделать вывод «фича удерживает» огромен. Но подумайте, кто вообще заходит в настройки и что-то там включает. Это уже вовлечённые, «прогретые» пользователи. Их высокая вовлечённость — и есть конфаундер: она одновременно поднимает вероятность включить фичу и вероятность остаться в продукте.
Нарисуем это стрелками словами: вовлечённость → включение фичи, и вовлечённость → retention. Прямой стрелки «фича → retention» может не быть вовсе, а корреляция между ними всё равно будет большой и положительной.
Проверить наличие такого расслоения можно прямо запросом, сравнив retention внутри групп по уровню активности:
SELECT
CASE WHEN u.sessions_30d >= 20 THEN 'power' ELSE 'casual' END AS segment,
u.feature_enabled,
AVG(u.retained_next_month) AS retention
FROM users u
GROUP BY segment, u.feature_enabled
ORDER BY segment, u.feature_enabled;
Если внутри каждого сегмента разница между feature_enabled = 1 и = 0 резко схлопывается — значит, почти всю «магию» фичи объяснял уровень активности, а не сама фича. Собрать такой разрез легко в SQL-тренажёре, а если группировки и агрегаты пока даются тяжело — начните с базового курса SQL, там как раз разбираются GROUP BY и условная агрегация.
А если причинность работает в обратную сторону?
Обратная причинность — когда мы уверенно ставим стрелку не в ту сторону. Тут любимый пример — пуш-уведомления. Видим, что у пользователей с включёнными пушами retention выше, и делаем вывод «пуши удерживают». Но что если наоборот: люди, которые и так собирались остаться и любят продукт, чаще оставляют пуши включёнными, а те, кто уже одной ногой на выходе, первым делом их отключают. Тогда retention «вызывает» пуши, а не пуши retention.
Ещё пример из e-commerce: пользователи, которые чаще открывают приложение, покупают больше. Открытие приложения повышает покупки — или намерение купить заставляет открывать приложение? Скорее всего работают оба направления сразу, и в наблюдательных данных их не разделить.
Признак, что стоит заподозрить обратную причинность: когда «причина» — это добровольное действие пользователя, которое он делает, потому что уже заинтересован. Подписка, включение настройки, добавление в избранное. Всё, что человек выбирает сам, тащит за собой отбор, и стрелка легко разворачивается. Именно такие вопросы — «в какую сторону работает связь» — любят задавать на собеседованиях аналитика, и правильный ответ почти всегда начинается со слов «а как пользователи попадали в эту группу».
Откуда берутся ложные корреляции?
Ложная корреляция — это когда связь есть в цифрах, но за ней нет вообще никакого содержательного механизма, ни прямого, ни через конфаундер. Чаще всего они вылезают на временных рядах. Две метрики, которые обе растут месяц к месяцу, автоматически будут скоррелированы, даже если между ними ноль общего: число регистраций на сайте и число проданных электросамокатов в городе. Обе растут с сезоном и с общим ростом рынка — вот и корреляция 0.9.
Второй источник — сезонность как общий драйвер. Продажи мороженого и число тепловых ударов коррелируют, но одно не вызывает другое: их обоих гонит жара. В продукте роль «жары» играет, например, маркетинговая кампания, которая одновременно подняла и трафик, и конверсию — и теперь кажется, что трафик поднял конверсию.
Третий, самый коварный — множественные сравнения. Если у вас 40 метрик и вы считаете корреляции всех пар, это почти 800 коэффициентов. Даже на случайных данных десятки из них окажутся «значимыми» просто по теории вероятностей. Поэтому когда кто-то приносит одну эффектную корреляцию, первый вопрос — сколько гипотез перебрали, прежде чем нашли эту. Практический приём против таких артефактов: считать связь не на уровнях, а на приращениях (разностях), и всегда держать в голове сезонность. Разобрать десяток таких кейсов из реальной аналитики можно в подборке кейсов.
Пользователи фичи активнее — значит фича работает?
Нет, и это самый частый неверный вывод в продуктовой аналитике, так что вынесу его отдельно. Проблема называется selection bias — смещение отбора. Группа «пользователи фичи» собралась не случайно: люди сами решили ей воспользоваться, и это решение скоррелировано со всем остальным — активностью, стажем в продукте, платящестью.
Представьте, что сравниваете средний DAU-вклад или число заказов у тех, кто пользуется рекомендациями, и у тех, кто нет. Разница будет, и большая. Но группы несравнимы: в первой уже собрались самые активные. Формально мы сравниваем яблоки с апельсинами и приписываем разницу фиче.
Быстрая диагностика — посмотреть, как группы различались ДО появления фичи:
# сравниваем группы по метрике, снятой до релиза фичи
before = df.groupby('used_feature')['orders_prev_month'].mean()
print(before)
# used_feature
# 0 2.1
# 1 5.8 <- эти пользователи покупали больше ещё ДО фичи
Если «до» между группами уже пропасть, то и «после» ничего не доказывает — они и без фичи разъехались бы. Этот приём (сравнение на предпериоде) — дешёвый способ поймать смещение до того, как оно попадёт в отчёт руководству. Потренировать саму механику фильтрации и агрегации по группам можно на практических задачах.
Как приблизиться к причинности: A/B, DiD и PSM
Раз наблюдательные данные врут, нужны методы, которые либо создают сравнимые группы, либо честно учитывают их несравнимость.
Золотой стандарт — A/B-тест. Мы случайно делим пользователей на контроль и вариант и включаем фичу только одной группе. Рандомизация в среднем уравнивает всё — и вовлечённость, и стаж, и то, что мы даже не измеряли. Поэтому разницу в метрике после теста можно приписывать самой фиче. Если есть возможность поставить эксперимент — ставьте его, остальное это костыли для случаев, когда эксперимент невозможен.
Когда рандомизировать нельзя (фичу уже раскатили на всех, изменение пришло извне, регион переключили целиком) — берут квазиэкспериментальные методы.
Difference-in-Differences (DiD) сравнивает не уровни, а изменения. Идея: берём группу, на которую подействовало изменение, и похожую группу, на которую нет, и смотрим не «насколько они отличаются после», а «насколько по-разному они изменились». Считаем разницу до-после в тестовой группе, вычитаем такую же разницу до-после в контрольной — то, что осталось, и есть эффект. Ключевое допущение — parallel trends: без вмешательства обе группы двигались бы параллельно.
-- эффект = (test_after - test_before) - (control_after - control_before)
SELECT
group_type,
AVG(CASE WHEN period = 'before' THEN metric END) AS before_avg,
AVG(CASE WHEN period = 'after' THEN metric END) AS after_avg
FROM did_data
GROUP BY group_type;
Propensity Score Matching (PSM) решает задачу несравнимых групп иначе: для каждого пользователя из «обработанной» группы модель оценивает вероятность (propensity) попасть в неё по наблюдаемым признакам, а потом мы подбираем ему пару из контроля с такой же вероятностью. Грубо говоря, к каждому активному пользователю фичи ищем такого же активного пользователя без фичи и сравниваем только их. Слабое место честно назову: PSM выравнивает только то, что мы измерили. Скрытый конфаундер, которого нет в данных, он не уберёт — в отличие от рандомизации.
Формулы и пошаговые примеры этих трёх методов есть в Python-справочнике, а типовые SQL-заготовки под предпериод и когорты — в SQL-справочнике.
Чем это отличается от парадокса Симпсона?
Их часто путают, но это не одно и то же. «Корреляция не значит причинность» — общий принцип: связь может быть, а причинного механизма нет. Парадокс Симпсона — частный и очень драматичный случай конфаундинга, когда добавление группирующей переменной не просто ослабляет связь, а разворачивает её знак.
Пример. Вариант B в A/B-тесте показывает конверсию выше, чем A, если смотреть на общий итог. Но стоит разбить по платформам — и вдруг на мобильных A лучше B, и на десктопе A лучше B тоже. Как так: B лучше в целом, но хуже в каждом сегменте? Потому что в вариант B случайно попало больше десктопного трафика, а десктоп в принципе конвертит лучше. Микс сегментов перевесил реальный эффект.
Итого: A = 8%, B = 10% -> кажется, B лучше
Мобильные: A = 6%, B = 5% -> A лучше
Десктоп: A = 14%, B = 12% -> A лучше
Мораль Симпсона практическая: всегда проверяйте, не разъезжается ли вывод при разбиении на осмысленные сегменты. Если агрегат говорит одно, а все сегменты — другое, верить нужно сегментам (при условии, что сегментирующая переменная действительно важна). А общий принцип про причинность шире: он предупреждает, что даже чистая, устойчивая при любом разбиении корреляция всё равно может не быть причинной.
Как встроить проверку на причинность в работу аналитика
Соберу это в короткий чек-лист, который прогоняю в голове каждый раз, когда вижу связь двух метрик.
Первое — спросить, как люди попали в группы. Если распределение было добровольным, а не случайным, дальше по умолчанию считаем, что там смещение отбора. Второе — придумать конфаундер: какая третья причина могла бы породить обе метрики. Если придумывается за десять секунд, наблюдательному выводу грош цена. Третье — проверить направление стрелки: не могла ли «следствие» на самом деле вызывать «причину». Четвёртое — посмотреть на предпериод: различались ли группы до вмешательства. Пятое — прикинуть, можно ли поставить A/B, и если нет — какой квазиэксперимент (DiD, PSM) ближе всего к вашей ситуации.
Ни один из этих шагов не требует сложной математики — только привычки не верить графику на слово. Именно это отличает аналитика, чьим выводам доверяют, от того, кто приносит красивые корреляции, разваливающиеся при первой раскатке.
Если хотите доводить эти навыки до автоматизма — на практике, а не в теории — в Pro-доступе открыты все задачи SQL-тренажёра и Python-тренажёра, полный справочник по причинному выводу с DiD и PSM, а также разборы кейсов с реальных собеседований, где как раз и просят отличить корреляцию от причинности. Это ровно тот навык, который на интервью проверяют в первую очередь.