Difference-in-Differences: метод quasi-экспериментов
Что такое Difference-in-Differences
Difference-in-Differences (DiD) — статистический метод для оценки причинного effect, когда нельзя провести рандомизированный эксперимент.
Идея: сравнить изменение outcome до и после intervention в treated group с изменением в control group. Разница этих разниц — эффект intervention.
Используется когда:
- AB-тест невозможен (территориальные rollouts, policy changes).
- Intervention уже произошла — нужно оценить effect постфактум.
- Natural experiments в данных.
Формула
Простейшая форма:
DiD = (Y_after_treated - Y_before_treated) - (Y_after_control - Y_before_control)Первая разница — изменение в treated group. Вторая — в control group. Их разница — эффект treatment, очищенный от общих трендов.
Пример
Компания запустила новую фичу в RU. DE — control (фичу не получили).
Средняя retention до запуска:
- RU: 35%
- DE: 33%
После запуска:
- RU: 40% (+5pp)
- DE: 34% (+1pp)
DiD estimate:
(40% - 35%) - (34% - 33%) = 5pp - 1pp = 4ppЭффект фичи на retention = +4 процентных пункта. Общий 1% рост (наблюдаемый в DE) — это тренд, не связанный с фичей.
Без DiD можно было бы сказать «retention вырос на 5pp» — и переоценить эффект.
Assumption: Parallel trends
Главное предположение DiD — parallel trends. Без treatment обе группы изменялись бы одинаково.
Это не testable directly (не наблюдаем counterfactual), но можно проверить pre-treatment periods:
График retention за 6 месяцев до запуска:
- RU: 30% → 35% (рост на 5pp, 0.8pp/месяц)
- DE: 28% → 33% (рост на 5pp, 0.8pp/месяц)Если pre-trend параллельны — assumption правдоподобна.
Если treated растёт быстрее ДО treatment — красный флаг. Дальнейший рост может быть продолжением тренда, а не эффектом.
DiD в регрессии
Более гибкий способ — через регрессию с interaction:
Y = β₀ + β₁·Treated + β₂·Post + β₃·(Treated × Post) + εГде:
Treated = 1если в treated groupPost = 1если после interventionTreated × Post = 1только в treated group после intervention
Коэффициент β₃ — DiD estimate.
Преимущества регрессии:
- Можно добавить controls (очистить от других факторов).
- Легко получить SE и p-values.
- Легко расширить на multiple periods, multiple treatments.
Python implementation
import statsmodels.formula.api as smf
import pandas as pd
# Данные: user_id, group ('treated'/'control'), period ('pre'/'post'), retention
df['treated'] = (df['group'] == 'treated').astype(int)
df['post'] = (df['period'] == 'post').astype(int)
df['treat_post'] = df['treated'] * df['post']
model = smf.ols('retention ~ treated + post + treat_post', data=df).fit()
print(model.summary())
# Коэффициент treat_post — DiD estimateЕсли treat_post значим и положителен — treatment увеличил retention.
Multiple time periods
Для событий с длительным rollout — Two-Way Fixed Effects (TWFE):
Y_it = α_i + γ_t + β·Treatment_it + ε_itГде:
α_i— fixed effect unit (user, region)γ_t— fixed effect timeTreatment_it = 1если unit i получил treatment к time t
Коэффициент β — средний effect treatment.
В Python:
import statsmodels.formula.api as smf
model = smf.ols(
'retention ~ treatment + C(user_id) + C(week)',
data=df
).fit()Fixed effects убирают unobserved time-invariant differences и common time shocks. Focus — на variation от treatment.
Staggered DiD — новая проблема
Если treatment наступает в разное время для разных unit (staggered rollout) — классический TWFE может давать смещённые оценки.
Проблема: когда уже-treated unit используется как control для позже-treated unit, возникает bias.
Современные методы (после 2021):
- Callaway-Sant'Anna estimator.
- Sun-Abraham estimator.
- De Chaisemartin-D'Haultfœuille.
Для crucial analysis (особенно в academic papers) используют эти методы. Для rough business estimates TWFE часто достаточно.
Causal inference — отличный skill для продвинутых аналитиков. В тренажёре Карьерник есть задачи по AB-тестам, causal inference и статистике.
Event study
Расширение DiD для визуализации dynamic effects.
Идея: оцениваем effect в каждый период относительно treatment:
Y_it = α_i + γ_t + Σ β_k · D_(it, k) + ε_itГде D_(it, k) = 1 если unit i в k-м периоде относительно своего treatment event.
График β_k по k показывает:
- Pre-treatment (k < 0): должен быть близок к 0 (parallel trends).
- Post-treatment (k >= 0): показывает dynamic effect.
Полезно видеть:
- Immediate vs delayed effect.
- Peak и fade out.
- Violation of parallel trends (pre-trends не zero).
Real-world examples
Card & Krueger (1994). Классика: повышение минимальной зарплаты в New Jersey. Control — Pennsylvania. Нашли, что повышение не снизило занятость (контр-интуитивный результат).
Google Ads rollout. Запуск feature в отдельных регионах. DiD показывает incremental impact.
Mobile Apps. Feature rollout по iOS versions. iOS 16 vs iOS 15 — DiD оценка feature.
Pricing changes. Повышение цены в одной категории. Control — похожие категории без повышения.
Company M&A. Эффект purchase на target company — DiD vs similar company peers.
Когда DiD не работает
Anticipation effect. Люди знают о будущем treatment и меняют поведение заранее. Parallel trends violated.
Spillovers. Control group тоже затронута treatment (через competitors, mutual users). Effect underestimated.
Shocks между treatments. Что-то другое случилось в treated area одновременно с treatment.
Small sample. Мало units → big standard errors. DiD нуждается в multiple treated и control units.
Non-random selection. Treatment назначен не случайно, а на основе characteristics, которые сами меняются во времени.
DiD с controls
Добавление covariates делает оценку robust:
model = smf.ols(
'retention ~ treated + post + treat_post + age + tenure_days + country',
data=df
).fit()Controls «очищают» DiD от confounding. Особенно важно если treated/control отличаются по observed characteristics.
Но: control variables не должны сами меняться от treatment (post-treatment bias). Например, tenure_days растёт со временем одинаково в обеих группах — OK. Но если treatment influenced tenure (через retention) — problematic.
SUTVA assumption
Stable Unit Treatment Value Assumption: treatment одного unit не влияет на outcome других.
Нарушения:
- Network effects. В social network treatment пользователя влияет на его friends.
- Market equilibrium. В ride-sharing если drivers get subsidies, riders тоже бенефит.
Если SUTVA violated — DiD оценки смещены. Решения: cluster-level randomization, network-aware methods.
Типичные ошибки
Skipping parallel trends check. Критический шаг. Без него DiD бессмыслен.
Cherry-picking periods. Выбор «удобных» pre/post periods, где результат выгодный. Pre-register analysis.
Ignoring standard errors. Simple OLS SE могут underestimate. Использовать clustered SE (на уровне group/region).
Treating staggered as simple DiD. Для multiple treatment times — используйте современные methods.
Не показывать pre-trends. Visualization убеждает stakeholders, что parallel trends holds.
Читайте также
FAQ
DiD и AB-тест — когда что?
AB-тест предпочтительнее если доступен (randomization дает clean causality). DiD когда AB невозможен (territorial, regulatory, timing constraints).
Можно ли DiD с одним treated unit?
Сложно. Синтетический контроль — расширение DiD для такого случая.
Parallel trends — как проверить?
Визуально (график pre-trends), статистически (test на significance pre-trends). Plus robustness checks с different controls.
DiD оценка — causal?
Да, ЕСЛИ parallel trends assumption holds. Это главное условие.