Проекты / выбор ассортиментной матрицы

Проект · Python, SQL, DuckDB

Ассортиментная матрица для каждого сегмента аптек

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

Данные синтетические: та же сгенерированная аптечная сеть, что и в кластеризации. Задача повторяет мой рабочий проект в аптечной сети; код переписан и запущен на синтетических данных, чтобы не раскрывать данные компании. Справочник лекарств - из открытого реестра Минздрава (ЖНВЛП), продажи и действующая матрица сети сгенерированы. Цифры не описывают реальный бизнес.

Коротко
  • Задача. Сейчас ассортимент задаётся по площади аптеки: у всех аптек одного размера одна и та же матрица. Нужно подобрать матрицу под сегмент так, чтобы в товарных остатках лежало меньше денег при сопоставимой прибыли.
  • Что сделано. Для каждого из 13 сегментов товары оценены по вкладу в продажи, строгость отбора подобрана так, чтобы прибыль осталась на уровне действующей матрицы, а остатки были минимальными. Результат проверен на следующих 4 неделях продаж, которых расчёт не видел.
  • Результат. При той же прибыли в товарных остатках сети лежит на 43,0 млн ₽ меньше - это 6% всех денег в запасах. Ни один другой способ разбить сеть на группы такого результата не даёт.
Сколько денег в остатках нужно, чтобы удержать прибыль действующей матрицыРазница с остатками действующей матрицы, млн ₽: меньше нуля - экономия. Одна и та же процедура отбора, меняется только то, как аптеки разбиты на группы (подробнее - в разделе 4).

1. Какие товары важны сегменту

Товары объединяются в юниты - группы взаимозаменяемых товаров, которые решают одну задачу покупателя. Для лекарств это действующее вещество, форма с путём введения, дозировка и объём пачки («ибупрофен, таблетки, 200 мг, 31-50 шт.»), для остального ассортимента - вид товара («подгузники», «зубная паста»). Юнит объединяет только то, что покупатель действительно может взять взамен: капли глазные и назальные, таблетки обычные и пролонгированного действия, детская и взрослая дозировка - разные юниты. Внутри юнита товары конкурируют, а матрице важно, чтобы сам юнит был на полке.

Как товар раскладывается по уровням справочникаКатегория → подкатегория → юнит: вещество, форма, дозировка и объём пачки (сколько в нём товаров) → самый продаваемый товар.
  • Костно-мышечная системаПротивовоспалительныеИбупрофен, таблетки, 200 мг, 31-50 шт. (13 товаров)Ибупирин 200 мг №50
  • Костно-мышечная системаПротивовоспалительныеИбупрофен, сироп, суспензия, раствор внутрь, 100 мг (13 товаров)Максиколд для детей 100 мг
  • Сердечно-сосудистая системаБлокаторы кальциевых каналовАмлодипин, таблетки, 5 мг, 31-50 шт. (4 товара)Амлодипин 5 мг №40
  • Мать и дитяПодгузники и пеленкиПодгузники (14 товаров)Гелиоопти подгузники
  • БАД и витаминыВитаминно-минеральные комплексыВитаминно-минеральные комплексы, саше, 51-100 шт. (8 товаров)Ортолайт саше №90

Первые две строки - одно вещество, но разные юниты: таблетки 200 мг для взрослого и детская суспензия друг друга не заменяют. Таблетки делятся ещё по дозировке и объёму пачки: 200 и 400 мг - разные юниты, а покупатель маленькой пачки не обязательно возьмёт пачку на 100 штук. Внутри юнита конкурируют оригинальный препарат и дженерики - копии того же лекарства от разных производителей.

Каждый товар получает оценку вклада (Score) - его выручку на одну аптеку сегмента: то, что сегмент покупает, само определяет вес товара. Вес юнита - его доля в выручке сегмента. Чем весомее юнит, тем больше его товаров остаётся в матрице: в важной для сегмента потребности покупателю нужен выбор, в редкой хватит одного-двух ходовых товаров.

Как распределён вклад юнитов, сегмент «Большие · универсальный · медиум +»Юниты по убыванию вклада: половину выручки сегмента дают 5% юнитов.

2. Строгость отбора и выбор матрицы

Строгость отбора меняется от мягкой (в матрице остаётся почти всё продаваемое) до строгой (только лидеры своего юнита). Каждый вариант сравнивается с действующей матрицей по деньгам, отдельно для каждой аптеки:

Зачем сокращать остатки. Деньги, замороженные в товаре, который плохо продаётся, можно направить на закуп ходового товара - например, не брать кредит на очередную поставку. Кроме того, каждый лишний рубль в запасе несёт затраты и риски: хранение, обработка, логистика, списания по сроку годности. В расчёте прибыль валовая (выручка минус закупочная стоимость), эти затраты в ней не вычтены, поэтому выгоду от меньшего запаса расчёт скорее занижает.

