Перцентиль, квантиль и квартиль: что это и как посчитать
Перцентиль — значение, ниже которого лежит заданная доля наблюдений. Чем перцентиль отличается от квантиля и квартиля, что значат P50, P90 и P99, как считать в SQL, Excel и Python и почему перцентили нельзя усреднять.
Содержание статьи
Команда хочет отправлять push-напоминание тем, кто не возвращался «дольше обычного». В дашборде написано, что средняя пауза между действиями пользователя — 96 часов, и напоминание предлагают ставить на четвёртый день. Но половина пауз в тех же данных короче 47 часов, а каждая десятая длиннее 260. Для типичного пользователя четыре дня тишины — уже вдвое дольше обычного, а тем, кто привычно возвращается через полторы недели, напоминание придёт слишком рано. Такие вопросы решают не средним, а перцентилями.
Коротко
- Перцентиль — это значение, ниже которого лежит заданный процент наблюдений. P90 = 260 часов значит, что 90% пауз короче 260 часов, а 10% — длиннее.
- «Процентиль» и «перцентиль» — одно и то же слово в двух написаниях.
- Квантиль — то же самое в долях от 0 до 1: квантиль 0,9 равен P90. Квартили делят данные на четыре части: Q1 = P25, Q2 = P50 = медиана, Q3 = P75.
- На данных с длинным хвостом — деньги, время, число покупок — среднее уезжает вправо, а перцентили описывают реальных пользователей.
- Способов вычисления несколько.
percentile_contинтерполирует между соседними значениями,percentile_discвозвращает одно из существующих. На малых выборках ответы заметно расходятся. - Перцентили нельзя усреднять по дням, каналам или серверам. Их считают по исходным наблюдениям.
Что такое перцентиль простыми словами
Выстройте все значения по возрастанию. Перцентиль с номером p — это точка на этой шкале, левее которой оказывается p% наблюдений. P50 делит данные пополам и совпадает с медианой. P90 отсекает 10% самых больших значений, P99 — последний процент.
Главное отличие от среднего: перцентиль отвечает на вопрос «сколько наблюдений укладывается в порог». «Среднее время ответа 293 мс» ничего не обещает конкретному запросу. «90% запросов быстрее 480 мс» — обещание, которое можно проверить и записать в договор.
Написание зависит от традиции: в русских учебниках статистики чаще «процентиль», в IT и мониторинге — «перцентиль», от английского percentile. Excel называет функцию ПРОЦЕНТИЛЬ, Grafana и Prometheus пишут p90 и p99. Смысл везде один.
Перцентиль, квантиль, квартиль и дециль: в чём разница
Все четыре слова описывают одну идею — точку, которая отделяет заданную долю отсортированных данных. Различаются только шкала и шаг деления.
Квантиль — общее название, его задают долей: квантиль 0,95. Перцентили делят данные на сто частей, децили — на десять, квартили — на четыре. Поэтому третий квартиль, девятый дециль и квантиль 0,75 легко перевести друг в друга по таблице ниже.
| Название | На сколько частей делит | Пример | То же самое |
|---|---|---|---|
| Квантиль | любая доля от 0 до 1 | квантиль 0,9 | P90, девятый дециль |
| Перцентиль (процентиль) | 100 | P95 | квантиль 0,95 |
| Дециль | 10 | D9 | P90, квантиль 0,9 |
| Квартиль | 4 | Q1, Q2, Q3 | P25, P50, P75 |
| Медиана | 2 | Q2 | P50, квантиль 0,5 |
Что значат P50, P90, P95 и P99
Номер перцентиля выбирают под вопрос. P50 — типичный случай: медианная сумма покупки, медианная длина сессии. P90 и P95 — «почти все»: за сколько грузится страница у большинства, какую сумму не превышают 95% заказов. P99 — край, который важен там, где редкий отказ стоит дорого: оплата, авторизация, отправка отчёта.
Время ответа сервиса — классический пример. Если P50 равен 170 мс, а P99 — 2 секунды, медленный запрос встречает не «кто-то иногда», а каждый сотый. На тысяче запросов в минуту это десять человек каждую минуту.
В продукте то же самое с деньгами. Медиана выручки на пользователя в учебной базе — 0: из 4 613 пользователей платили только 912. P90 — 29, P99 — 78, максимум — 117. Среднее 6,64 не похоже ни на кого: у неплатящих выручка ноль, у платящих — от 19 и выше.
Про то, как выбирать между средним и медианой для центра, есть отдельный разбор. Здесь важно другое: медиана — это частный случай перцентиля, и всё сказанное ниже про способы расчёта относится и к ней.
Почему перцентили честнее среднего на скошенных данных
Вернёмся к паузам из вступления. В учебной базе у 4 613 пользователей 30 728 пауз между соседними действиями. Их среднее — 95,8 часа, медиана — 47, P90 — 260, P99 — 625, самая длинная пауза — 1 391 час.
Среднее почти вдвое больше медианы и стоит между P50 и P75: короче среднего 68,5% пауз. Так обычно и бывает, когда снизу есть жёсткий ноль, а сверху ограничений нет. Несколько пользователей, вернувшихся через месяц, сдвигают среднее сильнее, чем тысячи вернувшихся через день.
Для задачи с напоминанием перцентили дают готовые правила. Порог на P50, 47 часов, сработает примерно на каждой второй паузе — это уже рассылка, а не напоминание. Порог на P90, 260 часов, или около 11 дней, тронет только каждую десятую паузу — тех, кто выпал из своего обычного ритма. У порога «по среднему» такого прочтения нет.
Учебная база SQL-курса, DuckDB, 30 728 интервалов. Среднее стоит между медианой и третьим квартилем: 68,5% пауз короче него.
with gaps as (
select
user_id,
extract(epoch from event_time - lag(event_time) over (
partition by user_id order by event_time
)) / 3600 as gap_hours
from events
)
select
count(gap_hours) as n,
round(avg(gap_hours), 1) as mean_h,
percentile_cont(0.5) within group (order by gap_hours) as p50_h,
percentile_cont(0.9) within group (order by gap_hours) as p90_h,
percentile_cont(0.99) within group (order by gap_hours) as p99_h,
max(gap_hours) as max_h
from gaps;Как посчитать перцентиль вручную
Возьмём десять времён ответа в миллисекундах, уже отсортированных: 120, 130, 140, 150, 160, 180, 200, 250, 400, 1 200. Среднее — 293 мс, и оно больше P80: восемь запросов из десяти быстрее среднего.
Способ с интерполяцией. Позиция P90 равна 1 + (n − 1) × 0,9 = 9,1. Девятое значение — 400, десятое — 1 200, и мы проходим 0,1 пути между ними: 400 + 0,1 × 800 = 480 мс. Так считают percentile_cont в SQL, ПРОЦЕНТИЛЬ.ВКЛ в Excel и numpy по умолчанию.
Дискретный способ. Берём первое значение, до которого накопилось не меньше 90% наблюдений: это девятое из десяти, 400 мс. Ответ всегда одно из реальных значений. Так работает percentile_disc.
Третий вариант — позиция (n + 1) × 0,9 = 9,9, то есть почти десятое значение: 400 + 0,9 × 800 = 1 120 мс. Так считает ПРОЦЕНТИЛЬ.ИСКЛ.
Три честных метода, три ответа: 400, 480 и 1 120. На десяти точках P90 определяется двумя крайними значениями и очень неустойчив. На тысячах наблюдений методы почти сходятся, но на маленьких сегментах всегда пишите, каким способом считали.
| Метод | Где встречается | Медиана | P90 |
|---|---|---|---|
| Линейная интерполяция | percentile_cont, ПРОЦЕНТИЛЬ.ВКЛ, numpy и pandas по умолчанию | 170 | 480 |
| Ближайшее снизу по накопленной доле | percentile_disc, numpy method='inverted_cdf' | 160 | 400 |
| Позиция (n + 1) × p | ПРОЦЕНТИЛЬ.ИСКЛ, numpy method='weibull' | 170 | 1 120 |
percentile_cont и percentile_disc в SQL
В PostgreSQL и DuckDB перцентили считают агрегатами с синтаксисом within group (order by …). percentile_cont возвращает интерполированное значение, которого может не быть в данных. percentile_disc возвращает реальное значение из столбца.
На дневном DAU учебной базы за 91 день медиана по обоим методам — 335. А вот P25 даёт 207 и 204, P95 — 529,5 и 530. Половина пользователя в P95 выдаёт интерполяцию: percentile_cont может вернуть дробь даже на целых числах.
Какой выбирать. Для непрерывных величин — времени, денег — обычно percentile_cont. Для величин, где промежуточное значение бессмысленно или ответ нужен как реальная строка — число товаров в заказе, тариф, — percentile_disc.
Отличия между системами тоже есть. В PostgreSQL нет функции median(), медиану пишут как percentile_cont(0.5). В DuckDB есть median(), quantile_cont и quantile_disc. В ClickHouse функция quantile по умолчанию приближённая, точный результат даёт quantileExact.
with daily as (
select event_time::date as day, count(distinct user_id) as dau
from events
group by 1
)
select
percentile_cont(0.25) within group (order by dau) as p25_cont,
percentile_disc(0.25) within group (order by dau) as p25_disc,
percentile_cont(0.5) within group (order by dau) as p50_cont,
percentile_disc(0.5) within group (order by dau) as p50_disc,
percentile_cont(0.95) within group (order by dau) as p95_cont,
percentile_disc(0.95) within group (order by dau) as p95_disc
from daily;Как посчитать перцентиль в Excel и Python
В Excel две пары функций. ПРОЦЕНТИЛЬ.ВКЛ(диапазон; 0,9) и КВАРТИЛЬ.ВКЛ(диапазон; 1) используют линейную интерполяцию и совпадают с percentile_cont. Версии .ИСКЛ считают по позиции (n + 1) × p и для крайних долей на малых выборках возвращают ошибку #ЧИСЛО!. Старая ПРОЦЕНТИЛЬ без суффикса работает как .ВКЛ. Обратите внимание: доля пишется как 0,9, а не 90.
В numpy две функции с разной шкалой: np.percentile принимает проценты от 0 до 100, np.quantile — доли от 0 до 1. Перепутать их легко, и np.quantile(x, 90) упадёт с ошибкой. Метод задаётся параметром method, в старых версиях numpy он назывался interpolation. В pandas Series.quantile(0.9) по умолчанию тоже использует линейную интерполяцию.
import numpy as np
ms = np.array([120, 130, 140, 150, 160, 180, 200, 250, 400, 1200])
np.percentile(ms, 90) # 480.0 — как percentile_cont
np.percentile(ms, 90, method='inverted_cdf') # 400 — как percentile_disc
np.percentile(ms, 90, method='weibull') # 1120.0 — как ПРОЦЕНТИЛЬ.ИСКЛ
np.quantile(ms, 0.9) # 480.0 — доля, а не процентМежквартильный размах и ящик с усами
Межквартильный размах, IQR, — это Q3 − Q1: ширина средней половины данных. В отличие от стандартного отклонения, он не реагирует на крайние значения, поэтому им описывают разброс скошенных распределений.
На нём построен ящик с усами (box plot). Ящик идёт от Q1 до Q3, линия внутри — медиана. Усы тянутся до самых дальних точек, которые лежат не дальше 1,5 × IQR от краёв ящика. Всё, что за усами, рисуют отдельными точками как кандидатов в выбросы.
У пауз между действиями Q1 = 22 часа, Q3 = 121, IQR = 99. Верхняя граница — 121 + 1,5 × 99 = 269,5 часа. За ней 2 664 паузы, 8,7% всех. Это не мусор, а обычные пользователи, которые вернулись через 11 дней и позже. На данных с длинным хвостом правило 1,5 × IQR помечает заметную долю нормальных значений, поэтому используйте его как повод посмотреть, а не как фильтр для удаления.
IQR = Q3 − Q1; выброс, если x < Q1 − 1,5 × IQR или x > Q3 + 1,5 × IQRДля пауз между действиями: 22 − 148,5 < 0, поэтому нижней границы фактически нет; верхняя — 269,5 часа.
Перцентили в SLA и мониторинге
Обязательства по скорости почти всегда формулируют через перцентили: «P95 времени ответа API не больше 300 мс за скользящие 5 минут». В такой формулировке три части, и без любой из них число становится спорным.
Окно: за минуту, час или сутки. P99 за минуту на слабом трафике считается по нескольким десяткам запросов и прыгает от шума. Объект: запрос, пользователь или сессия. P90 по запросам и P90 по пользователям — разные числа, потому что активные пользователи делают больше запросов. Метод: точный расчёт, приближённый или по корзинам гистограммы. В Prometheus перцентиль вычисляют функцией histogram_quantile по заранее заданным корзинам, и его точность зависит от их границ.
Отдельно проверяйте размер выборки. Чтобы P99 опирался хотя бы на десяток наблюдений в хвосте, нужна примерно тысяча наблюдений в окне.
Почему нельзя усреднять перцентили
Самая частая ошибка — сводная плитка «P90 за месяц» как среднее из дневных P90. Или общий P90 как среднее по сегментам. Перцентиль объединённых данных не выводится из перцентилей частей: нужны сами наблюдения.
Проверим на учебной базе. P90 паузы между действиями по всем каналам — 260 часов. По каналам: organic — 240, referral — 218, partner — 310, paid_search — 311,9. Простое среднее четырёх чисел — около 270 часов, на 10 часов выше правды. Взвешенное по числу пауз — 253,8, на 6 часов ниже. Ни одна арифметика над готовыми перцентилями не даёт 260.
С днями то же самое. За 1–29 августа P90 всех пауз — 291 час, а среднее 29 дневных P90 — 298,9. Здесь расхождение небольшое, но оно ничем не ограничено: на реальных данных с неравномерным трафиком по дням разница бывает кратной.
Решение — считать перцентиль по исходным строкам за нужный период. Если сырых данных слишком много, храните не готовые перцентили, а то, что складывается: гистограммы с фиксированными корзинами или скетчи вроде t-digest.
| Срез | Пауз | P90 |
|---|---|---|
| organic | 13 306 | 240 |
| referral | 8 740 | 218 |
| partner | 4 839 | 310 |
| paid_search | 3 843 | 311,9 |
| Среднее четырёх P90 | — | ≈ 270 |
| Среднее, взвешенное по числу пауз | — | 253,8 |
| Все каналы, по исходным паузам | 30 728 | 260 |
with gaps as (
select
user_id,
extract(epoch from event_time - lag(event_time) over (
partition by user_id order by event_time
)) / 3600 as gap_hours
from events
)
select
coalesce(u.channel, 'все каналы') as channel,
count(g.gap_hours) as n,
round(percentile_cont(0.9) within group (order by g.gap_hours), 1) as p90_h
from gaps as g
join users as u on u.user_id = g.user_id
group by grouping sets ((u.channel), ())
order by n desc;Типичные ошибки
Большинство ошибок с перцентилями не вычислительные: число посчитано верно, но не для того объекта или не тем способом, который ожидает читатель.
- Усреднять перцентили по дням, сегментам или серверам.
- Показывать P99 по выборке из пятидесяти наблюдений: это практически максимум.
- Сравнивать перцентили, посчитанные разными методами или в разных инструментах, и искать причину расхождения в данных.
- Путать
np.percentileиnp.quantileи передавать 90 вместо 0,9. - Считать перцентиль по событиям, когда вопрос про пользователей: самые активные попадут в выборку много раз.
- Удалять всё, что за границей 1,5 × IQR, на данных с длинным хвостом.
- Не указывать окно и объект в SLA: «P95 = 300 мс» без «за 5 минут по запросам» нельзя проверить.
Что читать дальше
Перцентили — язык для краёв распределения. Как они сочетаются с разбросом, формой данных и выборкой, разобрано в большом материале о статистике для аналитика.
Материалы по теме

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

Нулевая гипотеза простыми словами: что это и как её формулировать
Нулевая гипотеза (H0) — утверждение, что эффекта или разницы нет. Чем она отличается от альтернативной гипотезы H1, как формулировать H0 для A/B-теста и продуктовых вопросов, что значит «отвергнуть» и «не отвергнуть» H0 — с расчётом z-теста на учебной базе.