Как рассчитывается дисперсия для метрики конверсии нажатия на кнопку?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как рассчитывается дисперсия для метрики конверсии нажатия на кнопку
Дисперсия (variance) — это фундаментальная концепция в статистике. Для Product Analyst'а важно понимать как её рассчитывать, почему она нужна, и как использовать для A/B тестов.
Что такое дисперсия: интуиция
Дисперсия (Variance, σ²) — мера разброса данных относительно среднего значения.
Простой пример:
Кнопка A:
- День 1: 5% конверсия
- День 2: 5% конверсия
- День 3: 5% конверсия
- День 4: 5% конверсия
- День 5: 5% конверсия
Дисперсия: 0 (нет разброса, очень стабильно)
Кнопка B:
- День 1: 2% конверсия
- День 2: 8% конверсия
- День 3: 3% конверсия
- День 4: 7% конверсия
- День 5: 5% конверсия
Дисперсия: ВЫСОКАЯ (очень нестабильно)
Средняя конверсия одинаковая (5%), но Кнопка A более надёжна!
Формула дисперсии для бинарной переменной
Конверсия нажатия на кнопку — это бинарная переменная:
- Пользователь нажал (1) или нет (0)
Дисперсия для бинарной переменной:
σ² = p × (1 - p)
где:
p = доля успешных (конверсия)
(1 - p) = доля неудачных
Пример расчета:
Если конверсия p = 5% = 0.05:
σ² = 0.05 × (1 - 0.05)
σ² = 0.05 × 0.95
σ² = 0.0475
Standard Deviation (σ) = √σ² = √0.0475 = 0.218
Это значит средний разброс ±21.8 ppt от средней
Почему дисперсия p × (1-p)?
Доказательство через базовую статистику:
Для бинарной переменной X (0 или 1):
- Mean (μ) = p
- Variance (σ²) = E[X²] - (E[X])²
Вычисляем:
E[X] = 0×(1-p) + 1×p = p
E[X²] = 0²×(1-p) + 1²×p = p
σ² = E[X²] - (E[X])²
σ² = p - p²
σ² = p(1 - p)
Вывод: формула σ² = p(1-p) —это математический факт для бинарных данных.
Практический расчет для метрики
Сценарий: A/B тест кнопок
Button A:
- Показана: 1000 пользователей
- Нажата: 50 пользователей
- Конверсия p_A = 50 / 1000 = 0.05 = 5%
Button B:
- Показана: 1000 пользователей
- Нажата: 70 пользователей
- Конверсия p_B = 70 / 1000 = 0.07 = 7%
Дисперсии:
σ²_A = 0.05 × 0.95 = 0.0475
σ²_B = 0.07 × 0.93 = 0.0651
Standard Errors (для выборки):
SE_A = √(σ²_A / n_A) = √(0.0475 / 1000) = 0.0069
SE_B = √(σ²_B / n_B) = √(0.0651 / 1000) = 0.0081
Дисперсия и стандартная ошибка
Это НЕ одно и то же!
σ² = Variance (дисперсия в генеральной совокупности)
SE = Standard Error (стандартная ошибка ВЫБОРКИ)
SE = σ / √n = √(p(1-p) / n)
Почему SE меньше σ?
- При большей выборке оценка становится точнее
- √n растёт с размером выборки
- Поэтому SE уменьшается
-- SQL для расчета variance и SE
SELECT
'Button A' as button,
COUNT(*) as total_shown,
SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) as clicks,
-- Конверсия
ROUND(100.0 * SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*), 2) as conversion_pct,
-- Дисперсия
ROUND(
(SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*)) *
(1 - SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*)),
6
) as variance,
-- Standard Error
ROUND(
SQRT(
(SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*)) *
(1 - SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*)) /
COUNT(*)
),
6
) as standard_error,
-- 95% Confidence Interval
ROUND(100.0 * SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*), 2) as ci_lower_bound,
ROUND(100.0 * SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*) +
1.96 * SQRT((SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*)) *
(1 - SUM(CASE WHEN clicked = 1 THEN 1 ELSE 0 END) / COUNT(*)) / COUNT(*)), 2) as ci_upper_bound
FROM button_clicks
WHERE test_date >= DATE_SUB(TODAY(), INTERVAL 7 DAY)
GROUP BY button
Результат:
Button | Conversion | Variance | SE | 95% CI Lower | 95% CI Upper
--------|-----------|----------|--------|--------------|-------------
A | 5.0% | 0.0475 | 0.0069 | 4.86% | 5.14%
B | 7.0% | 0.0651 | 0.0081 | 6.84% | 7.16%
Дисперсия в статистических тестах
Chi-square test требует дисперсию:
Напоминаю формулу Chi-square:
χ² = Σ [(Observed - Expected)² / Expected]
Expected = (row_total × col_total) / grand_total
Это как раз работает с дисперсией!
Z-test для пропорций требует дисперсию:
Z = (p_A - p_B) / √(p(1-p) × (1/n_A + 1/n_B))
Знаменатель = корень из дисперсии!
Power анализ требует дисперсию:
from scipy.stats import norm
# Для расчета требуемого размера выборки:
baseline_p = 0.05 # Baseline conversion 5%
min_effect = 0.02 # Хотим поймать 2 ppt effect
alpha = 0.05 # Type I error
beta = 0.20 # Type II error (power = 80%)
variance = baseline_p * (1 - baseline_p) # ← дисперсия!
z_alpha = norm.ppf(1 - alpha/2)
z_beta = norm.ppf(1 - beta)
# Требуемый размер выборки в каждой группе
n = (z_alpha + z_beta)**2 * variance * 2 / (min_effect**2)
print(f"Требуется {int(n)} пользователей в каждой группе")
# Результат: 2649 пользователей в каждой группе
График: как дисперсия меняется с конверсией
Дисперсия p(1-p) максимальна при p=50%:
Variance
▲
0.25│ ╱╲
│ ╱ ╲
0.2 │ ╱ ╲
│ ╱ ╲
0.15│ ╱ ╲
│╱ ╲
0 │─────────────────────── p
0 0.25 0.5 0.75 1.0
Примеры:
- p = 1% (0.01): σ² = 0.01 × 0.99 = 0.0099 (низкая дисперсия)
- p = 5% (0.05): σ² = 0.05 × 0.95 = 0.0475
- p = 50% (0.50): σ² = 0.50 × 0.50 = 0.2500 (максимум!)
- p = 95% (0.95): σ² = 0.95 × 0.05 = 0.0475
- p = 99% (0.99): σ² = 0.99 × 0.01 = 0.0099 (низкая дисперсия)
Практический вывод:
- Экстремальные конверсии (очень низкие или высокие) имеют НИЗКУЮ дисперсию
- Средние конверсии (~50%) имеют ВЫСОКУЮ дисперсию
- Это значит экспериментам на 50% нужны БОЛЬШИЕ выборки
Пример: расчет дисперсии для разных кнопок
# Python пример
import math
def calculate_conversion_variance(clicks, total_shown):
"""Рассчитать дисперсию для конверсии нажатия"""
p = clicks / total_shown
variance = p * (1 - p)
std_dev = math.sqrt(variance)
std_error = std_dev / math.sqrt(total_shown)
# 95% confidence interval
ci_lower = (p - 1.96 * std_error) * 100
ci_upper = (p + 1.96 * std_error) * 100
return {
'conversion': p * 100,
'variance': variance,
'std_dev': std_dev,
'std_error': std_error,
'ci_lower': ci_lower,
'ci_upper': ci_upper
}
# Тестируем разные кнопки
button_a = calculate_conversion_variance(clicks=50, total_shown=1000)
button_b = calculate_conversion_variance(clicks=70, total_shown=1000)
button_c = calculate_conversion_variance(clicks=500, total_shown=1000)
for button_name, metrics in [('A', button_a), ('B', button_b), ('C', button_c)]:
print(f"Button {button_name}:")
print(f" Conversion: {metrics['conversion']:.1f}%")
print(f" Variance: {metrics['variance']:.4f}")
print(f" Std Dev: {metrics['std_dev']:.4f}")
print(f" 95% CI: [{metrics['ci_lower']:.2f}%, {metrics['ci_upper']:.2f}%]")
print()
# Output:
# Button A:
# Conversion: 5.0%
# Variance: 0.0475
# Std Dev: 0.2179
# 95% CI: [3.84%, 6.16%]
#
# Button B:
# Conversion: 7.0%
# Variance: 0.0651
# Std Dev: 0.2551
# 95% CI: [5.84%, 8.16%]
#
# Button C:
# Conversion: 50.0%
# Variance: 0.2500
# Std Dev: 0.5000
# 95% CI: [46.90%, 53.10%] ← НАМНОГО шире! Нужна большая выборка
Практическое применение: определение размера выборки
Дисперсия критична для определения когда остановить тест:
Нужно минимум n = (z_alpha/2 + z_beta)² × σ² × 2 / δ²
где:
- σ² = p(1-p) = дисперсия
- δ = minimum detectable effect
- z_alpha = 1.96 (для 95% CI)
- z_beta = 0.84 (для 80% power)
Пример:
Хотим детектировать +2 ppt эффект (0.02) на базе 5% (p=0.05):
σ² = 0.05 × 0.95 = 0.0475
n = (1.96 + 0.84)² × 0.0475 × 2 / (0.02)²
n = (2.80)² × 0.0475 × 2 / 0.0004
n = 7.84 × 0.0475 × 2 / 0.0004
n = 0.7448 / 0.0004
n = 1862
Нужно минимум 1862 пользователя в каждой группе = 3724 всего
Чеклист: правильный расчет дисперсии
- Определена что такое "конверсия" (what counts as click)
- Собраны данные (clicks и total_shown)
- Рассчитана p = clicks / total_shown
- Рассчитана σ² = p × (1-p)
- Рассчитана SE = √(σ² / n)
- Рассчитан 95% CI = p ± 1.96 × SE
- Интерпретирована CI (есть ли overlap между группами?)
- Проверена статистическая значимость (p-value < 0.05?)
Главный вывод: Дисперсия = p(1-p) для бинарных метрик. Она нужна для статистических тестов, confidence intervals, и определения размера выборки. Без правильного расчета дисперсии ты не сможешь делать валидные A/B тесты.