Как рассчитать необходимый размер выборки для A/B-теста?

«Как рассчитать необходимый размер выборки для A/B-теста?» — вопрос из категории Аналитика и метрики, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Расчет размера выборки (sample size) — это критический этап планирования A/B-теста, который определяет его длительность и статистическую достоверность. Я рассчитываю его, исходя из четырех ключевых параметров:

  1. Уровень значимости (Alpha, α): Вероятность ложноположительного результата (ошибка I рода). Обычно устанавливается в 0.05 (5%). Это означает 95% доверительный интервал.
  2. Мощность теста (Power, 1-β): Вероятность обнаружить эффект, если он действительно есть. Обычно целевое значение — 0.8 или 0.9 (80% или 90%). β — это вероятность ложноотрицательного результата.
  3. Минимальный детектируемый эффект (MDE): Наименьшее изменение метрики, которое имеет практическую значимость для бизнеса. Например, увеличение конверсии на 0.5% (относительное) или на 0.01 (абсолютное). Чем меньше MDE, тем больше выборка.
  4. Базовый уровень метрики (Baseline Rate, p): Текущее значение метрики в контрольной группе (например, конверсия 4%).

Формула и расчет на Python (для пропорций):

import statsmodels.stats.power as smp
import math

# Параметры
alpha = 0.05          # Уровень значимости
power = 0.8           # Мощность теста
p1 = 0.04             # Базовая конверсия (4%)
mde_relative = 0.05   # MDE = 5% относительного улучшения (от p1)
p2 = p1 * (1 + mde_relative)  # Ожидаемая конверсия в тестовой группе (~4.2%)

# Расчет размера выборки на ОДНУ группу (используется приближение для Z-теста)
effect_size = smp.proportion_effectsize(p1, p2)
sample_size_per_variant = smp.NormalIndPower().solve_power(
    effect_size=effect_size,
    power=power,
    alpha=alpha,
    ratio=1,  # Группы равного размера
    alternative='two-sided'  # Двусторонний тест
)

# Общий размер выборки для теста (A + B)
total_sample_size = math.ceil(sample_size_per_variant * 2)
print(f"Размер выборки на группу: {math.ceil(sample_size_per_variant)}")
print(f"Общий размер выборки: {total_sample_size}")

Важные нюансы:

  • Для непрерывных метрик (средний чек, время в приложении) используется tt_ind_solve_power из statsmodels.
  • Нужно учитывать вариабельность трафика (например, спад в выходные) и планировать тест так, чтобы набрать выборку за разумное время.
  • Если проводится множество тестов одновременно, может потребоваться поправка на множественное тестирование (например, поправка Бонферрони), которая увеличит требуемый размер выборки.