Как посчитать Bonferroni correction в SQL

Закрепи формулу bonferroni в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать bonferroni в Telegram

Зачем Bonferroni

Когда в одном A/B-эксперименте проверяют несколько гипотез — 5 вариантов, 10 метрик, 4 сегмента — вероятность найти хотя бы одно ложно-значимое срабатывание растёт. Family-wise error rate (FWER) надо контролировать. Bonferroni — самый простой и консервативный способ.

Формула

Если делаем m независимых тестов и хотим суммарный alpha ≤ α (обычно 0.05):

α_per_test = α / m

Или, эквивалентно, корректируем p-values:

p_adjusted = min(p × m, 1)

Скорректированная alpha

Например, 10 метрик в одном эксперименте, α=0.05:

WITH config AS (
    SELECT 0.05::NUMERIC AS family_alpha, 10::INT AS m_tests
)
SELECT
    family_alpha,
    m_tests,
    family_alpha / m_tests AS bonferroni_alpha
FROM config;

Результат — 0.005. Каждая метрика проверяется на α=0.005, и тогда суммарный риск ложного срабатывания по семейству ≤ 5%.

Скорректированные p-values

Удобнее адекватировать p-values, оставляя α=0.05:

WITH raw_p AS (
    SELECT * FROM (VALUES
        ('conversion',     0.003),
        ('revenue',        0.020),
        ('retention_d7',   0.045),
        ('time_on_page',   0.120),
        ('refunds',        0.500)
    ) AS t(metric, p_value)
),
correction AS (
    SELECT COUNT(*) AS m FROM raw_p
)
SELECT
    r.metric,
    r.p_value,
    LEAST(r.p_value * c.m, 1.0) AS p_bonferroni,
    LEAST(r.p_value * c.m, 1.0) < 0.05 AS significant_bonferroni
FROM raw_p r
CROSS JOIN correction c
ORDER BY r.p_value;

conversion остаётся значимой после умножения на 5 (0.003 × 5 = 0.015), revenue — нет (0.020 × 5 = 0.10).

Закрепи формулу bonferroni в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать bonferroni в Telegram

Holm-Bonferroni

Holm-Bonferroni — менее консервативный «sequential» вариант. P-values сортируют по возрастанию, корректируют по индивидуальной формуле:

p_(1) × m, p_(2) × (m−1), ..., p_(m) × 1
WITH raw_p AS (
    SELECT * FROM (VALUES
        ('conversion',     0.003),
        ('revenue',        0.020),
        ('retention_d7',   0.045),
        ('time_on_page',   0.120),
        ('refunds',        0.500)
    ) AS t(metric, p_value)
),
ordered AS (
    SELECT
        metric,
        p_value,
        ROW_NUMBER() OVER (ORDER BY p_value) AS rnk,
        COUNT(*) OVER () AS m
    FROM raw_p
)
SELECT
    metric,
    p_value,
    LEAST(p_value * (m - rnk + 1), 1.0) AS p_holm,
    LEAST(p_value * (m - rnk + 1), 1.0) < 0.05 AS significant_holm
FROM ordered
ORDER BY rnk;

Holm пропускает больше «реальных» эффектов, сохраняя контроль FWER.

Частые ошибки

Ошибка 1. Считать m без учёта direction. Если для каждой метрики проверяете и «больше» и «меньше» — это два теста, не один. m удваивается.

Ошибка 2. Bonferroni для коррелированных метрик. Conversion и revenue сильно коррелируют. Bonferroni считает их независимыми → слишком консервативно. Используйте Šidák или Hochberg.

Ошибка 3. Применять post-hoc. «У нас вышло 8 метрик не значимых, попробуем ещё 5» — это p-hacking. Bonferroni спасает только если m зафиксирован до эксперимента.

Ошибка 4. Не различать FWER и FDR. Bonferroni контролирует FWER (хоть одно ложное). Для большого m (50+ метрик) консервативность убивает power — лучше Benjamini-Hochberg (FDR).

Ошибка 5. LEAST(p × m, 1.0) без ::NUMERIC. В Postgres 1.0 иногда воспринимается как double, в других СУБД могут быть нюансы. Используйте ::NUMERIC для предсказуемости.

Связанные темы

FAQ

Bonferroni vs Holm?

Holm не менее строг по FWER, но сильнее по power. Если выбираете один — Holm.

При каком m Bonferroni «слишком жёсткая»?

При m &gt; 20 теряете значимые эффекты. Лучше Benjamini-Hochberg.

Можно ли Bonferroni для нескольких t-тестов в одном A/B/C/D?

Да, попарные сравнения = m = 6 для 4 групп. Делите α на 6.

Где брать p-values?

Из SQL для chi-square / Z-аппроксимации. Точные — из scipy / R.

FWER vs FDR?

FWER = P(хотя бы одно ложное). FDR = E(доля ложных среди значимых). FDR разумнее при большом числе метрик.