Ноль продаж при пустом складе: как не принять ограниченный спрос за отсутствие спроса

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

Выделить время, в которое покупка была возможна

Нам нужны продажи и доступность в одной детализации: товар, площадка и день либо час. Остаток на конец дня подходит не всегда. В 18:00 товар закончился, но большую часть дня продавался; нулевой вечерний снимок не означает сутки отсутствия. Лучше использовать интервалы доступности из событий склада и сравнивать их с часами работы магазина или доступности доставки.

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

Почему полученные три нельзя сразу умножить на месяц

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

Начните с календаря. Посчитайте показатель отдельно по будням и выходным, проверьте цены и рекламу, сравните с товарами, которые всё время были доступны. Если в данных нет ни одного доступного воскресенья, воскресный спрос из этого товара не наблюдался. В отчёте лучше оставить такую ячейку неизвестной и собрать данные, чем заменить её нулём или убедительным средним.

days = [{'available': True, 'sales': 3} for _ in range(10)]
days += [{'available': False, 'sales': 0} for _ in range(20)]
observed = [d for d in days if d['available']]
assert observed
assert all(d['sales'] == 0 for d in days if not d['available'])
sales = sum(d['sales'] for d in days)
rate = sum(d['sales'] for d in observed) / len(observed)
coverage = len(observed) / len(days)
scenario = rate * len(days)
print({'calendar_rate': sales/len(days), 'available_rate': rate,
       'coverage': round(coverage, 3), 'constant_rate_scenario': scenario})
assert rate == 3 and sales/len(days) == 1
assert scenario == 90

Разобрать записи, которые не укладываются в правило

Продажа при недоступности в примере считается противоречием. В реальной системе это может быть предзаказ, задержка обновления остатков или выдача ранее оформленного заказа. Выберите событие, которое действительно показывает спрос: оформление, оплату или отгрузку. После этого согласуйте момент доступности с этим событием. Если смешать оплату сегодня с отгрузкой вчера, исправление знаменателя не спасёт расчёт.

Частичную доступность можно выразить часами: тридцать продаж за восемьдесят часов, когда товар можно было заказать. Однако доступный ночной час и час дневного пика имеют разный смысл. Для круглосуточного магазина полезно хранить час суток и день недели, а для офлайн-магазина исключить время закрытия. Дробный знаменатель повышает точность времени, но сам по себе не устраняет календарные различия.

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

Продолжить работу с данными

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

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

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

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