«Возьмём односторонний — там уже значимо»
// Условие
Тест новой формы регистрации. Планировали как обычно: двусторонний тест, α = 0.05. Выборка собрана полностью, результат на грани. Коллега предлагает: «Мы же ожидали рост, а не падение — давай посчитаем односторонний тест, там p уже меньше 0.1... ну или α возьмём 0.1 — и вообще значимо!»
result — dict с ключами p_two_sided, p_one_sided.// Данные
user_id, group (A/B), converted (0/1) — одна строка на юзера// Решение
Подсказка
Двусторонний: 2 * (1 - stats.norm.cdf(abs(z))). Односторонний (H1: B > A): 1 - stats.norm.cdf(z).
При положительном z односторонний p — ровно половина двустороннего. Дёшево и сердито... если выбрать его до теста, а не после.
Сначала попробуй сам → Показать решение
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']
p_pool = df['converted'].mean()
se = (p_pool * (1 - p_pool) * (1 / s.loc['A', 'count'] + 1 / s.loc['B', 'count'])) ** 0.5
z = (pb - pa) / se
p_two = 2 * (1 - stats.norm.cdf(abs(z))) # ≈ 0.145
p_one = 1 - stats.norm.cdf(z) # ≈ 0.072
result = {'p_two_sided': p_two, 'p_one_sided': p_one}
print(result)
Коллега ждёт поддержки. Твой вердикт?
Правила игры — тип теста, α, метрику, длительность — фиксируют до запуска. Каждая «поправка» после просмотра данных увеличивает реальную вероятность ложного открытия: двигая α и хвосты, из p = 0.145 можно «выжать» что угодно. Ожидание роста — не аргумент: оно было и до теста, но тест задизайнили двусторонним. Честный итог: эффект не доказан; хочется доказать — новый тест с большей выборкой.