Все материалы
Продуктовая аналитикагайдсредний

Корреляция и причинность: как проверить связь до того, как назвали её причиной

Разбор на учебной базе курса: связь «создал отчёт — дольше остаётся» выглядит убедительно и статистически значима, но полностью объясняется каналом привлечения. Как это увидеть в SQL и что делать дальше.

КПКейсПрактика22 июля 2026 г.14 мин

Почти в каждом продукте находится действие, после которого пользователи выглядят лучше: включили уведомления, создали первый отчёт, пригласили коллегу. Разница в удержании между теми, кто это сделал, и остальными обычно большая и легко считается одним запросом. Дальше происходит подмена: связь называют эффектом и ставят задачу «довести до этого действия всех». Ниже — разбор одной такой связи на учебной базе SQL-курса, где видно, откуда берётся разница и как она исчезает.

Коротко

Корреляция говорит, что две величины меняются вместе. Причинность требует ответа на другой вопрос: что было бы с теми же пользователями без этого действия. Данные наблюдений на этот вопрос сами по себе не отвечают.

  • Статистическая значимость не спасает: разница может быть надёжной и при этом целиком созданной третьей переменной.
  • Первый шаг проверки — не регрессия, а разбивка по составу групп: кто в них попал и в каких долях.
  • Люди выбирают действия не случайно, поэтому сравнение «сделал / не сделал» почти всегда сравнивает разных людей.
  • Контроль переменных помогает не всегда: некоторые контроли создают смещение, а не убирают его.
  • Если решение дорогое, нужен эксперимент или квазиэкспериментальный дизайн, а не более сложная модель на тех же данных.

Связь, которая выглядит убедительно

В учебной базе курса 5000 пользователей и события первых трёх недель. Возьмём привычную продуктовую гипотезу: пользователи, создавшие первый отчёт, активнее остальных. Мерить будем числом разных дней, в которые человек открывал приложение.

Запрос простой, и результат ровно такой, какого ждёт продуктовая команда: 11,37 активного дня против 10,33. Разница — один день на пользователя, десять процентов сверху.

На этом месте обычно и появляется вывод «нужно довести до первого отчёта всех новых пользователей». Он кажется тем более обоснованным, что данные не выборочные, а полные: посчитаны все 5000 человек.

Активность в первые три недели
ГруппаПользователейАктивных дней в среднем
Создали отчёт200111,37
Не создали299910,33
Разница+1,04 дня (+10,0%)
Наивное сравнение: создал отчёт против не создал
WITH flags AS (
  SELECT
    u.user_id,
    u.channel,
    max(CASE WHEN e.event_name = 'report_created' THEN 1 ELSE 0 END) AS made_report,
    count(DISTINCT CASE WHEN e.event_name = 'app_open'
                        THEN date_trunc('day', e.event_time) END)     AS active_days
  FROM users u
  LEFT JOIN events e USING (user_id)
  GROUP BY 1, 2
)
SELECT
  made_report,
  count(*)                  AS users,
  round(avg(active_days), 2) AS avg_active_days
FROM flags
GROUP BY 1
ORDER BY 1;

Статистика подтверждает разницу — и это ничего не меняет

Первое, что делают с такой находкой, — проверяют, не случайна ли она. Проверка проходит с запасом: при стандартных отклонениях 3,35 и 3,57 дня стандартная ошибка разницы равна 0,099, то есть t ≈ 10,5, а 95% доверительный интервал — от +0,84 до +1,23 дня. Ни о какой случайности речи нет.

Именно здесь чаще всего и теряется осторожность. Значимость отвечает на вопрос «могла ли такая разница возникнуть из случайного шума». Она ничего не говорит о том, почему группы отличаются. Тест не знает, что группы собраны не жребием, а решением самих пользователей, и на это нечувствителен.

Полезная привычка: увидев маленькое p-value в наблюдательном сравнении, спрашивать не «надёжна ли разница», а «чем ещё эти две группы отличаются друг от друга».

Что проверяет значимость

p-value отвечает на вопрос о случайности, а не о причине. Систематическое различие между группами оно только подтвердит — тем увереннее, чем больше данных.

Разбивка по каналу: разница исчезает

Прежде чем строить модели, стоит посмотреть на состав групп. В базе четыре канала привлечения, и они сильно различаются по вовлечённости: пользователи из referral активны в среднем 13,67 дня, из organic — 12,68, из partner — 10,14, из paid_search — всего 6,84.

Те же каналы различаются и по доле создавших отчёт: referral — 51,3%, organic — 45,5%, partner — 40,3%, paid_search — 25,9%. Получается, что канал влияет и на действие, и на результат. Это и есть третья переменная в чистом виде.

Теперь сравним внутри каждого канала — то есть среди людей, пришедших одинаковым путём. Разница не просто уменьшается: она пропадает и слегка меняет знак. В referral 13,61 против 13,72, в organic 12,64 против 12,72, в partner 10,11 против 10,16, в paid_search 6,79 против 6,86.

Ни в одном канале создание отчёта не связано с большей активностью. Весь наблюдавшийся плюс был разницей состава: среди создавших отчёт 39,8% пришли из organic и 25,6% из referral, а среди остальных — 31,8% и 16,2%, зато 37,0% из слабого paid_search против 19,4%.

