Хи-квадрат Пирсона: таблица 2×2 и точный тест Фишера
Критерий хи-квадрат Пирсона: ожидаемые частоты, поправка Йейтса и точный тест Фишера. Расчёт в Python, размер эффекта и перенос на конверсию.
Содержание статьи
В условном пилоте повторное обращение произошло у 18 из 100 участников одной группы и у 30 из 100 другой. Разница выглядит существенной, но коллеги получают разные p-value: один пишет 0,0469, другой 0,0679. Причина может быть в разных процедурах, а не в ошибке арифметики. Разберём критерий хи-квадрат Пирсона, ожидаемые частоты, поправку Йейтса и точный тест Фишера на одной таблице. Все числа вымышлены для обучения; они не описывают эффективность лечения или работу конкретной клиники.
Когда подходит хи-квадрат Пирсона
Название «хи-квадрат» встречается в нескольких задачах. Здесь речь о независимости двух категориальных признаков: группы и факта события. Критерий согласия отвечает на другой вопрос — соответствуют ли наблюдаемые частоты заранее заданному распределению. Общая идея расхождения наблюдаемого и ожидаемого похожа, но ожидаемые числа и степени свободы определяются по-разному. Не выбирайте функцию только по знакомому символу χ²: сначала запишите нулевую гипотезу словами и проверьте, какую таблицу она предполагает.
- Есть два категориальных признака, и вы проверяете их независимость по таблице количеств наблюдений.
- Каждый независимый участник попадает в одну ячейку. Повторные измерения и кластеры требуют другого учёта зависимости.
- Ожидаемые частоты позволяют использовать асимптотическое приближение; в небольшой разреженной таблице 2×2 рассмотрите точный тест Фишера.
- Вместе с p показывайте доли и размер эффекта. Проверка независимости не объясняет причинность и не оценивает практическую пользу автоматически.
От отдельных людей к таблице 2×2
В нашем синтетическом примере все двести участников наблюдались одно и то же полное окно. В строках стоят группы A и B, в столбцах — «было повторное обращение» и «не было». Таблица равна [[18, 82], [30, 70]]. Суммы строк — по 100, суммы столбцов — 48 и 152. Ноль обращений здесь означает отсутствие события за полностью наблюдаемое окно. Если часть участников потеряна для наблюдения, отсутствие записи ещё нельзя считать отсутствием обращения.
Таблица должна содержать количества, а не проценты без знаменателей. Значения 18% и 30% могут относиться к сотне людей или к нескольким тысячам; размер эффекта одинаков по шкале долей, а неопределённость разная. Проценты в интерфейсе удобны читателю, но для воспроизводимого расчёта сохраняйте числители и знаменатели. Если участник обращался несколько раз, заранее решите, анализируется ли факт хотя бы одного обращения или число обращений. Для первого вопроса человек учитывается один раз; второй требует модели счётного исхода.
| Группа | Событие | Нет события | Всего |
|---|---|---|---|
| A | 18 | 82 | 100 |
| B | 30 | 70 | 100 |
| Всего | 48 | 152 | 200 |
Как получаются ожидаемые частоты
При нулевой гипотезе независимости общая доля события 48/200 = 0,24 применяется к каждой строке. Для ста участников ожидается 24 события и 76 отсутствий события. Поэтому ожидаемая таблица равна [[24, 76], [24, 76]]. Формула для каждой ячейки: сумма её строки, умноженная на сумму её столбца и делённая на общий размер. Это не прогноз клинического эксперта и не плановый норматив. Ожидание относится именно к статистической гипотезе независимости при данных маргинальных суммах.
Статистика Пирсона суммирует (O − E)²/E по всем ячейкам. В нашем примере отклонения равны −6, +6, +6 и −6. Их вклад зависит от ожидаемой частоты: одинаковое отклонение на фоне 24 весит больше, чем на фоне 76. Итог χ² = 3,94737. Для таблицы 2×2 число степеней свободы равно (2 − 1) × (2 − 1) = 1. При асимптотическом сравнении без поправки Йейтса получаем p ≈ 0,04694.
Название «ожидаемые» легко провоцирует неверную очистку. Нельзя заменить ими наблюдаемые числа, чтобы таблица стала аккуратнее. Нельзя удалить категорию с неудобной частотой, если она была частью исходного вопроса. Ожидаемая таблица нужна для вычисления статистики и оценки качества приближения. Если она слишком разрежена, меняется процедура анализа или план сбора данных, а не факты. Объединение категорий должно иметь предметный смысл и по возможности быть задано заранее, иначе вы меняете вопрос по увиденному результату.
Eᵢⱼ = Rᵢ × Cⱼ / N; χ² = Σ (Oᵢⱼ − Eᵢⱼ)² / EᵢⱼR и C — суммы строк и столбцов; степени свободы (r − 1)(c − 1).
| Группа | Событие | Нет события |
|---|---|---|
| A | 24 | 76 |
| B | 24 | 76 |
Python: явно фиксируем поправку
В SciPy вызов chi2_contingency по умолчанию включает поправку непрерывности Йейтса, когда число степеней свободы равно единице. В первом расчёте мы задаём correction=False, чтобы показать классическую статистику Пирсона. Отдельный вызов с correction=True даёт p ≈ 0,06857. Точный двусторонний тест Фишера для той же таблицы даёт p ≈ 0,06791. Эти значения не обязаны совпадать: процедуры используют разные способы оценить хвостовую вероятность по дискретным данным.
Выбор между ними нельзя делать по тому, какое p оказалось ниже 0,05. Зафиксируйте основной метод до просмотра эффекта и сообщите настройки. Если для проверки устойчивости показаны альтернативы, так и назовите их. В этом учебном примере результаты около условного порога хорошо показывают, насколько мало пользы от отчёта «есть эффект / нет эффекта» без самих чисел. Оценка разности долей не исчезает при смене процедуры, меняется сила статистического свидетельства при разных правилах проверки.
import numpy as np
from scipy import stats
table = np.array([[18,82],[30,70]]) # синтетические количества
r = stats.chi2_contingency(table, correction=False)
print("chi2, p, df:", r.statistic, r.pvalue, r.dof)
print("expected:", r.expected_freq)
manual = ((table-r.expected_freq)**2/r.expected_freq).sum()
assert np.isclose(manual, r.statistic)
print("Yates p:", stats.chi2_contingency(table, correction=True).pvalue)
print("Fisher two-sided:", stats.fisher_exact(table, alternative="two-sided"))
pa, pb = table[:,0]/table.sum(axis=1)
print("risk A, risk B, difference, RR:", pa, pb, pa-pb, pa/pb)
print("OR:", (pa/(1-pa))/(pb/(1-pb)))Небольшие ожидаемые частоты и точный тест Фишера
Рассмотрим второй синтетический набор: [[1, 19], [6, 14]]. В каждой группе двадцать участников. Общая доля события 7/40, поэтому ожидаемое число событий в каждой группе равно 3,5. Наблюдаемая частота и ожидаемая — разные числа; применимость приближения оценивают прежде всего по ожидаемой структуре. Практическое правило про частоты не меньше пяти — ориентир, а не физическая граница. Для маленькой таблицы 2×2 с такими ожиданиями разумно заранее выбрать точный метод вместо опоры на сомнительное приближение.
Пирсон без поправки на этой таблице даёт p ≈ 0,03747, а двусторонний Фишер — p ≈ 0,09148. Разница уже заметно влияет на бинарную интерпретацию порога. В условной модели Фишера фиксируются суммы строк и столбцов, затем оценивается, насколько вероятны таблицы не менее экстремальные по используемому определению. В SciPy для двустороннего варианта складываются вероятности таблиц, не превышающие вероятность наблюдаемой. Поэтому двустороннее p не следует автоматически получать удвоением меньшего одностороннего значения.
Слово «точный» относится к вычислению в рамках гипотезы и условной модели. Оно не означает точного знания эффекта и не отменяет смещение отбора, разные окна наблюдения или зависимость людей внутри клиники. Если таблица собрана неверно, точный тест точно обработает неверную постановку. Есть и другие процедуры для небольших таблиц; выбор обсуждают с учётом дизайна и целей. Вводному анализу достаточно понимать, почему приближение может расходиться с точным расчётом и почему метод выбирают до просмотра удобного результата.
import numpy as np
from scipy import stats
table = np.array([[1,19],[6,14]])
r = stats.chi2_contingency(table, correction=False)
print("expected:", r.expected_freq)
print("Pearson p:", r.pvalue)
print("Fisher p:", stats.fisher_exact(table, alternative="two-sided").pvalue)Разность долей, отношение рисков и отношение шансов
Вернёмся к первой таблице. Доли событий A и B равны 18% и 30%. Разность A − B составляет −12 процентных пунктов, отношение рисков A/B равно 0,60. На уровне наблюдаемых долей это означает, что частота события в A составляет 60% частоты в B. Это не то же самое, что снижение на 12%: процентные пункты описывают абсолютную разность, относительное изменение использует базовую долю в знаменателе. Направление сравнения нужно подписать, иначе читатель может получить обратное отношение.
Отношение шансов для этой ориентации равно (18/82)/(30/70) ≈ 0,5122. Шанс — отношение вероятности события к вероятности его отсутствия, а не сама вероятность. Поэтому OR и RR здесь различаются. Функция fisher_exact возвращает статистику, которую в стандартном случае таблицы 2×2 SciPy определяет как выборочную оценку отношения шансов. Нельзя переименовать её в риск просто потому, что она стоит рядом с p. При инверсии строк или столбцов изменится и смысл отношения.
Для реального отчёта добавьте интервал выбранного размера эффекта, рассчитанный подходящим способом, и предметный порог значимости. В нашем учебном разборе точечные эффекты нужны, чтобы не потерять масштаб за спором о тестах. Само p Пирсона не является интервалом разности долей. При малых частотах особенно опасно применять случайную простую формулу без проверки её свойств. Заранее решите, какой эффект будет основным, и сохраняйте способ построения интервала вместе с остальными настройками анализа.
Независимые группы и пары нельзя смешивать
Если одни и те же люди отвечали «да/нет» до и после, две строки не являются независимыми выборками. Нужно сохранить переходы: нет → да, да → нет, нет → нет и да → да. Для сравнения парных бинарных исходов часто рассматривают критерий Мак-Немара, который использует информацию о несовпадающих парах. Таблица только общих долей до и после теряет эту связь. Даже если оба подхода в конкретном примере дают похожие p, это не делает независимый хи-квадрат корректным для парного дизайна.
Аналогично, если группы назначали целыми клиниками или компаниями, стандартная таблица по всем людям не отражает кластерную структуру. Участники внутри организации могут иметь общие условия, и обычная оценка неопределённости окажется чрезмерно оптимистичной. Не существует поправки на ожидаемые частоты, которая одновременно исправляет такую зависимость. Нужен анализ на уровне назначения либо модель, учитывающая кластеры. В отчёте число людей и число независимых единиц назначения следует различать явно.
Больше двух категорий: общий тест не называет виновника
В таблице с несколькими строками и столбцами значимый общий результат говорит о несовместимости данных с независимостью, но не устанавливает, какие именно категории отличаются. Можно исследовать вклад ячеек и заранее предусмотренные сравнения, однако дополнительные проверки требуют учёта множественности. Нельзя после общего p выбрать самую яркую ячейку и представить её как единственную заранее заданную гипотезу. Читателю нужно видеть, был ли разрез частью плана или появился при исследовании данных.
Для продуктового примера это может быть распределение причин отмены заказа по нескольким вариантам интерфейса. Сначала проверьте, одинаково ли кодируются причины, не изменился ли список вариантов и учитываются ли пропуски. Если новый интерфейс иначе собирает причину, различие таблиц может отражать изменение измерения. Редкие категории объединяйте только осмысленно: «другое» из несовместимых процессов облегчает вычисление, но ухудшает интерпретацию. Иногда полезнее показать описательную таблицу и собрать больше данных, чем искусственно упрощать вопрос ради теста.
Перенос на конверсию и retention
В A/B-тесте таблица 2×2 строится из числа назначенных пользователей с целевым действием и без него. Действие и окно должны быть фиксированы: например, хотя бы одна оплата за полные семь дней после назначения. Повторные оплаты одного человека не увеличивают число успешных пользователей. Если вариант влияет на прохождение промежуточного шага, отбор только дошедших меняет оцениваемый эффект. Таблица среди открывших оплату и таблица среди всех назначенных отвечают на разные вопросы, хотя обе технически имеют размер два на два.
Для D7 retention нужен полный седьмой день наблюдения в согласованной временной зоне и единое определение возврата. Свежие регистрации без этого окна нельзя автоматически записывать в невозвратившиеся. Для конверсии учитывайте задержку события: оплата может произойти позже визита, а данные загрузиться ещё позже. Перед проверкой частот сравните зрелость когорт и полноту загрузки по вариантам. Иначе статистический тест обнаружит отличие доступности данных, которое команда ошибочно назовёт изменением поведения.
Проверка соотношения размеров экспериментальных групп — отдельный вопрос. Если ожидалось равное назначение, а фактические количества сильно отличаются, это сигнал качества рандомизации или учёта, а не тест продуктовой конверсии. Для него используются другие ожидаемые частоты и другая нулевая гипотеза. Не смешивайте проверку назначения, сравнение целевого исхода и анализ сегментов в одном «хи-квадрате». Каждая процедура должна иметь собственный вопрос и место в плане эксперимента.
Ошибки, которые дают уверенный неверный вывод
Первая ошибка — подать проценты вместо количеств. Вы потеряете реальный объём и получите произвольную точность. Вторая — проверять порог пяти по наблюдаемым ячейкам, не посмотрев ожидаемые. Можно пропустить плохое приближение или отвергнуть подходящий метод без основания. Третья — многократно посчитать одного участника по обращениям или кликам. Получится зависимая таблица с искусственно увеличенным n. Исправление во всех трёх случаях начинается с восстановления исходной единицы и числителей, а не со смены критерия.
Четвёртая ошибка — выбрать между поправкой Йейтса и Фишером после сравнения p. Так процедура подгоняется под результат. Пятая — назвать OR отношением рисков и неправильно описать масштаб изменения. Шестая — объявить причинный эффект по двум наблюдательным группам. Для исправления укажите основной метод заранее, подпишите ориентацию эффекта и опишите механизм формирования групп. Статистическая значимость не заменяет контроль смешивающих факторов или случайное назначение; эта граница сохраняется при любом размере выборки.
Как написать результат и что почитать
Для первой таблицы можно написать: «За одинаковое окно событие зарегистрировано у 18/100 в A и 30/100 в B. Разность A − B равна −12 п.п., RR = 0,60. Пирсон без поправки: χ² = 3,947, df = 1, p = 0,0469; в анализе чувствительности двусторонний Фишер даёт p = 0,0679. Вывод о причинности требует сведений о назначении». В реальном протоколе порядок и статус процедур должны быть определены заранее, а рядом с эффектом нужен интервал.
Для практики измените обе строки пропорционально, сохранив доли, и предскажите, что произойдёт: разность долей сохранится, а статистическое свидетельство изменится вместе с объёмом. Затем замените независимые группы повторными наблюдениями тех же людей и объясните, почему уже недостаточно прежней таблицы. Эти два упражнения отделяют размер эффекта от точности и структуру данных от внешнего вида матрицы. Если вы можете объяснить оба перехода, формула Пирсона перестаёт быть чёрным ящиком.
В обзоре Гланца обсудим, как практиковать такие проверки без привязки к старому программному пакету. Отдельный материал про p-value помогает аккуратно сформулировать статистический вывод, а материал про доверительные интервалы — показать его точность. Возвращайтесь к исходным количествам всякий раз, когда спор сводится к одному порогу: зачастую именно таблица и описание окна объясняют больше, чем очередная настройка теста.
Это учебный разбор статистических методов на синтетических данных. Он не является медицинской рекомендацией, диагностическим инструментом или основанием для выбора лечения.
Материалы по теме

Корреляция Спирмена и Пирсона: выбор, расчёт и ошибки
Корреляция Спирмена и Пирсона на условных медицинских данных: линейная и монотонная связь, выбросы, перестановочный тест в Python и перенос в продукт.

Относительный риск и отношение шансов: разница на примерах
Чем относительный риск отличается от отношения шансов: таблица 2×2, абсолютный эффект, доверительные интервалы, случай — контроль и A/B-тест в Python.

Чувствительность и специфичность теста: расчёт на примере
Чувствительность и специфичность теста, PPV и NPV на синтетических данных. Распространённость, пороги, интервалы и перенос в антифрод с кодом Python.