Difference-in-Differences простыми словами
SELECT COUNT(DISTINCT user_id) FROM orders, если у некоторых пользователей несколько заказов?Содержание:
Зачем это знать
Marketplace запустил фичу в одном городе, в другом нет — как измерить эффект? A/B-тест невозможен: нельзя пользователю одновременно «видеть и не видеть». На помощь приходит DiD — классика квази-экспериментальных методов.
На собесах в B2C / marketplace / delivery компаниях DiD — обязательный навык для middle+ аналитика.
Короткое объяснение
Difference-in-Differences сравнивает изменения в treatment и control группах до и после воздействия.
Effect = (Treatment_after - Treatment_before) - (Control_after - Control_before)Первая разница — что случилось у treatment. Вторая — что случилось у control (baseline trend). Разница разниц — чистый эффект.
Пример
Москва получила фичу, Санкт-Петербург — нет.
| До | После | |
|---|---|---|
| Москва | 100 orders | 130 orders |
| СПб | 90 orders | 110 orders |
- Москва: +30
- СПб: +20 (общий тренд сезонный)
Effect = 30 - 20 = +10 orders — чистый эффект фичи.
Без DiD мы бы сказали «фича дала +30», что неверно (+20 был бы и без фичи).
Parallel trends assumption
Ключевое assumption: без воздействия тренды в двух группах были бы параллельны.
Т.е. разница между Москвой и СПб оставалась бы такой же.
Если это не так — DiD не работает.
Как проверить
Посмотрите исторические данные. Если тренды параллельны в pre-period — предположение, скорее всего, выполняется.
В формуле
Y = α + β₁ × Treatment + β₂ × Post + β₃ × (Treatment × Post) + εГде:
- Treatment = 1 если в treatment group
- Post = 1 если после воздействия
- β₃ — это и есть эффект (DiD estimate)
Пример в SQL
SELECT
city, period,
SUM(orders) AS total
FROM data
WHERE city IN ('Moscow', 'SPb')
GROUP BY 1, 2;
-- Потом в Python / Excel:
effect = (moscow_after - moscow_before) - (spb_after - spb_before)В Python
import statsmodels.api as sm
data['treatment'] = (data['city'] == 'Moscow').astype(int)
data['post'] = (data['period'] == 'after').astype(int)
data['interaction'] = data['treatment'] * data['post']
X = sm.add_constant(data[['treatment', 'post', 'interaction']])
model = sm.OLS(data['orders'], X).fit()
print(model.summary()) # коэффициент interaction = DiD estimateКогда использовать
- A/B невозможен (географическое воздействие, юридические причины).
- Несколько групп (более 2).
- Временные панельные данные.
- Естественные эксперименты (минимальная зарплата, закон, эпидемия).
Проблемы и pitfalls
Нарушение parallel trends
Если Москва росла быстрее СПб и без фичи — DiD завышает эффект.
Решение: плацебо-тест. Применить DiD на pre-period — если виден «эффект» там, где его нет, предположение нарушено.
Spillover effects
Если Москва «заражает» СПб (пользователи мигрируют) — контроль не чистый.
Изменения состава
Если в treatment group изменился состав — эффект смешан с композиционным.
Anticipation
Если treatment group «знает заранее» о будущем воздействии и меняет поведение → смещение.
Расширения
Synthetic control
Вместо одного control-города — взвешенная комбинация нескольких. Более точно.
Event study
Смотреть эффект по периодам: какие дни после? Показывает динамику.
Triple-differences (DDD)
Три размерности: treatment × post × подгруппа.
На собесе
«Что такое DiD?» Метод измерения эффекта без рандомизации, через сравнение изменений в группах.
«Ключевое предположение?» Parallel trends — без воздействия тренды были бы параллельны.
«Как проверить?» Плацебо-тесты, визуализация трендов в pre-period.
«Когда использовать?» Когда нельзя A/B (гео, юридические причины и т.д.).
Частые ошибки
Не проверять parallel trends
Самая частая и критичная ошибка.
Игнорировать spillover
Treatment может влиять на control косвенно.
Pre-period слишком короткий
Нужен достаточно длинный pre-period, чтобы оценить тренды.
Единственный control
Один контрольный город легко отличается по мелочам. Берите несколько или synthetic control.
Смешивать эффект с другими событиями
Если одновременно с фичей в Москве был дождь, праздник или другой запуск — DiD припишет эффект фиче.
Связанные темы
FAQ
Все равно предвзятый?
Если assumption выполняется — unbiased. Иначе смещённый.
Работает ли с несколькими группами?
Да, через panel data methods.
DiD vs A/B?
A/B — gold standard (randomized). DiD — alternative когда A/B нельзя.