A/B-тестыЛовушки A/B-тестовEasyБесплатно~8 мин

Группы «разъехались»: паника или норма?

// Условие

Джун из команды пишет в панике: «У нас в тесте группы разъехались — 40 200 против 39 800, целых 400 юзеров разницы! Это же SRM, тест испорчен?!» Дизайн сплита — 50/50.

Что нужно
Проверь сплит хи-квадратом против 50/50 и посчитай p-value эффекта. Сохрани в result — dict с ключами p_value_srm, p_value_effect.

// Данные

df: user_id, group (A/B), converted (0/1) — одна строка на юзера
▶ Решить в A/B-тренажёре

// Решение

Подсказка

SRM-чек: stats.chisquare([n_a, n_b], f_exp=[total/2, total/2]). Смотри на p-value: маленький (< 0.001) — сплит сломан, большой — всё в порядке.

Разница размеров групп при честной рандомизации — это биномиальный шум: ±400 из 80 000 — обычное дело.

p-value эффекта — z-тест двух долей, как обычно.

Сначала попробуй сам → Показать решение
df = load_data()
from scipy import stats

vc = df['group'].value_counts()
n_a, n_b = int(vc['A']), int(vc['B'])
total = n_a + n_b

# SRM: p ≈ 0.157 — отклонение 400 юзеров из 80 000 полностью объяснимо шумом
p_srm = stats.chisquare([n_a, n_b], f_exp=[total / 2, total / 2]).pvalue

s = df.groupby('group')['converted'].agg(['sum', 'count'])
pa = s.loc['A', 'sum'] / s.loc['A', 'count']
pb = s.loc['B', 'sum'] / s.loc['B', 'count']
p_pool = df['converted'].mean()
se = (p_pool * (1 - p_pool) * (1 / n_a + 1 / n_b)) ** 0.5
z = (pb - pa) / se
p_effect = 2 * (1 - stats.norm.cdf(abs(z)))

result = {'p_value_srm': p_srm, 'p_value_effect': p_effect}
print(result)
SRM — это не «размеры групп различаются», а «различаются сильнее, чем позволяет случайность». Здесь хи-квадрат даёт p ≈ 0.16: сплит здоров. Сравни с задачей «Слишком красивый рост», где p ≈ 10⁻⁴⁵ — вот там SRM. Порог тревоги на практике — p < 0.001.

Что ответишь джуну?

  • ✓ Паника отменяется: SRM-чек даёт p ≈ 0.16 — отклонение 400 из 80 000 это нормальный биномиальный шум. А вот эффект значим (p ≈ 0.01) — готовим раскатку
  • Джун прав: группы должны быть строго равными, тест перезапускаем
  • SRM есть, но небольшой — просто отрежем лишние 400 юзеров из A
  • Разница размеров не важна в принципе — SRM-чек можно вообще не делать

Рандомизация — это подбрасывание монетки 80 000 раз: ровно 40 000 решек почти никогда не выпадает, и ±400 — типичное отклонение (p ≈ 0.16). SRM-чек делать обязательно, но тревожиться — когда p крошечный (< 0.001). Идеально равные группы, кстати, сами по себе подозрительны: значит, кто-то «подровнял» сплит руками. Хороший аналитик отличает шум от поломки — и учит этому команду.

// Похожие задачи

// Разобраться в теме

→ Гайд по A/B-тестам