Проекты / выбор ассортиментной матрицы
Проект · Python, SQL, DuckDBАссортиментная матрица для каждого сегмента аптек
Продолжение кластеризации точек: аптеки разбиты на сегменты, теперь для каждого нужен свой список товаров, которые обязаны быть на полке, - ассортиментная матрица. Цель - держать в остатках меньше денег, не теряя прибыли, и принимать решение не по вкусу категорийного менеджера, а по измеримому вкладу товара.
Данные синтетические: та же сгенерированная аптечная сеть, что и в кластеризации. Задача повторяет мой рабочий проект в аптечной сети; код переписан и запущен на синтетических данных, чтобы не раскрывать данные компании. Справочник лекарств - из открытого реестра Минздрава (ЖНВЛП), продажи и действующая матрица сети сгенерированы. Цифры не описывают реальный бизнес.
- Задача. Сейчас ассортимент задаётся по площади аптеки: у всех аптек одного размера одна и та же матрица. Нужно подобрать матрицу под сегмент так, чтобы в товарных остатках лежало меньше денег при сопоставимой прибыли.
- Что сделано. Для каждого из 13 сегментов товары оценены по вкладу в продажи, строгость отбора подобрана так, чтобы прибыль осталась на уровне действующей матрицы, а остатки были минимальными. Результат проверен на следующих 4 неделях продаж, которых расчёт не видел.
- Результат. При той же прибыли в товарных остатках сети лежит на 43,0 млн ₽ меньше - это 6% всех денег в запасах. Ни один другой способ разбить сеть на группы такого результата не даёт.
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) - его выручку на одну аптеку сегмента: то, что сегмент покупает, само определяет вес товара. Вес юнита - его доля в выручке сегмента. Чем весомее юнит, тем больше его товаров остаётся в матрице: в важной для сегмента потребности покупателю нужен выбор, в редкой хватит одного-двух ходовых товаров.
2. Строгость отбора и выбор матрицы
Строгость отбора меняется от мягкой (в матрице остаётся почти всё продаваемое) до строгой (только лидеры своего юнита). Каждый вариант сравнивается с действующей матрицей по деньгам, отдельно для каждой аптеки:
- остатки - сколько денег лежит на полке: под каждый товар матрицы держится запас по его спросу, но не меньше двух пачек на витрине;
- прибыль - продажи товаров матрицы; если товар убран, половина его покупателей берёт аналог из того же юнита.
Зачем сокращать остатки. Деньги, замороженные в товаре, который плохо продаётся, можно направить на закуп ходового товара - например, не брать кредит на очередную поставку. Кроме того, каждый лишний рубль в запасе несёт затраты и риски: хранение, обработка, логистика, списания по сроку годности. В расчёте прибыль валовая (выручка минус закупочная стоимость), эти затраты в ней не вычтены, поэтому выгоду от меньшего запаса расчёт скорее занижает.
Почему главный показатель - остатки. Остатки зависят только от состава матрицы, поэтому варианты сравниваются по ним полностью. Прибыль же оценивается по текущим продажам: видно, сколько уже существующего спроса матрица удерживает, но не видно спроса на товары, которых на полке не было, и того, сколько покупателей на самом деле перейдёт на аналог. Полный эффект на прибыль покажет только пилот (раздел 5). Поэтому задача ставится так: минимум денег в остатках при сопоставимой прибыли.
Все варианты
| Вариант | Позиций на аптеку | Δ остатки | Δ выручка | Δ прибыль |
|---|---|---|---|---|
| экспоненциальный (λ=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 сегментах матрица, наоборот, становится шире: там продаются товары, которых нет в действующей матрице.
4. Проверка на новых неделях
Матрица выбиралась по тем же неделям продаж, по которым считался вклад товаров, - такая оценка оптимистична: матрица подстраивается под случайные всплески спроса. Поэтому период разделён пополам: по первым 4 неделям строятся сегменты и матрицы, затем матрицы фиксируются, а по реальным продажам следующих 4 недель считается, что они дали бы. Матрица автосегментов из раздела 2 подбиралась так, чтобы на неделях 1-4 её прибыль совпала с действующей. На неделях 5-8 она зарабатывает на 1,6 млн ₽ (1,2%) меньше, чем действующая матрица, а денег в остатках у неё по-прежнему на 48,9 млн ₽ меньше. Если подобрать строгость так, чтобы прибыль совпала именно на новых неделях, экономия будет 43,0 млн ₽ - это и есть главный результат, он проверен на продажах, которых расчёт не видел.
Заодно сравниваются разные способы разбить сеть на группы. Процедура везде одна, меняется только то, какую матрицу получает аптека:
- одна матрица на всю сеть - нижняя планка: деление на сегменты должно давать больше;
- категории A-E - группы как сейчас в сети, по площади аптеки, но матрица каждой категории пересчитана тем же методом (это не действующая матрица);
- автосегменты - результат кластеризации;
- архетипы - скрытые типы аптек, заложенные в синтетические данные;
- случайные группы того же размера, что автосегменты, - проверка, что выигрыш даёт смысл групп, а не само деление.
Для каждого способа строится кривая «остатки → прибыль на новых неделях», и точно считаются две точки её пересечения с нулевыми осями: остатки при той же прибыли (главный разрез: сколько денег нужно на полке, чтобы удержать прибыль действующей матрицы) и прибыль при тех же остатках (второй разрез).
| Способ | Групп | Остатки при той же прибыли | Прибыль при тех же остатках |
|---|---|---|---|
| Автосегменты | 13 | -43,0 млн ₽ | +7,0 млн ₽ |
| Архетипы | 8 | -4,8 млн ₽ | +0,8 млн ₽ |
| Случайные группы | 13 | +1,2 млн ₽ | -0,2 млн ₽ |
| Категории A-E | 5 | +26,7 млн ₽ | -5,7 млн ₽ |
| Одна матрица на сеть | 1 | +63,1 млн ₽ | -15,1 млн ₽ |
Итог: автосегменты дают лучшее соотношение прибыли и запасов. При той же прибыли им нужно меньше всего денег в остатках, а при тех же остатках они приносят больше всего прибыли.
Вклад именно смысла сегментов - разница со случайными группами того же размера, около 44,2 млн ₽ остатков. Само по себе деление на мелкие группы экономии не даёт. Архетипы отстают от автосегментов: архетип объединяет маленькие и большие аптеки одного типа, а сегмент учитывает ещё и размер.
Подробнее: как это выглядит по неделям
Чтобы увидеть, откуда берётся результат, каждый способ выбирает свою матрицу только по первым 4 неделям по тому же правилу - прибыль как у действующей матрицы при минимуме остатков, - и дальше матрица не меняется. По каждой неделе считаются прибыль по реальным продажам и остатки по нормативу, пересчитанному по спросу недели.
Прибыль на неделях обучения у всех способов совпадает с действующей: так подобрана строгость. На новых неделях автосегменты недобирают около 0,4 млн ₽ прибыли в неделю (-1,2%), почти столько же, сколько случайные группы того же размера. Значит, это эффект размера группы, а не её смысла: в маленьком сегменте вклад товара оценивается по небольшим продажам, и матрица частично подстраивается под случайные всплески первых недель. Поэтому в итоговом сравнении выше строгость каждого способа подбирается так, чтобы прибыль совпала именно на новых неделях, - часть экономии уходит на этот запас прочности.
Разница в остатках от недели к неделе почти не меняется: экономия заложена в самом составе матрицы. В остатках автосегментов в среднем на 49,5 млн ₽ меньше денег, чем у действующей матрицы, у одной матрицы на сеть - на 60,0 млн ₽ больше.
5. Как проверить полный эффект: пилот
Остатки расчёт сравнивает надёжно, а прибыль - только в части уже существующего спроса. Полный эффект покажет пилот:
- Выбрать пары аптек. В каждом сегменте - группа пилотных аптек и похожая на неё контрольная: сходные размер, выручка и динамика продаж за последние месяцы.
- Ввести новую матрицу только в пилотных аптеках на 8-12 недель; контрольные работают по действующей.
- Сравнить изменения, а не уровни. Сравнивается, насколько изменились продажи, прибыль, остатки, списания и доля дней без товара в пилоте и в контроле с момента запуска. Так общий для всех рост или сезонность не выдаются за эффект матрицы.
- Масштабировать по результату. Если прибыль не просела, а остатки снизились, матрица распространяется на весь сегмент; если нет - корректируется строгость отбора.
Ограничение расчёта: в синтетических данных спрос стабилен от недели к неделе, поэтому разница между периодами - только случайные колебания. В реальной сети добавятся сезонность и тренды, и матрицы нужно пересчитывать регулярно.