То же сравнение внутри каналов
КаналПользователейС отчётомБез отчётаРазница
referral100013,6113,72−0,11
organic175012,6412,72−0,08
partner75010,1110,16−0,05
paid_search15006,796,86−0,07
Средняя активность по каналам

Каналы различаются вдвое. Группа «создали отчёт» просто состоит из более сильных каналов.

Активных дней

Как посчитать разницу при одинаковом составе

Чтобы не читать четыре строки таблицы глазами, разницу сводят в одно число: считают её внутри каждого канала, а затем усредняют с весами по размеру канала. Приём называется прямой стандартизацией и отвечает на вопрос «какой была бы разница, если бы обе группы имели одинаковый набор каналов».

Для нашего примера получается −0,08 дня: 10,70 против 10,78. Исходный плюс в один день исчез полностью. Вывод «первый отчёт удерживает» не подтверждается — по крайней мере, этими данными.

Стандартизация не превращает наблюдение в эксперимент. Она убирает влияние только того фактора, который вы назвали и измерили. Если бы вместе с каналом действовала мотивация, устройство или тариф, поправка на канал их бы не тронула.

Стандартизованная разница
Δ = Σ nᵢ · (aᵢ − bᵢ) / Σ nᵢ

aᵢ и bᵢ — средние в группах внутри слоя i, nᵢ — размер слоя. Веса берут из общей популяции, а не из одной группы.

Разница, взвешенная по размеру каналов
WITH flags AS (
  SELECT
    u.user_id,
    u.channel,
    max(CASE WHEN e.event_name = 'report_created' THEN 1 ELSE 0 END) AS made_report,
    count(DISTINCT CASE WHEN e.event_name = 'app_open'
                        THEN date_trunc('day', e.event_time) END)     AS active_days
  FROM users u
  LEFT JOIN events e USING (user_id)
  GROUP BY 1, 2
),
per_channel AS (
  SELECT
    channel,
    count(*)                                              AS n,
    avg(CASE WHEN made_report = 1 THEN active_days END)   AS with_report,
    avg(CASE WHEN made_report = 0 THEN active_days END)   AS without_report
  FROM flags
  GROUP BY 1
)
SELECT round(sum(n * (with_report - without_report)) / sum(n), 2) AS adjusted_diff
FROM per_channel;

Три способа получить связь без причины

Разобранный случай — самый частый, но не единственный. Полезно держать в голове три механизма и проверять их по очереди, потому что лечатся они по-разному.

Третья переменная действует на оба конца связи, как канал в примере выше. Обратная причинность переставляет местами причину и следствие: не приглашения удерживают команду, а те, кто уже собирается остаться, зовут коллег. Отбор в выборку создаёт связь там, где её нет вовсе: если смотреть только на активных пользователей, любые два фактора успеха начнут выглядеть враждебными друг другу — слабость по одному компенсируется силой по другому, иначе человек в выборку не попал бы.

Третий механизм обычно самый неожиданный, потому что он возникает не из данных, а из фильтра в запросе. Условие вида «только оплатившие» или «только дожившие до 30-го дня» — уже отбор, и он способен перевернуть знак связи.

  • Третья переменная: и действие, и результат зависят от общего фактора. Лечится разбивкой или поправкой — если фактор известен и измерен.
  • Обратная причинность: следствие принято за причину. Проверяется временем — что случилось раньше и с каким лагом.
  • Отбор в выборку: фильтр в запросе связывает независимые вещи. Лечится только сменой выборки, поправка тут не помогает.

Почему «добавить контроль» — не универсальное лекарство

После первой встречи с третьей переменной возникает соблазн добавить в регрессию все доступные признаки: чем больше контролей, тем чище оценка. Это неверно, и два случая портят результат систематически.

Первый — переменная после воздействия. Если мы изучаем влияние онбординга на оплату и добавляем контролем «дошёл до второго экрана», то отбираем у онбординга ровно тот путь, которым он и работает. Оценка эффекта становится меньше настоящей, притом выглядит аккуратнее.

Второй — общее следствие. Контроль по переменной, на которую влияют и причина, и результат, создаёт связь между ними, даже если её не было. Именно так фильтр «только активные» превращает независимые факторы в отрицательно связанные.

Отсюда рабочее правило: контроли выбирают до расчёта и по смыслу — что произошло раньше воздействия и могло повлиять на обе стороны. Список признаков, доступных в таблице, таким критерием не является.

Что делать с переменной
ПеременнаяКогда возниклаДействие
Канал, устройство, тариф на входедо действияконтролировать или разбивать
Шаг внутри воронкипосле действияне контролировать, смотреть отдельно
Признак активности, факт оплатыследствие обоихне фильтровать по ней выборку
Неизмеренная мотивациядо действияпоправкой не берётся — нужен эксперимент

Что меняет рандомизация

В той же базе есть эксперимент с онбординговым чеклистом, и разница между ним и предыдущим сравнением — не в математике, а в том, кто распределял людей по группам. Здесь это делал жребий, а не сами пользователи.