Почему главный показатель - остатки. Остатки зависят только от состава матрицы, поэтому варианты сравниваются по ним полностью. Прибыль же оценивается по текущим продажам: видно, сколько уже существующего спроса матрица удерживает, но не видно спроса на товары, которых на полке не было, и того, сколько покупателей на самом деле перейдёт на аналог. Полный эффект на прибыль покажет только пилот (раздел 5). Поэтому задача ставится так: минимум денег в остатках при сопоставимой прибыли.

Варианты матрицы: изменение остатков и прибыли относительно действующейМатрицы автосегментов при разной строгости отбора. Точка (0; 0) - действующая матрица. По осям - на сколько вариант отличается от неё: по остаткам и по прибыли за 4 недели. Линия - шкала строгости: слева строгие варианты с меньшими остатками, справа мягкие. Выбран вариант, где линия пересекает горизонтальную ось, то есть прибыль такая же, как у действующей матрицы.
Все варианты
ВариантПозиций на аптекуΔ остаткиΔ выручкаΔ прибыль
экспоненциальный (λ=0.01)2 613+223,8 млн ₽+86,0 млн ₽+21,2 млн ₽
экспоненциальный (λ=0.018)2 547+208,9 млн ₽+84,7 млн ₽+20,9 млн ₽
экспоненциальный (λ=0.032)2 453+181,1 млн ₽+81,7 млн ₽+20,1 млн ₽
экспоненциальный (λ=0.058)2 330+142,3 млн ₽+75,7 млн ₽+18,6 млн ₽
экспоненциальный (λ=0.11)2 164+87,7 млн ₽+62,9 млн ₽+15,3 млн ₽
экспоненциальный (λ=0.19)2 011+33,9 млн ₽+47,4 млн ₽+11,6 млн ₽
экспоненциальный (λ=0.34)1 862-17,1 млн ₽+27,4 млн ₽+6,5 млн ₽
экспоненциальный (λ=0.62)1 720-67,6 млн ₽-13,9 млн ₽-4,0 млн ₽
экспоненциальный (λ=1.1)1 603-113,7 млн ₽-73,1 млн ₽-19,1 млн ₽
экспоненциальный (λ=2)1 520-146,7 млн ₽-116,9 млн ₽-30,3 млн ₽
экспоненциальный (λ=0.498)1 769-48,9 млн ₽+1,8 млн ₽-0,0 млн ₽

Чем строже отбор, тем меньше денег в остатках, но после определённого порога вместе с залежавшимся товаром уходит и продаваемый: самый строгий вариант освобождает 146,7 млн ₽, но теряет 30,3 млн ₽ прибыли. Правило выбора: самый строгий вариант, который ещё удерживает прибыль действующей матрицы, - точка, где линия пересекает горизонтальную ось.

Подробнее: как задаётся строгость и считается запас

Строгость. Товар остаётся в матрице, если его доля в оценке своего юнита выше порога. Порог плавно зависит от веса юнита в сегменте: у весомых юнитов он ниже, и в них остаётся больше товаров. Общую строгость задаёт параметр λ: кривая строится по 10 его значениям, а нулевые точки находятся точно - делением отрезка пополам. Товары минимального обязательного ассортимента и собственной торговой марки входят в матрицу всегда. В выбранной точке λ = 0,50: 1 769 позиций на аптеку вместо 1 918 и на 48,9 млн ₽ меньше денег в остатках (-7,4%) на неделях, по которым матрица выбиралась.

Норматив запаса. Средний запас товара в аптеке = страховой запас + половина недельной поставки, но не меньше выкладки в 2 пачки. Страховой запас рассчитан на уровень сервиса 95% при сроке поставки 2 дня и заказе раз в 7 дней. Так редкий товар замораживает минимум выкладки в каждой аптеке, а ходовой - запас под свой спрос.

3. Матрица по сегментам

Сейчас ширина матрицы зависит только от площади аптеки (категория A-E), новая - от того, что покупают в сегменте. Поэтому сокращение неравномерное: сильнее всего сокращается матрица сегмента «Малые · сердце и кровь · эконом»: 1 656 → 1 245 позиций (-24,8%), а в сегменте «Большие · универсальный · медиум +» почти не меняется (-1,7%). В 2 сегментах матрица, наоборот, становится шире: там продаются товары, которых нет в действующей матрице.

Сколько позиций в матрице: сейчас и по новому расчётуПозиций в матрице одной аптеки. «Сейчас» - среднее по аптекам сегмента: в один сегмент попадают аптеки разных категорий A-E, у каждой своя действующая матрица. «Новая» - матрица автосегмента из кластеризации, одна на все его аптеки. В скобках - число аптек.

4. Проверка на новых неделях

