P90 времени ответа в pandas: как сравнить команды и не спрятать хвост

У команды A большинство клиентов получает ответ за минуту, но некоторые ждут почти два часа. Команда B отвечает всем примерно за восемь минут. Одно среднее плохо передаёт различие этих процессов. Посчитаем распределение времени ответа в pandas и подготовим отчёт, по которому руководитель сможет выбрать конкретное улучшение.

Определяем начало и конец ожидания

Возьмём время от поступления обращения до первого содержательного ответа сотрудника. Автоматическое уведомление о получении заявки ответом не считается. Эти правила нужно согласовать до выгрузки: иначе команда с быстрым ботом окажется лучше той, которая сразу отвечает по существу. В примере все обращения уже получили ответ, а длительность измеряется в календарных минутах.

Если в рабочем отчёте есть ещё ожидающие обращения, отдельно покажите их количество и текущий возраст. Исключение самых долгих открытых заявок улучшает распределение завершённых искусственно. Для оценки полного времени ожидания пригодятся методы с цензурированием; для операционного контроля достаточно начать с явного отдельного списка открытых случаев и их возраста.

Ещё одно решение относится к повторным сообщениям. Клиент может написать три раза по одному вопросу. Если система создаёт три обращения, нагрузка и распределение будут другими, чем при объединении в один тикет. Сохраняйте устойчивый идентификатор обращения и проверяйте дубли до расчёта длительности.

Какие показатели поставить рядом

Среднее показывает среднее время ожидания ответа, медиана — середину распределения. P90 обозначает 90-й процентиль: границу, ниже которой лежит примерно 90% наблюдений. Для выбранного договором лимита дополнительно нужна доля обращений дольше лимита. Квантиль и доля нарушений отвечают на разные вопросы, поэтому один показатель не заменяет другой.

В примере у A девяносто ответов по одной минуте и десять по сто. У B сто ответов по восемь минут. Для P90 используем линейную интерполяцию pandas. На дискретных длительностях результат может не совпадать ни с одним реальным обращением. Метод интерполяции должен быть одинаковым между командами и периодами.

Нельзя усреднить P90 отдельных дней и получить P90 недели. Для недельного показателя объедините исходные длительности либо используйте специально поддерживаемое агрегируемое представление распределения. Аналогично общий P90 команды не получается средним квантилей её сотрудников. Это особенно заметно при разном количестве обращений.

import pandas as pd
import numpy as np
d = pd.DataFrame({"team":["A"]*100+["B"]*100,"minutes":[1]*90+[100]*10+[8]*100})
assert d.minutes.ge(0).all()
d["over30"] = d.minutes.gt(30)
r = d.groupby("team").agg(n=("minutes","size"),mean=("minutes","mean"),median=("minutes","median"),p90=("minutes",lambda s:s.quantile(0.9,interpolation="linear")),maximum=("minutes","max"),share_over30=("over30","mean"))
print(r.to_string())
assert np.isclose(r.loc["A","p90"],10.9)
assert r.loc["A","share_over30"] == 0.1
assert r.loc["B","p90"] == 8

От цифр к разбору процесса

Медиана A равна одной минуте, среднее и P90 — примерно 10,9 минуты. При этом реальные долгие ответы занимают 100 минут: интерполированный квантиль не означает, что клиент действительно ждал 10,9. У B все основные показатели равны восьми минутам. Для лимита 30 минут A нарушает его в 10% обращений, B — ни разу.

Сначала разберите десять долгих обращений A: в какую смену они поступили, требовалась ли эскалация, какой продукт затронут. Если это одна очередь сложных вопросов, улучшать нужно маршрутизацию и передачу специалисту. Ускорение уже быстрых ответов не устранит хвост. Для B задача может быть другой: сократить обычное ожидание без ухудшения стабильности.

Сравниваем сопоставимые обращения

Перед рейтингом команд разбейте обращения по сложности, каналу и времени поступления. Команда, которая обслуживает ночные технические инциденты, не сопоставима напрямую с дневной очередью простых вопросов. Покажите распределение внутри одинаковых категорий и долю каждой категории. Это помогает отделить процесс команды от состава работы.

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

Отдельный разбор помогает сохранить в операционном отчёте ещё не закрытые случаи: Просроченные заявки в SQL: почему открытые тикеты нельзя выбрасывать из SLA.

Как оформить рабочую таблицу сравнения

Для каждой команды выведите число обращений, медиану, P90, максимум и долю дольше выбранного лимита. Сортировку выбирайте под вопрос: для клиентского обещания важна доля нарушений, для разбора обычного ожидания — медиана. Если сортировать только по среднему, разные формы распределений снова сольются в один рейтинг.

Для хвоста полезно сохранять ссылки на обращения, которые превысили лимит, с датой поступления и причиной эскалации. Тогда руководитель сможет проверить последовательность действий и найти повторяющийся этап ожидания. После исправления сравните следующий закрытый период при том же составе категорий. Улучшение P90 стоит подтвердить уменьшением конкретных долгих случаев, а не только изменением числа в дашборде.

Продолжить практику

В «Практической аналитике данных» вы разбираете средние, медианы, квартили и распределения, а затем связываете их с бизнес-вопросом. Учебные кейсы доступны через pandas или SQL. В конце вы повторяете анализ на данных нового месяца, собираете дашборд DataLens и формулируете рекомендацию в записке. Откройте программу курса.

Продолжить на практике

  • Практическая аналитика данных ↗

    Превратите знания SQL или Python в аналитическую работу: проверяйте данные, считайте бизнес-метрики, стройте дашборды и объясняйте выводы на трёх прикладных кейсах.