Все материалы
Продуктовая аналитикаматериалстарт

Z-оценка (z-score): формула, пример и как искать выбросы

Что такое z-оценка и как её посчитать: формула z = (x − μ) / σ, пример вручную, перевод в процентиль, SQL с оконными функциями, поиск аномалий, модифицированная z-оценка через медиану и MAD.

КейсПрактика25 сентября 2026 г.14 мин

В понедельник на дашборде выручки торчит суббота, 22 августа: 771 доллар, хотя половина августовских дней укладывается в 450–600. Менеджер спрашивает, аномалия это или просто удачный день. Первое, что приходит в голову аналитику, — посчитать z-оценку и посмотреть, не больше ли она двух. Это правильный инструмент, но у него есть условия, и на растущей метрике он отвечает на другой вопрос, чем кажется. Ниже — формула, расчёт вручную, перевод в процентиль, SQL на учебной базе SQL-курса и три случая, когда правило «|z| > 3 — выброс» подводит.

Что такое z-оценка простыми словами

Z-оценка — это расстояние от значения до среднего, измеренное в стандартных отклонениях. Z = 2 означает, что значение на два стандартных отклонения выше среднего, z = −0,5 — на половину отклонения ниже. Единицы измерения при этом исчезают, поэтому z-оценки выручки, времени и числа событий можно ставить рядом.

Другое название — стандартизированная оценка, по-английски z-score или standard score. Операцию «вычесть среднее и поделить на стандартное отклонение» называют стандартизацией.

  • Знак показывает направление: плюс — выше среднего, минус — ниже.
  • Перевод z в процентиль через нормальное распределение работает, только если данные близки к нормальным.
  • Z-оценка по всему периоду не подходит для метрики с трендом: среднее растущего ряда — это середина тренда, а не «обычный день».
  • Один сильный выброс раздувает стандартное отклонение и прячет остальные. Устойчивая замена — модифицированная z-оценка через медиану и MAD.
  • Z-статистика в A/B-тесте — та же идея, только делят разницу между группами на её стандартную ошибку.

Формула z-оценки

Для генеральной совокупности с известными μ и σ формула выглядит так, как показано ниже. На практике параметры неизвестны, и их заменяют выборочными оценками: z = (x − x̄) / s, где x̄ — среднее выборки, а s — выборочное стандартное отклонение с делителем n − 1. В SQL это avg() и stddev_samp().

Разница между s и σ заметна только на маленьких выборках. На 86 днях выручки из примера ниже stddev_samp даёт 187,73, а stddev_pop — 186,63: z-оценки расходятся меньше чем на 1%. На десяти точках разница уже около 5%.

Сама стандартизация не меняет форму распределения. Если исходные данные скошены вправо, z-оценки будут скошены так же. Меняются только центр (он становится нулём) и масштаб (стандартное отклонение становится единицей).

Z-оценка
z = (x − μ) / σ

x — значение, μ — среднее, σ — стандартное отклонение. Для выборки: z = (x − x̄) / s.

Как посчитать z-оценку: пример вручную

Вернёмся к субботе. В учебной базе оплаты идут с 6 июня по 30 августа 2026 года: 86 календарных дней, из них два дня без единой оплаты. Среднее дневной выручки — 356,3, стандартное отклонение — 187,7. Выручка 22 августа — 771.

Считаем в три шага. Отклонение от среднего: 771 − 356,3 = 414,7. Делим на стандартное отклонение: 414,7 / 187,7 ≈ 2,21. Итог: 22 августа выручка на 2,21 стандартного отклонения выше средней за период.

Нулевые дни, 9 и 11 июня, получают z = (0 − 356,3) / 187,7 ≈ −1,90. Запомните это число: день, когда продукт не заработал ничего, по z-оценке выглядит менее необычным, чем удачная суббота. К этому парадоксу вернёмся через пару разделов.

Как перевести z-оценку в процентиль

Если данные распределены нормально, z-оценка сразу говорит, какая доля значений ниже. Эту долю даёт функция нормального распределения Φ(z). Отсюда правило 68–95–99,7: в пределах ±1σ лежит 68,27% значений, в пределах ±2σ — 95,45%, в пределах ±3σ — 99,73%.

