Difference-in-Differences простыми словами

Проверь себя · 1/3разбор после ответа
Что вернёт запрос 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 был бы и без фичи).

Ключевое 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
Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Когда использовать

  • A/B невозможен (географическое воздействие, юридические причины).
  • Несколько групп (более 2).
  • Временные панельные данные.
  • Естественные эксперименты (минимальная зарплата, закон, эпидемия).

Проблемы и pitfalls

Если Москва росла быстрее СПб и без фичи — 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 (гео, юридические причины и т.д.).

Частые ошибки

Самая частая и критичная ошибка.

Игнорировать 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 нельзя.