Проверить работу жребия можно тем же способом, каким мы нашли проблему: посмотреть состав групп. Из organic в контроле 598 человек, в тестовой 573; из paid_search — 499 и 488; из referral — 329 и 335; из partner — 230 и 267. Каналы разложились ровно, и это не совпадение, а свойство случайного распределения.

Конверсия в активацию: 18,60% в контроле (308 из 1656) против 29,16% с чеклистом (485 из 1663). Разница 10,6 п.п., z ≈ 7,1, 95% интервал — от 7,7 до 13,4 п.п. Формально это такая же значимая разница, как и в первом сравнении. Содержательно — совсем другая: здесь мы знаем, что группы отличались только чеклистом, потому что всё остальное распределял случай.

Разница в том, что нужно допустить. Для эксперимента — что сплит корректен и метрика измерена одинаково; это проверяемо. Для наблюдения — что не осталось ни одного неучтённого фактора; это не проверяется в принципе.

Рандомизированное сравнение: конверсия в активацию

Учебный эксперимент той же базы. Каналы в группах сбалансированы жребием, поэтому разницу можно отнести к чеклисту.

Конверсия, %

Если эксперимент невозможен

Эксперимент ставят не всегда: изменение может быть общим для всех, слишком дорогим или уже случившимся. Тогда работают с дизайном наблюдения, и каждый вариант держится на своём допущении, которое нужно называть вслух.

Сравнение до и после у затронутой и незатронутой групп снимает общий тренд, но требует, чтобы без вмешательства группы двигались параллельно — это видно на истории до события и проверяется глазами. Резкий порог в правиле (скидка от определённой суммы, лимит по возрасту аккаунта) позволяет сравнить тех, кто оказался чуть выше и чуть ниже границы: рядом с порогом попадание в группу почти случайно. Внешний толчок вроде поэтапной раскатки по регионам иногда заменяет жребий.

Эти дизайны сильнее простого сравнения групп, но слабее эксперимента, и их результат корректно подавать вместе с допущением: «при условии, что без редизайна обе когорты двигались бы одинаково, эффект составил…». Такая оговорка не ослабляет вывод, а показывает, где он сломается.

  • До/после с контрольной группой — допущение о параллельных трендах, проверяется по истории.
  • Разрыв на пороге правила — допущение о непрерывности всего остального в точке порога.
  • Поэтапная раскатка — допущение, что порядок этапов не связан с результатом.
  • Поправка на наблюдаемые факторы — допущение, что неучтённых больше нет; самое сильное и самое частое.

Как написать вывод, который не превратится в дорогое решение

Разница между честной и опасной формулировкой — не в осторожности тона, а в том, названо ли сравнение. «Первый отчёт повышает удержание на 10%» — утверждение об эффекте. «Пользователи, создавшие отчёт, активнее на один день, но это различие каналов: внутри каждого канала разницы нет» — описание данных, из которого сразу видно следующий шаг.

Хорошая запись держит три части: что сравнивали, что осталось от разницы после поправки на известные факторы и какой шаг даст ответ на причинный вопрос. Третья часть важнее первых двух: она превращает «мы не знаем» в план.

Для нашего примера это выглядит так: «Связь между первым отчётом и активностью полностью объясняется каналом привлечения — внутри каналов разница нулевая. Продвижение отчёта на онбординге не обосновано этими данными. Проверить эффект можно за две недели, показав подсказку про отчёт половине новых пользователей».

Формулировки
ОпасноТочнее
Отчёт повышает удержание на 10%В группе с отчётом активность выше на 1 день
Метрика значима, эффект доказанРазница устойчива, но группы различаются по каналам
Мы контролировали все факторыПоправка сделана на канал; мотивация не измерена
Нужно довести до отчёта всехНужен тест подсказки на половине новых пользователей

Проверка перед выводом

Список короткий и проходится за один заход. Он не заменяет причинный анализ, но отсекает большую часть выводов, которые разваливаются на первом же вопросе.

  • Кто попал в группы и по какому решению — своему или чужому.
  • Чем ещё группы отличаются: канал, устройство, тариф, дата прихода.
  • Что было раньше по времени — действие или результат.
  • Есть ли в запросе фильтр, который сам создаёт отбор.
  • Что останется от разницы после разбивки по главному фактору.
  • Какой эксперимент ответил бы на вопрос и сколько он стоит.
Продолжить чтение
Вся библиотека
Продуктовая аналитика24 июля 2026 г.12 мин
Два горизонтальных интервала: длинный и заметно более короткий.

Доверительный интервал: как показать, насколько точна ваша цифра

Что означает 95% доверительный интервал для конверсии и разницы конверсий, как его посчитать, почему он важнее p-value и какая формулировка про него неверна.

Читать материал
Продуктовая аналитика1 августа 2026 г.12 мин
Две пересекающиеся кривые, область за порогом закрашена.

Статистическая мощность: почему тест не находит эффект, который есть

Что такое мощность A/B-теста, как она связана с размером выборки и MDE, как посчитать нужное число участников и почему «незначимо» на слабом тесте ничего не доказывает.

Читать материал