p = 0.049: победа?
// Условие
Тест нового флоу оформления заказа отработал ровно по плану: выборка собрана, подглядываний не было. Результат — p чуть-чуть ниже порога 0.05. Команда открывает шампанское. Продакт, впрочем, уточняет: раскатка потребует переписать половину чекаута — ошибиться дорого.
result — dict с ключами p_value, ci_low, ci_high.// Данные
user_id, group (A/B), converted (0/1) — одна строка на юзера// Решение
Подсказка
p-value — пулированный z-тест; CI — непулированная SE, diff ± 1.96 * se (как в задаче про доверительный интервал).
Посмотри на нижнюю границу CI: насколько она далека от нуля?
Сначала попробуй сам → Показать решение
df = load_data()
from scipy import stats
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']
diff = pb - pa
p_pool = df['converted'].mean()
se_pool = (p_pool * (1 - p_pool) * (1 / s.loc['A', 'count'] + 1 / s.loc['B', 'count'])) ** 0.5
z = diff / se_pool
p_value = 2 * (1 - stats.norm.cdf(abs(z)))
se = (pa * (1 - pa) / s.loc['A', 'count'] + pb * (1 - pb) / s.loc['B', 'count']) ** 0.5
result = {'p_value': p_value, 'ci_low': diff - 1.96 * se, 'ci_high': diff + 1.96 * se}
print(result)
Шампанское уже открыто. Что скажешь команде?
Бинарное мышление «p < 0.05 → истина» — самая частая ошибка интерпретации. p = 0.049 — слабое доказательство: будь истинный эффект нулевым, такой результат выпадал бы в ~5% тестов, а нижняя граница CI (+0.01 п.п.) допускает почти нулевой эффект. Когда цена ошибки высока, слабое доказательство конвертируют не в «да/нет», а в снижение риска: репликация, постепенная раскатка, мониторинг. И это не «недействительный результат» — это результат, который честно описан.