Для z = 2,21 получается Φ ≈ 98,64%: при нормальных данных такой день был бы выше 98,6% остальных. На деле 771 — просто максимум ряда из 86 дней, и процентиль по таблице здесь ничего не добавляет к этому факту.

Коварнее то, что наш ряд почти идеально проходит «проверку» правилом 68–95: в пределах ±1σ лежат 58 дней из 86 (67,4%), в пределах ±2σ — 84 (97,7%). При этом ряд вообще не похож на одно распределение: выручка растёт от десятков долларов в день в начале июня до 600 с лишним в конце августа. Совпадение долей не доказывает нормальность — смотрите на форму, как описано в статье про нормальное распределение.

Z-оценка и доля значений ниже неё при нормальном распределении
zΦ(z), процентильКак читать
−30,13%ниже почти всех значений
−22,28%нижние 2–3%
−115,87%нижняя шестая часть
050,00%ровно среднее, оно же медиана
184,13%выше 84% значений
1,64595,00%верхние 5%
1,9697,50%верхние 2,5%
297,72%верхние 2,3%
399,87%верхние 0,13%
pythonΦ(z) и доли внутри ±kσ через scipy
from scipy.stats import norm

for z in [-3, -2, -1, 0, 1, 1.645, 1.96, 2, 2.21, 3]:
    print(z, round(norm.cdf(z) * 100, 2))   # 2.21 -> 98.64

for k in [1, 2, 3]:
    print(k, round((norm.cdf(k) - norm.cdf(-k)) * 100, 2))   # 68.27, 95.45, 99.73

Как посчитать z-оценку в SQL

В SQL z-оценка — одна строка с оконными функциями. avg(x) over () с пустым окном возвращает среднее по всем строкам и ставит его в каждую строку, stddev_samp(x) over () делает то же со стандартным отклонением. Группировать и соединять таблицу саму с собой не нужно.

Перед этим соберите ряд с календарём. Если посчитать дневную выручку простым group by paid_at, дни без оплат пропадут из ряда: среднее вырастет, стандартное отклонение сожмётся, а самые интересные дни — провалы — исчезнут. generate_series и left join возвращают их с нулём.

Запрос находит два дня с |z| > 2: 9 августа (770, z = 2,20) и 22 августа (771, z = 2,21). Оба — поздний август, когда обычный день и так приносит 500–600. Нулевые дни начала июня с z = −1,90 в список не попали.

Результат на учебной базе: среднее 356,3, стандартное отклонение 187,7
ДатаВыручкаzПопал в |z| > 2
9 июня0−1,90нет
11 июня0−1,90нет
9 августа7702,20да
22 августа7712,21да
Z-оценка дневной выручки и дни с |z| > 2
with calendar as (
  select cast(d as date) as paid_at
  from generate_series(date '2026-06-06', date '2026-08-30', interval 1 day) as t(d)
),
daily as (
  select c.paid_at, coalesce(sum(p.amount), 0) as revenue
  from calendar c
  left join payments p using (paid_at)
  group by c.paid_at
),
z as (
  select
    paid_at,
    revenue,
    (revenue - avg(revenue) over ()) / stddev_samp(revenue) over () as z
  from daily
)
select paid_at, revenue, round(z, 2) as z
from z
where abs(z) > 2
order by paid_at;

Почему z-оценка по всему периоду не видит провалов на растущей метрике

Z-оценка сравнивает каждое значение с одним средним и одним разбросом. Это предполагает, что все дни — наблюдения из одного распределения. У растущей выручки это не так: среднее 356,3 — это уровень второй половины июля, а стандартное отклонение 187,7 в основном измеряет сам рост, а не колебания вокруг обычного уровня.

На графике видно, что средняя дневная выручка недели поднимается от 78 до 612, с одним провалом на неделе 10 августа. Порог «среднее + 2σ» равен 731,7, и его пересекают только два дня позднего августа. Нижний порог «среднее − 2σ» отрицательный: даже полный ноль не может его пробить.

Выходов два. Первый — сравнивать день со скользящей базой: avg(x) over (order by day rows between 28 preceding and 1 preceding) и такое же окно для stddev_samp. Текущий день в базу не входит, иначе он сам сдвигает свою норму. Второй — поделить метрику на то, что задаёт рост. Выручка растёт вместе с аудиторией, поэтому выручка на активного пользователя (ARPDAU) держится около единицы весь период. Её и возьмём дальше.

