Нормальное распределение: проверка данных и выбор метода
Как проверить нормальное распределение: гистограмма, Q–Q и Шапиро — Уилк. Условные медицинские данные, Python, выбросы и перенос на продуктовые метрики.
Содержание статьи
Вы получили шестнадцать измерений и собираетесь сравнивать группы. В инструкции написано: «сначала проверьте нормальное распределение». После одного теста хочется получить зелёный свет для всех дальнейших расчётов. Но форма данных, форма разностей и распределение среднего отвечают на разные вопросы. Разберём, что проверять, как читать результат и что делать с асимметрией. Медицинские измерения, время ожидания и продуктовые ситуации ниже условные: это собственные учебные данные, а не результаты исследования пациентов.
Когда предположение о нормальности полезно
В рабочем отчёте вопрос «нормальны ли данные?» часто слишком широкий. Если вы хотите оценить среднее время ожидания, важна надёжность вывода о среднем. Если вас интересует доля людей, которые ждут дольше установленного порога, удобнее анализировать эту долю. Если задача — предсказать отдельное следующее наблюдение, хвост распределения может быть существеннее точности среднего. Одинаковая гистограмма в этих трёх случаях ведёт к разным проверкам. Поэтому сначала назовите величину, которую собираетесь оценивать, и только затем выбирайте диагностику её модели.
- Нормальное распределение — модель непрерывной величины с симметричной формой; её задают среднее и стандартное отклонение.
- Перед проверкой определите объект: отдельные наблюдения, разности внутри пар или ошибки модели. Для разных задач объект различается.
- Смотрите на данные и Q–Q-график вместе с формальным тестом. Большое p не доказывает нормальность, маленькое не выбирает следующий метод.
- При отклонении ищите причину и сохраняйте смысл оцениваемого эффекта. Переход к логарифмам или рангам меняет вопрос анализа.
Среднее, масштаб и площадь под кривой
У нормального распределения параметр μ задаёт центр, а σ — масштаб разброса. Увеличение μ перемещает всю кривую вправо без изменения формы. Увеличение σ делает её шире и ниже: общая площадь под плотностью остаётся равной единице. Высота плотности в конкретной точке не является вероятностью ровно этого значения. Для непрерывной модели вероятность относится к интервалу, то есть площади между двумя границами. Это различие пригодится, когда на одном рисунке оказываются гистограмма в количествах и кривая плотности.
Правило приблизительно 68–95–99,7 относится к долям нормальной популяции в пределах одного, двух и трёх стандартных отклонений от μ. Это не обещание, что в любой маленькой выборке будет именно такой состав. Представьте условную модель измерения с μ = 130 и σ = 8: интервал μ ± 2σ равен 114–146. Модельная вероятность попасть туда около 95,45%. Отсюда не следует, что эти границы — медицинская норма или диагностический порог. Статистическая модель распределения и клиническая интерпретация показателя задаются разными основаниями.
Стандартизация z = (x − μ) / σ удобна для сопоставления масштаба. В нашей условной модели значение 146 находится на два стандартных отклонения выше центра. Но стандартизация не превращает произвольную форму в нормальную. Если исходное время ожидания сильно скошено, вычитание среднего и деление на стандартное отклонение сохранят скошенность. Получится другая шкала тех же данных. Это одна из причин, по которой нормализацию чисел в программной библиотеке нельзя путать с проверкой нормального закона.
z = (x − μ) / σСмена центра и масштаба не меняет форму распределения.
Два учебных набора, которые можно проверить целиком
Первый набор — условное систолическое давление шестнадцати разных участников: 112, 118, 121, 124, 125, 127, 128, 129, 130, 131, 132, 134, 135, 137, 139, 143. Измерения специально подобраны для гладкой симметричной картины. Среднее равно 129,06, медиана 129,50, выборочное стандартное отклонение 7,98. Это не случайная выборка из известной клинической популяции: мы используем её, чтобы можно было вручную проследить вычисления и обсуждать форму без скрытого файла.
Второй набор — условное ожидание результата в минутах: 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30, 55. Здесь среднее 12,125 заметно выше медианы 7,50, стандартное отклонение равно 13,56. Одно длинное ожидание влияет на среднее, но не делает это среднее неправильным. Для оценки суммарной нагрузки хвост может быть частью задачи. Для описания обычного опыта полезны медиана и верхние квантили. Выбирать показатель нужно по вопросу, а не по тому, какое число приятнее выглядит.
Таблица квантилей ниже дополняет центр распределения. Межквартильный диапазон показывает среднюю половину наблюдений; высокий квантиль раскрывает правый хвост. Значения вычислены линейным методом NumPy. На маленькой выборке разные соглашения об интерполяции дают немного разные квантили, поэтому название функции и метод стоит сохранять рядом с кодом. Это техническая деталь с содержательным следствием: нельзя объяснять небольшое расхождение между двумя отчётами изменением процесса, пока не проверили, одинаково ли они считают показатель.
| Показатель | Давление, мм рт. ст. | Ожидание, мин |
|---|---|---|
| n | 16 | 16 |
| Среднее | 129,0625 | 12,125 |
| Медиана | 129,5 | 7,5 |
| Q1 | 124,75 | 4,75 |
| Q3 | 134,25 | 12,75 |
| p90 | 138 | 25 |
| SD (ddof=1) | 7,9789 | 13,5640 |
Что увидеть на гистограмме и чего она скрывает
Разбейте диапазон на интервалы и посмотрите, сколько наблюдений попало в каждый. Гистограмма первого набора выглядит относительно симметричной, второго — с длинным правым хвостом. Но выбор ширины корзины влияет на рисунок. Слишком широкие интервалы скроют несколько пиков, слишком узкие превратят маленькую выборку в набор отдельных столбиков. Для шестнадцати чисел полезно рядом показать сами точки или отсортированный ряд. Читатель тогда увидит, что кажущийся провал может быть всего лишь промежутком между двумя наблюдениями.
Несколько пиков — повод проверить состав. Например, в одну выгрузку могли попасть два прибора, разные протоколы измерения или два режима работы лаборатории. В продукте это часто дневная и ночная очередь, мобильный и настольный сценарии, пользователи бесплатного и корпоративного тарифов. Если причина смеси известна и связана с задачей, покажите распределения по группам. Нельзя автоматически разрезать данные на удобные сегменты после просмотра значимости; разрез должен объяснять процесс, а не помогать получить красивый тест.
Проверьте также границы измерения. Округление до целых создаёт повторяющиеся значения, предел обнаружения собирает наблюдения у нижнего края, тайм-аут обрезает правый хвост. Если все значения выше некоторого времени записываются одной константой, обычная гистограмма показывает работу измерительной системы вместе с процессом. Логарифм не восстановит утраченные данные. Сначала нужно понять кодирование и при необходимости использовать модель, учитывающую ограничение или цензурирование. Ошибка здесь появляется ещё до вопроса о нормальности.
Q–Q-график: сравнивайте квантили, а не силуэт
На нормальном Q–Q-графике отсортированные наблюдения сопоставляются с теоретическими нормальными квантилями. При подходящей форме точки располагаются примерно вдоль прямой; её положение и наклон зависят от центра и масштаба данных. Систематический изгиб подсказывает, где эмпирическая форма расходится с моделью. Отдельная далёкая точка может быть выбросом, а последовательное отклонение хвоста — свойством всего процесса. График не сообщает причину автоматически: причину ищут в данных, протоколе и предметном контексте.
Не требуйте идеальной прямой от небольшой выборки. Даже случайные наблюдения из нормальной модели отклоняются от неё. Полезно думать о характере расхождения: оно устойчиво по всему хвосту или связано с одним наблюдением? Сохраняется ли после исправления документированной ошибки? Меняется ли при учёте известных групп? Высокая корреляция точек с линией сама по себе не является универсальным сертификатом нормальности. В блоке Python показано, как получить координаты графика; оценивать нужно картину, а не превращать ещё одно число в обязательный проходной балл.
Шапиро — Уилк: что означает результат
Критерий Шапиро — Уилка проверяет нулевую гипотезу о нормальном распределении. Для первого учебного набора W ≈ 0,9903 и p ≈ 0,9994; для времени ожидания W ≈ 0,6956 и p ≈ 0,000151. Первый результат не доказывает нормальность популяции, тем более что числа здесь подобраны вручную. Второй показывает сильное расхождение с нормальной моделью в рамках этого теста. Нельзя прочитать p как вероятность того, что данные нормальны, или вычесть его из единицы и получить уверенность в альтернативе.
У малой выборки тест может не заметить отклонение, которое было бы видно на большем объёме. У большой выборки он может обнаружить очень небольшое отклонение. Поэтому «не отвергли» и «хорошая модель для моей задачи» не равнозначны. Документация SciPy отдельно предупреждает: для размеров более 5000 точность p у этой реализации может быть недостаточной, хотя статистика W вычисляется корректно. Ограничение реализации — дополнительная причина читать документацию, а не механически запускать одну функцию на любом столбце.
Не заменяйте Шапиро первым попавшимся тестом без проверки его условий. Например, классическая калибровка критерия Колмогорова — Смирнова для полностью заданного распределения отличается от случая, когда параметры нормальной модели оценены на тех же данных. Подставить выборочные среднее и отклонение и затем интерпретировать стандартное p как будто параметры известны заранее — некорректный путь. Для вводной диагностики вполне достаточно понятного набора графиков, проверки происхождения данных и корректно применённого теста с описанными ограничениями.
Запуск Python и чтение каждого вывода
Код ниже сам создаёт два массива и выводит среднее, медиану, стандартное отклонение, квантили и результат Шапиро — Уилка. Для стандартного отклонения указано ddof=1: это выборочная оценка с делением суммы квадратов отклонений на n − 1. Не меняйте её молча на стандартную настройку NumPy, если сравниваете результат с учебником или другим пакетом. Числа в статье проверены в NumPy 2.4.6 и SciPy 1.16.3; последние знаки при другой версии могут отличаться из-за вычислительных деталей.
Для построения Q–Q в ноутбуке можно передать ось Matplotlib аргументом plot функции probplot. В нашем исполняемом блоке дополнительные графические зависимости не нужны: он возвращает пары квантилей, которые можно проверить и перенести в визуализацию. Сохранение исходного массива и параметров расчёта полезнее снимка экрана с одним p. Другой аналитик сможет заменить одно наблюдение, повторить расчёт и проверить, действительно ли ваше объяснение реакции метода соответствует данным, а не случайному оформлению графика.
import numpy as np
from scipy import stats
# Условные учебные значения, не реальные пациенты.
pressure = np.array([112,118,121,124,125,127,128,129,130,131,132,134,135,137,139,143.])
waiting = np.array([2,3,3,4,5,5,6,7,8,9,10,12,15,20,30,55.])
for name, x in [("pressure", pressure), ("waiting", waiting)]:
print(name, "mean, median, sd:", x.mean(), np.median(x), x.std(ddof=1))
print("Q1, Q3, p90:", np.quantile(x, [.25, .75, .9], method="linear"))
print("Shapiro:", stats.shapiro(x))
theoretical, observed = stats.probplot(x, dist="norm", fit=False)
print("Q-Q pairs:", list(zip(theoretical.round(3), observed)))
print("log waiting:", stats.shapiro(np.log(waiting)))
for k in (1, 2, 3):
print("normal probability within", k, "sd:", stats.norm.cdf(k)-stats.norm.cdf(-k))Распределение среднего не равно распределению людей
Центральная предельная теорема объясняет, почему среднее большого числа независимых одинаково распределённых наблюдений с конечной дисперсией при подходящих условиях имеет приблизительно нормальное выборочное распределение после стандартизации. Речь о мысленном повторении выборок и вычислении среднего в каждой. Отдельные длительности ожидания при этом не становятся симметричными. Это помогает понять, почему умеренная ненормальность исходных данных не обязательно делает вывод о средних непригодным на достаточно большой выборке.
Однако универсальной границы «после тридцати всё нормально» нет. Скорость приближения зависит от хвостов, асимметрии, зависимости и баланса групп. Сильно скошенная выручка с редкими крупными платежами может потребовать гораздо больше информации, чем почти симметричная физическая величина. Десятки тысяч событий одного небольшого набора пользователей тоже не являются десятками тысяч независимых наблюдений. Прежде чем ссылаться на большой n, посчитайте независимые единицы и проверьте, не определяет ли результат несколько необычных участников.
Что делать, если распределение не нормальное
Первый вариант — оставить исходную шкалу и использовать метод, подходящий к интересующей величине и данным. Если задача относится к среднему, оцените размер групп, хвосты, выбросы и устойчивость вывода; вариант Уэлча снимает предположение равных дисперсий, но не все остальные проблемы. Можно рассмотреть бутстрэп доверительного интервала, если его схема соответствует независимым единицам и данным хватает информации о хвосте. Перевыборка не создаёт ненаблюдавшихся редких событий и не исправляет смещение отбора.
Второй вариант — преобразовать шкалу с содержательной интерпретацией. Логарифм положительной длительности превращает мультипликативные изменения в аддитивные. В нашем примере логарифмы времени дают W ≈ 0,9748 и p ≈ 0,9096. Это демонстрация изменения формы, а не основание объявить логарифм единственно правильным решением. Среднее логарифмов после обратного преобразования даёт геометрическое среднее. Разность средних логарифмов после экспоненты связана с отношением геометрических средних, а не с разностью арифметических средних минут.
Третий вариант — поставить ранговый вопрос. Критерий Манна — Уитни сравнивает две независимые выборки через порядок значений; при дополнительных предпосылках его можно трактовать как проверку сдвига положения. Он не является универсальной заменой теста средних и не обязан отвечать на вопрос о медианах при разной форме распределений. Если вам нужна медиана или конкретный квантиль, задайте эту величину прямо и выберите процедуру для неё. Изменение вопроса может быть разумным, но его нужно объяснить читателю.
Четвёртый вариант — изменить модель процесса. Для бинарного исхода естественнее работать с вероятностью события, для счётных данных — с моделью счётчика, для времени с незавершённым наблюдением — учитывать цензурирование. Нельзя заставлять каждую переменную соответствовать нормальной кривой только потому, что знаком один критерий. При сложном дизайне обсуждение со статистиком должно начинаться с описания данных и решения, а не с просьбы подобрать преобразование, которое наконец даст большое p нормальности.
Пропуски и единицы измерения: две проверки перед графиком
Проверьте, не объединены ли в одном массиве разные единицы. Минуты и секунды создают ложный хвост, а ноль, которым закодировали пропуск, — отдельный пик. В условной очереди значение 55 может быть корректным долгим ожиданием или ошибкой импорта; график не различит эти причины без исходного журнала. Исправление документированной ошибки нужно сохранить в коде и описать отдельно от статистического преобразования. Иначе следующий аналитик не поймёт, изменили вы данные по протоколу или убрали неудобную точку.
Если отсутствующие наблюдения исключаются, сравните долю пропусков и причины по группам. Красивое распределение оставшихся не подтверждает репрезентативность. Например, система могла переставать записывать длительность после тайм-аута: тогда самые долгие случаи исчезнут ещё до построения гистограммы. Для продуктовой метрики это особенно коварно, потому что после технического сбоя хвост выглядит короче и среднее лучше. Сначала восстановите механизм измерения и только затем обсуждайте, насколько нормальная модель подходит к наблюдаемым значениям.
Продуктовый пример: скорость первой ценности
Представим сервис, где пользователя считают активированным после первого завершённого проекта. Среди активированных время до результата имеет длинный правый хвост. Команда хочет сократить ожидание и начинает с проверки нормальности этого времени. Но раньше формы возникает вопрос отбора: новый интерфейс мог изменить саму вероятность завершения проекта. Сравнение только активированных условно на событии после назначения варианта может дать смещённую картину даже при идеально симметричных временах. Нужно заранее определить, какой эффект тестируем.
Один возможный основной исход — доля назначенных пользователей, завершивших проект в течение полного семидневного окна. Он бинарный и не требует нормальности индивидуальных нулей и единиц. Время среди завершивших можно показать как дополнительное описание с явным ограничением. Если же интересует именно время до активации, не выбрасывайте неуспевших: для такой постановки понадобится анализ времени до события. Во всех вариантах сначала обеспечьте зрелость окна и корректное назначение, затем выбирайте статистическую процедуру.
Для операционной нагрузки среднее всё ещё может быть нужным: сумма времени равна среднему, умноженному на число наблюдений. Медиана удобнее описывает середину опыта, но не восстановит суммарную нагрузку. Покажите обе величины вместе с верхним квантилем и числом наблюдений, если они отвечают на разные решения команды. Ненормальность здесь становится полезной характеристикой процесса: хвост указывает, где искать длинные сценарии и кому они принадлежат, а не только мешает получить разрешение на тест.
Пять ошибок и их последствия
Удалить всё дальше трёх стандартных отклонений — значит применить правило, основанное на определённой модели, прежде чем проверить саму модель. Для настоящего правого хвоста вы удалите часть процесса, измените среднее и недооцените нагрузку. Сначала отделите ошибки измерения от редких корректных наблюдений. Проверить нормальность смеси «до» и «после» для парного теста — значит диагностировать другую величину. Исследуйте разности внутри участников и независимость между ними; это следует из задачи, а не из удобства объединённого столбца.
Переключиться на ранги после малого p Шапиро и продолжить писать про среднюю выручку — значит заменить оцениваемый эффект незаметно для читателя. Результат может быть верным для рангов, но бесполезным для бюджета. Признать модель нормальной из-за большого p на крошечном наборе — значит спутать нехватку свидетельств с подтверждением. И наконец, перебрать преобразования до удобного p — значит подогнать процедуру под наблюдения без отражения этой свободы в выводах. Покажите обоснованный основной анализ и чувствительность, а не скрытую конкуренцию настроек.
Что почитать и как закончить проверку
В рабочей заметке запишите, какая величина проверялась, как выглядит распределение, что означает результат диагностики для вашего метода и что вы решили делать. Например: «Время ожидания скошено вправо; для расчёта нагрузки сохраняем арифметическое среднее, показываем хвост отдельно и проверяем устойчивость интервала по независимым участникам». Это полезнее фразы «данные плохие». Хорошая диагностика заканчивается выбором модели и ясной интерпретацией, а не оценкой набора по принципу прошёл или не прошёл.
Для дальнейшего чтения подойдёт наш обзор «Наглядной медицинской статистики» Петри и Сэбина: он помогает организовать переход от описания данных к выбору метода и показывает границы краткого справочника. Подробности сравнений средних и рангов разобраны в отдельных материалах. Не пытайтесь решить все вопросы нормальности заранее: возьмите одну свою метрику, выпишите её единицу и цель, проверьте происхождение хвоста и затем объясните коллегам, какое решение меняется благодаря этому знанию.
Это учебный материал о статистических методах. Медицинские числа синтетические; они не задают референсные интервалы, диагностические пороги или рекомендации по лечению.
Материалы по теме

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

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

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