Как рассчитать размер выборки A/B
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Зачем это знать
«Сколько выборки нужно?» — fundamental в A/B. Запустили с 1000 users → не detect 1% lift → waste. Запустили с 1M → over-powered → waste time.
На собесах A/B power analysis — обязательный знать.
Короткое объяснение
Sample size зависит от:
- Alpha (α): желаемый FPR (обычно 0.05)
- Power (1 - β): шанс detect true effect (обычно 0.80)
- MDE (minimum detectable effect): lift, который важно catch
- Baseline: текущий conversion (или mean / variance)
Формула (proportions)
Для binary metrics (conversion):
n = 2 × (z_α/2 + z_β)² × p̄ × (1 - p̄) / (p1 - p2)²Где:
- z_α/2 = 1.96 для α=0.05
- z_β = 0.84 для power=0.80
- p̄ = average proportion
- p1, p2 — baseline and treatment expected
Практический пример
Setup
- Baseline CR = 10%
- Хотим detect +1 p.p. (=1 pp) lift
- α = 0.05, power = 0.80
Compute
p1 = 0.10, p2 = 0.11, p̄ = 0.105 (p1 - p2)² = 0.0001
n = 2 × (1.96 + 0.84)² × 0.105 × 0.895 / 0.0001 n ≈ 2 × 7.84 × 0.094 / 0.0001 n ≈ 14 740 per group
Total ≈ 29 500 users.
Python функция
from scipy import stats
import numpy as np
def sample_size_proportion(p1, p2, alpha=0.05, power=0.80):
z_alpha = stats.norm.ppf(1 - alpha/2)
z_beta = stats.norm.ppf(power)
p_avg = (p1 + p2) / 2
n = 2 * (z_alpha + z_beta)**2 * p_avg * (1 - p_avg) / (p1 - p2)**2
return int(np.ceil(n))
# Example
print(sample_size_proportion(0.10, 0.11)) # 14 758Для continuous
Revenue, time-on-site — continuous.
n = 2 × (z_α/2 + z_β)² × σ² / (μ1 - μ2)²σ — standard deviation.
def sample_size_continuous(mu1, mu2, sigma, alpha=0.05, power=0.80):
z_alpha = stats.norm.ppf(1 - alpha/2)
z_beta = stats.norm.ppf(power)
n = 2 * (z_alpha + z_beta)**2 * sigma**2 / (mu1 - mu2)**2
return int(np.ceil(n))statsmodels
Complex cases — use library:
from statsmodels.stats.power import NormalIndPower
analysis = NormalIndPower()
sample_size = analysis.solve_power(
effect_size=0.01 / np.sqrt(0.105 * 0.895), # Cohen's h-like
alpha=0.05,
power=0.80
)Или proportions specifically:
from statsmodels.stats.power import proportions_effectsize, NormalIndPower
es = proportions_effectsize(0.10, 0.11)
n = NormalIndPower().solve_power(effect_size=es, alpha=0.05, power=0.80)Trade-offs
Smaller MDE
Больше N нужно. n ∝ 1 / MDE².
MDE cut в 2 → N в 4 раза.
Larger alpha
Easier detect → меньше N. Но more false positives.
Larger power
Safer → больше N.
MDE выбор
Business decision:
«Какой effect важен для shipping?»
- +0.5%: trivial. Usually ship по другим reasons.
- +5%: meaningful.
- +20%: huge.
Pick threshold matching business value.
SRM
Assignment 50/50 сбалансированный. Actual могло быть 50.2/49.8.
Chi-square тест:
from scipy.stats import chisquare
obs = [users_control, users_test]
expected = [sum(obs) / 2, sum(obs) / 2]
chi2, p = chisquare(obs, expected)
if p < 0.01:
print("SRM issue! Investigate.")Allocation
50/50 — default. Но:
- 90/10: conservative, small treatment exposure
- 50/50 / 50: multiple variants
Unequal splits require recalc.
n ∝ 1/k + 1/(1-k) для ratio kEqual (0.5) minimizes total N для given power.
Variance reduction
CUPED reduces variance → нужно меньше N. Подробнее.
Duration
N / daily traffic = duration.
Пример: N = 30k per group, 60k total. Traffic 10k/day → 6 days.
Plus consider:
- Full weeks (weekly patterns)
- Novelty (2+ weeks)
- Seasonality
Rule: minimum 2 weeks обычно, даже если N hit earlier.
Ratio metrics
«Revenue per session» — ratio. Delta method для variance (complex).
Approximation:
# Use bootstrap for complex metrics
from scipy.stats import bootstrapCalculators
Online:
- Evan's A/B calc
- Optimizely (старый калькулятор)
- Статьи с калькуляторами
Для quick estimates.
Повторный расчёт
Что если actual baseline отличается от expected?
Re-compute. Lower baseline → часто больше N нужно.
Частые ошибки
Use observed effect для MDE
MDE — до теста. «Ожидаемо +1%». Не «observed +1%».
Ignore baseline variability
Small p → heavy influence from p × (1-p).
Forget traffic constraint
N 1M required. Daily traffic 1k → 1000 days. Infeasible.
Accept higher MDE или другой approach.
Peeking inflates Type I
Pre-registered sample size matters.
На собесе
«Sample size для A/B»
Ask:
- Baseline CR
- Desired MDE
- Alpha / power (usually default)
Compute или give rough (formula).
«Почему 80% power?»
Convention. Balance: false negative cost vs time / effort.
«Больше выборка лучше?»
Более precise, но more time. Match к business need.
Связанные темы
FAQ
Power меньше 80%?
Possible. Business может accept more misses.
Alpha 0.01 vs 0.05?
Stricter → fewer false positives, require больше N.
One-tailed vs two-tailed?
Two-tailed safer. One-tailed only если strong priors about direction.
Тренируйте A/B — откройте тренажёр с 1500+ вопросами для собесов.