Дневная выручка по неделям и пороги z-оценки за весь период

Учебная база SQL-курса, недели с понедельника, 8 июня – 30 августа 2026. Порог 731,7 превышают только 9 августа (770) и 22 августа (771).

Лучший день неделиСредняя дневная выручка неделиСреднее за период, 356,3Среднее + 2σ, 731,7

Как один выброс прячет остальные

Считаем ARPDAU как дневную выручку, делённую на число активных пользователей в тот же день, и строим z-оценку тем же запросом. Сильнее всех выделяется 30 августа: ARPDAU 3,23 при типичной единице, z = 5,40. Это не рекорд продаж. Выгрузка событий заканчивается 30 августа в 12:59, поэтому DAU за этот день — 223 вместо обычных 500, а оплаты записаны датой без времени, и их за этот день 29 — как в лучшие полные дни. Z-оценка честно нашла неполный день.

Проблема в том, что этот день успел испортить статистику для остальных. С ним стандартное отклонение ARPDAU равно 0,4118, без него — 0,3348: один день из 86 раздул разброс на 23%. Из-за этого 9 августа, реальный пик продаж, получает z = 1,79 и не проходит порог 2. Уберите 30 августа, и у 9 августа z = 2,28. Так же исчезают из списка 7 и 20 июня. Это называется маскировкой: выброс увеличивает σ и прячет выбросы поменьше.

На коротких рядах маскировка доходит до абсурда. Выборочная z-оценка не может превысить (n − 1) / √n по модулю. Для десяти точек это 2,85, поэтому правило |z| > 3 на десяти днях не сработает никогда, что бы ни случилось. Условный ряд ниже: девять дней около 100 и один день с нулём из-за сбоя. Z-оценка нулевого дня — всего −2,84.

ARPDAU: z-оценка с 30 августа и без него, модифицированная z-оценка
ДатаARPDAUz, все 86 днейz без 30 августаМодифицированная z
7 июня0,25−1,85−2,19−2,80
9 июня0−2,45−2,94−3,68
11 июня0−2,45−2,94−3,68
20 июня0,31−1,70−2,02−2,59
9 августа1,751,792,282,48
30 августа3,235,40—7,73
Условный ряд из десяти дней: z-оценка не дотягивается до порога 3
with t(day, revenue) as (
  values (1, 100.0), (2, 104), (3, 98), (4, 101), (5, 97),
         (6, 103), (7, 99), (8, 102), (9, 100), (10, 0)
)
select
  day,
  revenue,
  round((revenue - avg(revenue) over ()) / stddev_samp(revenue) over (), 2) as z,
  round(0.6745 * (revenue - median(revenue) over ()) / mad(revenue) over (), 2) as modified_z
from t
order by day;
-- день 10: z = -2.84, modified_z = -33.73

Модифицированная z-оценка: медиана и MAD

Устойчивая версия заменяет среднее медианой, а стандартное отклонение — MAD, медианой абсолютных отклонений от медианы. Один экстремальный день почти не двигает ни ту, ни другую. Множитель 0,6745 подгоняет шкалу: на нормальных данных модифицированная z-оценка примерно совпадает с обычной. Порог для выбросов, который предложили Иглевич и Хоглин, — |M| > 3,5.

В DuckDB есть обе функции: median() и mad(), причём mad() возвращает сырую медиану отклонений без коэффициента 1,4826. Обе работают как оконные, так что модифицированная z-оценка в SQL — та же одна строка. В PostgreSQL mad нет: посчитайте медиану через percentile_cont(0.5) within group (order by x) в CTE, затем медиану от abs(x − median) во втором CTE.

На ARPDAU разница видна в таблице выше. Для 9 августа модифицированная z-оценка — 2,48 с 30 августа и 2,51 без него: неполный день её почти не сдвинул, тогда как обычная z прыгнула с 1,79 до 2,28. По порогу 3,5 метод отмечает три дня: 30 августа (7,73) и оба нулевых дня июня (−3,68). Это ровно те дни, которые стоит проверить руками.

Одна ловушка: если больше половины значений совпадают, MAD равна нулю, и формула делит на ноль. Так происходит с суммами отдельных оплат в учебной базе: 706 из 1 251 платежа — ровно 19 долларов, медиана 19, MAD 0. На дискретных данных с тремя тарифами поиск выбросов по отклонениям вообще мало что даёт.