Матрица выбиралась по тем же неделям продаж, по которым считался вклад товаров, - такая оценка оптимистична: матрица подстраивается под случайные всплески спроса. Поэтому период разделён пополам: по первым 4 неделям строятся сегменты и матрицы, затем матрицы фиксируются, а по реальным продажам следующих 4 недель считается, что они дали бы. Матрица автосегментов из раздела 2 подбиралась так, чтобы на неделях 1-4 её прибыль совпала с действующей. На неделях 5-8 она зарабатывает на 1,6 млн ₽ (1,2%) меньше, чем действующая матрица, а денег в остатках у неё по-прежнему на 48,9 млн ₽ меньше. Если подобрать строгость так, чтобы прибыль совпала именно на новых неделях, экономия будет 43,0 млн ₽ - это и есть главный результат, он проверен на продажах, которых расчёт не видел.

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

Для каждого способа строится кривая «остатки → прибыль на новых неделях», и точно считаются две точки её пересечения с нулевыми осями: остатки при той же прибыли (главный разрез: сколько денег нужно на полке, чтобы удержать прибыль действующей матрицы) и прибыль при тех же остатках (второй разрез).

Прибыль на новых неделях при разном объёме остатковТочки на линиях - варианты строгости. Крестик - остатки при той же прибыли (пересечение с горизонтальной осью), ромб - прибыль при тех же остатках (пересечение с вертикальной).
СпособГруппОстатки при той же прибылиПрибыль при тех же остатках
Автосегменты13-43,0 млн ₽+7,0 млн ₽
Архетипы8-4,8 млн ₽+0,8 млн ₽
Случайные группы13+1,2 млн ₽-0,2 млн ₽
Категории A-E5+26,7 млн ₽-5,7 млн ₽
Одна матрица на сеть1+63,1 млн ₽-15,1 млн ₽

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

Вклад именно смысла сегментов - разница со случайными группами того же размера, около 44,2 млн ₽ остатков. Само по себе деление на мелкие группы экономии не даёт. Архетипы отстают от автосегментов: архетип объединяет маленькие и большие аптеки одного типа, а сегмент учитывает ещё и размер.

Подробнее: как это выглядит по неделям

Чтобы увидеть, откуда берётся результат, каждый способ выбирает свою матрицу только по первым 4 неделям по тому же правилу - прибыль как у действующей матрицы при минимуме остатков, - и дальше матрица не меняется. По каждой неделе считаются прибыль по реальным продажам и остатки по нормативу, пересчитанному по спросу недели.

Прибыль по неделям относительно действующей матрицыРазница с прибылью действующей матрицы за неделю, млн ₽. Слева от вертикальной линии - недели, по которым выбиралась матрица, справа - новые.

Прибыль на неделях обучения у всех способов совпадает с действующей: так подобрана строгость. На новых неделях автосегменты недобирают около 0,4 млн ₽ прибыли в неделю (-1,2%), почти столько же, сколько случайные группы того же размера. Значит, это эффект размера группы, а не её смысла: в маленьком сегменте вклад товара оценивается по небольшим продажам, и матрица частично подстраивается под случайные всплески первых недель. Поэтому в итоговом сравнении выше строгость каждого способа подбирается так, чтобы прибыль совпала именно на новых неделях, - часть экономии уходит на этот запас прочности.

Остатки по неделям относительно действующей матрицыРазница со стоимостью остатков действующей матрицы, млн ₽: запас по нормативу, пересчитанному по спросу недели.

Разница в остатках от недели к неделе почти не меняется: экономия заложена в самом составе матрицы. В остатках автосегментов в среднем на 49,5 млн ₽ меньше денег, чем у действующей матрицы, у одной матрицы на сеть - на 60,0 млн ₽ больше.

5. Как проверить полный эффект: пилот

Остатки расчёт сравнивает надёжно, а прибыль - только в части уже существующего спроса. Полный эффект покажет пилот:

  1. Выбрать пары аптек. В каждом сегменте - группа пилотных аптек и похожая на неё контрольная: сходные размер, выручка и динамика продаж за последние месяцы.
  2. Ввести новую матрицу только в пилотных аптеках на 8-12 недель; контрольные работают по действующей.
  3. Сравнить изменения, а не уровни. Сравнивается, насколько изменились продажи, прибыль, остатки, списания и доля дней без товара в пилоте и в контроле с момента запуска. Так общий для всех рост или сезонность не выдаются за эффект матрицы.
  4. Масштабировать по результату. Если прибыль не просела, а остатки снизились, матрица распространяется на весь сегмент; если нет - корректируется строгость отбора.

Ограничение расчёта: в синтетических данных спрос стабилен от недели к неделе, поэтому разница между периодами - только случайные колебания. В реальной сети добавятся сезонность и тренды, и матрицы нужно пересчитывать регулярно.

Ноутбук на GitHubНазад: кластеризация точек