Модифицированная z-оценка
M = 0,6745 × (x − медиана) / MAD

MAD = медиана |x − медиана|. Выброс, если |M| > 3,5.

ARPDAU за 17–30 августа, медиана и порог модифицированной z-оценки

Учебная база SQL-курса. Медиана за 6 июня – 30 августа 1,04, MAD 0,191, порог |M| = 3,5 соответствует ARPDAU 2,03. Пик 30 августа — неполный день: DAU 223, события обрываются в 12:59.

ARPDAUМедиана, 1,04Порог M = 3,5
Обычная и модифицированная z-оценка ARPDAU в одном запросе
with dau as (
  select cast(event_time as date) as day, count(distinct user_id) as dau
  from events
  group by 1
),
rev as (
  select paid_at as day, sum(amount) as revenue
  from payments
  group by 1
),
daily as (
  select d.day, d.dau, coalesce(r.revenue, 0) / d.dau as arpdau
  from dau d
  left join rev r using (day)
  where d.day >= date '2026-06-06'
)
select
  day, dau, round(arpdau, 2) as arpdau,
  round((arpdau - avg(arpdau) over ()) / stddev_samp(arpdau) over (), 2) as z,
  round(0.6745 * (arpdau - median(arpdau) over ())
        / mad(arpdau) over (), 2) as modified_z
from daily
order by day;

Почему правило |z| > 3 ошибается на скошенных данных

Возьмём выручку на покупателя: 912 человек заплатили от 19 до 117 долларов за всё время. Среднее — 33,60, медиана — 29, стандартное отклонение — 17,74, коэффициент асимметрии — 1,77. Распределение скошено вправо: большинство заплатили один раз, меньшинство продлевали подписку.

Правило |z| > 3 отмечает 22 покупателя: 15 человек с суммой 87 (z = 3,01) и 7 человек со 117 (z = 4,70). Если бы распределение было нормальным, выше трёх сигм оказалось бы 0,13% людей, то есть около одного человека из 912. Здесь таких 2,4%, и это не ошибки данных, а самые лояльные клиенты дорогих тарифов, которые заплатили три раза. Удалить их как выбросы — значит выкинуть ту часть выручки, ради которой продукт работает.

Медиана и MAD эту проблему не решают: модифицированная z-оценка тоже отмечает суммы 87 и 117. Скошенность — свойство процесса, а не шум. Для таких метрик смотрите на перцентили, сравнивайте логарифмы или прямо задайте бизнес-правило вроде «больше трёх оплат за месяц — проверить».

Сколько покупателей заплатили каждую сумму за всё время

Учебная база SQL-курса, 912 покупателей. Z-оценка суммы: 57 — 1,32; 78 — 2,50; 87 — 3,01; 117 — 4,70.

Покупателей

Как сравнить величины в разных шкалах через z-оценку

Стандартизация полезна, когда нужно поставить рядом числа в разных единицах. Покупатель 1339 сделал 16 событий в продукте и заплатил 58 долларов. Что в нём необычнее — активность или деньги? Среди 912 покупателей среднее число событий — 8,87 при стандартном отклонении 3,24, поэтому z по событиям равна 2,20. Z по выручке — 1,38. Активность выделяется сильнее: на неё и стоит смотреть, если вы ищете будущих амбассадоров.

Сравнивать z-оценки имеет смысл, если они посчитаны на одной и той же группе. Z по событиям среди всех 4 613 пользователей и z по выручке среди 912 покупателей отвечают на разные вопросы.

Та же операция в машинном обучении называется z-нормализацией признаков, в scikit-learn это StandardScaler. Она нужна моделям, чувствительным к масштабу: линейным с регуляризацией, k-ближайших соседей, k-means. Среднее и стандартное отклонение считают только на обучающей выборке и применяют к тестовой. Если посчитать их на всех данных сразу, в признаки протечёт информация из теста.

Z-оценки активности и выручки для каждого покупателя
with ev as (
  select user_id, count(*) as events from events group by user_id
),
pay as (
  select user_id, sum(amount) as revenue from payments group by user_id
)
select
  e.user_id, e.events, p.revenue,
  round((e.events - avg(e.events) over ()) / stddev_samp(e.events) over (), 2) as z_events,
  round((p.revenue - avg(p.revenue) over ()) / stddev_samp(p.revenue) over (), 2) as z_revenue
from ev e
join pay p using (user_id)
order by e.user_id;
-- user_id 1339: events 16, revenue 58, z_events 2.20, z_revenue 1.38

Чем z-оценка отличается от z-теста

Z-оценка описывает одно значение относительно разброса отдельных значений. Z-тест описывает разницу между группами относительно разброса этой разницы, то есть её стандартной ошибки. Формула та же — «отклонение, делённое на меру разброса», меняются числитель и знаменатель.

В эксперименте onboarding_checklist конверсия с чек-листом — 467 из 1 541 (30,30%), в контроле — 306 из 1 527 (20,04%). Стандартная ошибка разницы — 0,0156, z = (0,3030 − 0,2004) / 0,0156 ≈ 6,60. Разница в 10 процентных пунктов — это 6,6 стандартной ошибки, при нулевой гипотезе такое почти невозможно: p-value меньше 0,0001.

Путать их опасно в одну сторону. Z-оценка пользователя, равная 2, ничего не говорит о статистической значимости. Z-статистика теста, равная 2, ничего не говорит о том, насколько необычен отдельный пользователь. Подробнее о тесте — в статье про статистическую значимость, а посчитать свой эксперимент можно в калькуляторе.

Z-статистика для разницы конверсий
z = (p₁ − p₂) / √(p₁(1 − p₁)/n₁ + p₂(1 − p₂)/n₂)

Числитель — наблюдаемая разница, знаменатель — её стандартная ошибка.

Z-статистика эксперимента onboarding_checklist
with g as (
  select variant, count(*) as n, avg(case when converted then 1.0 else 0 end) as cr
  from experiment_exposures
  where experiment_name = 'onboarding_checklist'
  group by variant
),
w as (
  select
    max(cr) filter (where variant = 'checklist') as p1,
    max(n)  filter (where variant = 'checklist') as n1,
    max(cr) filter (where variant = 'control')   as p2,
    max(n)  filter (where variant = 'control')   as n2
  from g
)
select
  round(sqrt(p1 * (1 - p1) / n1 + p2 * (1 - p2) / n2), 4) as se,   -- 0.0156
  round((p1 - p2) / sqrt(p1 * (1 - p1) / n1 + p2 * (1 - p2) / n2), 2) as z   -- 6.6
from w;

Что попробовать на учебной базе

Проверьте свою метрику в калькуляторе z-оценки, а потом повторите запросы в песочнице SQL-курса. Для начала посчитайте z-оценку дневного DAU по всему периоду и найдите дни с |z| > 2: из-за роста аудитории картина будет похожа на выручку. Затем замените пустое окно на скользящее rows between 28 preceding and 1 preceding и сравните списки.

Второе упражнение — исключить 30 августа фильтром where day < date '2026-08-30' и посмотреть, как меняются z-оценки остальных дней ARPDAU и почему модифицированная z-оценка почти стоит на месте.

Продолжить чтение
Вся библиотека
Продуктовая аналитика21 июля 2026 г.11 мин
Ряд одинаково низких столбцов и один, поднимающийся намного выше остальных.

Выбросы в данных: что удалять, что оставить и почему правило IQR почти всегда врёт на деньгах

Разбор на модельном наборе из 2000 заказов: правило 1,5×IQR помечает 6% заказов, из которых аномальны пять. Как отличить ошибку от редкого клиента и что делать с каждым случаем.

Читать материал
Продуктовая аналитика25 сентября 2026 г.12 мин
Ломаная линия, которая сильно скачет слева и постепенно ложится на горизонтальную прямую справа

Закон больших чисел простыми словами: формулировка и примеры

Закон больших чисел: почему среднее и доля стабилизируются с ростом выборки. Пример с монетой, накопленная конверсия A/B-теста в SQL, слабая и сильная форма, ошибка игрока и когда закон работает медленно.

Читать материал
Продуктовая аналитика25 сентября 2026 г.11 мин
Большое поле одинаковых точек, из которого выделена небольшая группа: абстрактная схема генеральной совокупности и выборки.

Генеральная совокупность и выборка: что это и как не перепутать

Генеральная и выборочная совокупность простыми словами: параметр и статистика, способы отбора, объём выборки и погрешность. Пример на SQL: честная выборка против удобной.

Читать материал