全部版块 我的主页
论坛 新商科论坛 四区(原工商管理论坛) 商学院 运营管理(物流与供应链管理)
78 0
2025-12-03

一、业务场景与目标说明

1.1 核心问题描述

在零售仓储与配送的实际操作中,同一SKU(库存单位)会因时间、仓库的不同而呈现出多种运营状态。这些状态包括但不限于以下几种典型情况:
  • 刚上新+强铺货:新品集中投放至大量门店,导致短期内出库门店数量和总出库量急剧上升;
  • 短暂下架:商品虽有库存,但因系统设置、运营策略调整或临时管控等原因被暂停销售,短期内无出库记录;
  • 长期下架:该商品已退出正常运营序列,长时间未发生出库行为,库存归零或维持极低水平且无流动迹象;
  • 缺货:当前库存为零或极低,但历史数据显示其具备稳定需求,表明供应未能匹配实际销售需要。

核心目标是:基于完整的过往数据,实现对每一个日期、每个仓库、每种商品所处运营状态的自动化识别,生成可用于补货决策、新品评估及陈列优化的状态标签体系。

二、数据结构与分析粒度设计

2.1 基础数据层级(事实表构建)

建议采用以“日”为单位的出入库与库存明细作为底层事实数据源。每条记录应至少包含如下字段信息:
date
日期(自然日)
warehouse_id
仓库 ID
sku_id
商品 ID
cate_1 / cate_2 / cate_3
一级/二级/三级品类分类(便于后续按品类动态设定判断阈值)
inventory_qty
当日期末库存数量(或日均库存量)
outbound_qty
当日总出库量(所有门店出库之和)
outbound_store_cnt
当日产生出库行为的门店数(去重统计) (可选字段)
inbound_qty
当日入库总量 若缺少直接的入库数据
inbound_qty
,可通过库存变动与出库数据间接推算。

2.2 分析单元定义(打标最小粒度)

分析的基本单元为:仓库 × SKU × 日期 的组合。所有状态判定逻辑均以此三元组为唯一标识键
(warehouse_id, sku_id, date)
。 多级品类信息(cate_1/2/3)不改变分析粒度,主要用于差异化配置规则参数——不同品类的商品生命周期、周转频率存在差异,需据此调整判断标准。

三、关键指标与特征工程

在进行状态标注前,需预先计算一系列滑动窗口指标和统计特征,用于检测异常模式或显著变化。

3.1 库存变动与入库量反推

当原始数据中缺乏明确的入库字段
inbound_qty
时,可通过库存差额与出库数据估算“隐式入库量”:
inbound_qty(t) = max( inventory_qty(t) - inventory_qty(t-1) + outbound_qty(t), 0 )
公式解释: 库存变化 = 昨日库存 + 入库 - 出库 整理可得:入库 = 当日库存 - 昨日库存 + 当日出库 为避免噪声干扰造成负值,所有计算结果中小于0的“入库量”统一截断为0。 此步骤有助于捕捉新品铺货阶段出现的大规模集中入库现象。

3.2 滑动窗口特征构建

针对每个
(warehouse_id, sku_id)
序列,按时间顺序计算以下滚动指标: 短期动销表现
roll_7d_outbound_qty
最近7日累计出库量
roll_7d_outbound_store_cnt
最近7日内有出库行为的门店总数(每日去重后累加) 中长期销售趋势
roll_30d_outbound_qty
最近30日累计出库量
roll_30d_outbound_store_cnt
最近30日内有出库门店数之和 库存与补货相关指标
roll_7d_inbound_qty
近7日累计入库量
roll_30d_inbound_qty
近30日累计入库量

3.3 历史统计特征提取

基于较长周期的历史数据(如全部历史记录,或最近90~180天),为每个仓-SKU组合计算以下统计量:
hist_outbound_mean
历史平均日出库量(可选择性排除出库为0的日期)
hist_outbound_std
日出库量的标准差
hist_outbound_median
日出库量的中位数
hist_outbound_MAD
基于中位数的绝对偏差(MAD)
hist_store_cnt_median
历史出库门店数的中位数
hist_store_cnt_MAD
门店数的MAD 这些统计值将作为自动设定“强铺货”判定阈值以及“常规销售”基准的重要依据。

四、四类运营状态的定义与判定逻辑

4.1 上新强铺货(New & Strong Push)

业务含义: 某SKU在特定仓库首次进入销售阶段,正处于大规模铺货期,短时间内向众多门店发货,出库量与覆盖门店数远高于其后期常态水平。

4.1.1 新品起始点识别

对于每个
(warehouse_id, sku_id)
序列,
首销日期 first_sell_date = 最早 outbound_qty > 0 的 date
上新期长度 T_new = 按品类设定,常见 7–14 天(生鲜可以短一点)
[first_sell_date, first_sell_date + T_new - 1]
这一时间段内,视为潜在的“上新观察期”。

4.1.2 强铺货行为识别条件

若在上述上新期内满足以下任一“显著放大”特征,则可标记为“上新强铺货”: - 门店覆盖显著增加
outbound_store_cnt(t) > hist_store_cnt_median + K1 * hist_store_cnt_MAD
其中K1取值范围为2~3,可根据具体品类灵活调整。 - 出库总量明显偏高
outbound_qty(t) > hist_outbound_median + K2 * hist_outbound_MAD
也可使用分位数方式进行判断:
outbound_qty(t) > hist_outbound_Q90 (历史 90% 分位)
- 入库量异常增长(如有数据或通过推算获得)
inbound_qty(t) > hist_inbound_median + K3 * hist_inbound_MAD
综合判定规则示例:
若 t 在 [first_sell_date, first_sell_date + T_new - 1] 内,
且 (门店数显著高 OR 出库量显著高 OR 入库量显著高),
则状态 = "上新强铺货"。
可进一步细化为: 仅在上新初期的前3–5天出现集中放量,之后趋于平稳,则仅将最初几天标记为“上新强铺货”,后续转为“正常上架”状态。

4.2 短暂下架(Short-term Off-shelf)

业务理解: 商品仍在运营生命周期内,但由于系统设置、运营调度或合规审查等临时原因,暂时停止出库。通常表现为仓内仍有库存,且下架前后均有正常销售活动。

4.2.1 关键识别特征

存在一段持续时间较短的连续日期区间,满足:
outbound_qty = 0
——即连续多日无出库; 同时
inventory_qty > 0
——表示库存尚存但未释放; 并且该区间的前后均存在一定时期的出库行为,说明仅为阶段性中断。

4.2.2 数学化判定规则

设定“短暂下架”的时间窗口范围: - 最小持续天数
K_min
,例如2~3天; - 最大允许天数
K_max
,例如不超过10天(超过则更倾向归类为“长期下架”)。 对每个
(warehouse_id, sku_id)
序列, 查找所有满足以下条件的日区间
[t_start, t_end]
对于 t ∈ [t_start, t_end]:
    outbound_qty(t) = 0
    AND inventory_qty(t) > 0
区间长度 L = t_end - t_start + 1
K_min ≤ L ≤ K_max
在区间前后存在出库的情形下,需对相关日期进行识别与标记处理。
在 [t_start - P, t_start - 1] 这 P 天中,存在 t',使 outbound_qty(t') > 0
并且 在 [t_end + 1, t_end + Q] 这 Q 天中,存在 t'',使 outbound_qty(t'') > 0
对于参数 P 和 Q 的取值,可设定为 7 天,或根据商品品类灵活配置。 针对满足条件的每一个日期 t ∈ [t_start, t_end],执行如下打标操作:
状态 = "短暂下架"

4.3 长期下架(Long-term Off-shelf)

业务理解:

该 SKU 已基本从当前仓库的货架体系或运营流程中撤出,表现为长时间无法购买、不再补货。典型特征包括:

  • 持续较长时间无库存;
  • 库存为 0 或极低,且后续无入库记录;
  • 此前一段时间曾有较为明显的销售表现。
outbound_qty = 0
4.3.1 阈值按品类差异化设置

由于不同品类的商品生命周期差异显著,建议依据品类分别配置“长期下架”的判定天数阈值。

M

示例:

一级品类 短暂下架上限 K_max 长期下架阈值 M
生鲜 3–5 天 7–14 天
食品杂货 7–10 天 30 天
日化百货 10–14 天 30–60 天
4.3.2 形式化判断规则

对每个

(warehouse_id, sku_id)

,寻找满足以下条件的时间点:

存在连续 M 天区间 [t_start, t_end],对所有 t ∈ [t_start, t_end]:
    outbound_qty(t) = 0
并且 (以下任一成立)

1)库存长期为 0 型:
    inventory_qty(t) = 0  对所有 t ∈ [t_start, t_end]

2)库存极低且无入库型:
    inventory_qty(t) ≤ I_low (小阈值,如 1 或 2)
    且 inbound_qty(t) ≈ 0 (可以用 roll_30d_inbound_qty 很小来判断)

3)长期无流动型:
    inbound_qty(t) ≈ 0 且库存几乎不变化(|inventory_qty(t) - inventory_qty(t-1)| ≤ δ)

同时确保在

[t_start - H, t_start - 1]

这一时间段内,商品曾有过稳定销量:

roll_30d_outbound_qty(t_start - 1) > V_min

若不满足上述销量条件,则可能属于从未真正上架推广的滞销品,不应标记为“下架”,而应归类为“未推广”状态。

对符合条件的每个日期 t ∈ [t_start, t_end],进行如下标记:

状态 = "长期下架"

4.4 缺货(Out-of-stock)

业务理解:

该 SKU 在市场上具备需求基础(历史数据显示为动销商品),但当前仓库库存为 0 或远低于合理水平,且无出库行为,表明供应能力未能匹配市场需求。

缺货通常被视为最高优先级的运营问题。

4.4.1 缺货识别的关键要素
  • 当前库存为 0 或接近于 0:
inventory_qty(t) <= 安全库存阈值 I_safe(通常 0 或很小)
  • 当前无出库或出库量显著低于历史均值:
outbound_qty(t) = 0

outbound_qty(t) << hist_outbound_mean (比如 < 0.2 * hist_outbound_mean)
  • 近期存在动销或消费者需求:
    为避免将原本就无销量的“死货”误判为缺货,需验证其近期是否具有动销表现。
  • 滑动窗口内的销量数据:
roll_30d_outbound_qty(t-1) > V_min
  • 滑动窗口内发生过出库的门店数量:
roll_30d_outbound_store_cnt(t-1) > S_min
  • 可选补充:门店层面的未满足订单或缺货报表
    若拥有门店订单信息,可进一步叠加分析:
store_order_qty(t) > 0 但 outbound_qty(t) = 0
4.4.2 形式化规则定义

(warehouse_id, sku_id, date=t)

,当满足:

if inventory_qty(t) <= I_safe
   AND ( outbound_qty(t) = 0
         OR outbound_qty(t) < α * hist_outbound_mean )
   AND ( roll_30d_outbound_qty(t-1) > V_min
         OR roll_30d_outbound_store_cnt(t-1) > S_min ):
    状态 = "缺货"

其中:

  • I_safe
    可设为 0,也可根据品类设定相应的安全库存基准;
  • α
    建议取值范围为 0.1~0.3;
  • V_min
    S_min
    可通过全局统计或按品类确定。
    示例:将“动销 SKU”定义为过去 90 天内至少产生 10 笔订单,并覆盖不少于 3 家门店。

五、状态优先级与冲突消解机制

同一 SKU 在同一天可能符合多个状态判定规则(例如:库存为 0、长期无销量,同时刚过新品推广期)。因此,必须建立统一的状态优先级体系,以确保每日仅输出一个最终标签。

推荐优先级顺序(由高到低):

  1. 缺货 —— 直接影响销售转化与用户体验
  2. 上新强铺货 —— 新品运营关键阶段
  3. 短暂下架
  4. 长期下架
  5. 正常

实现逻辑上,可采用逐层覆盖方式:

for 每个 warehouse_id, sku_id, date=t:

    if 满足缺货条件:
        label(t) = "缺货"
    else if 满足上新强铺货条件:
        label(t) = "上新强铺货"
    else if 满足短暂下架条件:
        label(t) = "短暂下架"
    else if 满足长期下架条件:
        label(t) = "长期下架"
    else:
        label(t) = "正常"

注意:
“长期下架”与“短暂下架”本质上是区间型属性,可先整体识别连续区间,再回填至每日记录。但在最终每日状态判定时,仍需按照上述优先级进行覆盖处理。

六、多仓与多级品类的参数管理体系

6.1 多仓库场景(Multiple Warehouses)

无需更改核心规则逻辑,只需保证所有计算均在

(warehouse_id, sku_id)

分组基础上独立运行即可。

  • 滑动窗口统计、历史指标计算等,均以“仓 + SKU”为最小单位;
  • 如此可使同一 SKU 在不同仓库中呈现不同的生命周期状态。

伪代码示意:

按 (warehouse_id, sku_id) 分组:
    按 date 排序
    计算 rolling 指标 + 历史统计指标
    计算首销日期 first_sell_date
    扫描日期序列进行状态判断打标
6.2 多级品类结构(cate_1 / cate_2 / cate_3)

多级品类主要用于差异化配置各类阈值参数,例如:

  • 新品期长度
    T_new
  • 短暂下架最短/最长天数
    K_min, K_max
  • 长期下架判定天数
    M
  • 缺货安全库存
    I_safe
  • 动销判断标准
    V_min, S_min
  • 强铺货倍率阈值
    K1, K2, K3

建议构建一张“品类参数配置表”,示例如下:

cate_1 cate_2 cate_3 T_new K_min K_max M I_safe V_min S_min α(缺货倍率)
生鲜 水果 进口水果 5 2 5 10 5 3 0.2
生鲜 肉禽蛋 冷鲜肉 3 2 5 7 5 3 0.2
食品 饮料 碳酸饮料 10 3 10 30 2 10 5 0.3
日化 清洁 洗衣液 14 5 14 60 2 8 4 0.3

实际计算过程中,依据 SKU 所属的 cate_1/cate_2/cate_3 层级匹配对应参数。

七、端到端整体实施流程

提供一套可直接转化为 SQL 或 Python 代码的完整执行框架(按步骤说明)。

步骤 0:准备基础日粒度数据表

从原始业务系统中提取或汇总生成“日级库存+出库”明细表:

fact_daily_sku_warehouse
(
  date,
  warehouse_id,
  sku_id,
  cate_1, cate_2, cate_3,
  inventory_qty,
  outbound_qty,
  outbound_store_cnt
)

若有入库数据,可通过 join 补充

inbound_qty

;若无,则可根据库存变动趋势反向推算入库情况。

步骤 1:按“仓+SKU”计算时间序列特征

(warehouse_id, sku_id)

进行分组,并按

date

排序,依次计算以下字段:

  • prev_inventory_qty
    —— 上一日库存
  • inbound_qty
    —— 根据指定公式推导得出
  • roll_7d_outbound_qty
    /
    roll_30d_outbound_qty
  • roll_7d_outbound_store_cnt
    /
    roll_30d_outbound_store_cnt
  • roll_7d_inbound_qty
    /
    roll_30d_inbound_qty

同时计算必要的历史统计量:

hist_*

(可预先生成一张按 sku+仓 聚合的基础统计结果表)

步骤 2:识别新品期及上新强铺货状态

对每个

(warehouse_id, sku_id)

  • 确定其首次销售日期:
first_sell_date

步骤 3:识别下架区间

查找连续出现的

outbound_qty = 0

区间;对每一个这样的区间,依据其长度 L 判断属于“短暂下架候选”还是“长期下架候选”。

短暂下架候选:
- 区间内库存需大于 0;
- 区间前 P 天与后 Q 天均存在出库记录;
若满足上述条件,则将该区间内的每一天 t 标记为

label_candidate(t, "短暂下架") = 1

长期下架候选:
- 区间长度 L ≥ M(取自品类参数表);
- 区间内库存为 0 或处于极低水平,且无任何入库行为;
- 在区间开始之前存在历史销售行为;
若满足以上条件,则将该区间内所有时间点 t 标记为

label_candidate(t, "长期下架") = 1

实现方式上,可利用窗口函数对“连续零销量”段进行分组处理。例如采用“连续区间 ID”的技术方案——通过累计求和的方式划分不同的连续区间。

步骤 4:每日缺货判断

针对每个

(warehouse_id, sku_id, date=t)

执行以下操作:

  • 从品类参数表中提取相关阈值参数:
  • I_safe
    α
    V_min
    S_min
  • 结合前述缺货判定公式,判断当日是否处于“缺货”状态;
  • 如判定为缺货,则标记为
  • label_candidate(t, "缺货") = 1

步骤 2:确定最早铺货日期

通过查询品类参数表获取基础配置信息,并计算首个 outbound_qty > 0 的 date,即为该商品最早的实际发货日期。

T_new

[first_sell_date, first_sell_date + T_new - 1]

范围内,逐日判断是否达到“强铺货”标准(即是否超过设定阈值):

若满足条件,则标记为

label_candidate(t, "上新强铺货") = 1

步骤 5:基于优先级整合最终状态

对于每一个

(warehouse_id, sku_id, date=t)

综合已有候选标签并按照预设优先级规则进行决策输出:

if label_candidate(t, "缺货") == 1:
    label_final(t) = "缺货"
elif label_candidate(t, "上新强铺货") == 1:
    label_final(t) = "上新强铺货"
elif label_candidate(t, "短暂下架") == 1:
    label_final(t) = "短暂下架"
elif label_candidate(t, "长期下架") == 1:
    label_final(t) = "长期下架"
else:
    label_final(t) = "正常"

最终生成一张完整的每日状态标识表,结果示意如下:

sku_warehouse_daily_status
(
  date,
  warehouse_id,
  sku_id,
  cate_1, cate_2, cate_3,
  status  -- {上新强铺货, 短暂下架, 长期下架, 缺货, 正常}
)

八、异常数据与边界情况处理

8.1 从未销售过的 SKU
若某个

(仓, SKU)

在其整个历史周期中

outbound_qty 始终为 0

  • 若其库存始终为 0:可定义为“从未上架”,通常直接赋予“未上架/无效 SKU”标签,不参与后续四类状态划分;
  • 若曾有库存但一直未产生销售:可视为“无动销”,可归入“正常”状态,或单独划分为“僵尸 SKU”类别。

建议在主流程启动前先行识别此类 SKU,避免被误判为“长期下架”或“短暂下架”情形。

8.2 清仓尾货场景识别
在某些长期下架发生前,可能出现短期内销量骤增随后迅速归零且不再补货的现象,属于典型的清仓行为。

若需单独区分,可引入附加规则(可选):

  • 在某一特定日期附近,
  • outbound_qty(t)
    短时间内显著高于其历史平均水平;
  • 此后立即进入长时间
  • inventory_qty=0
    outbound_qty=0

满足上述模式的区间,可在后续标记为“清仓后下架”。尽管本质上仍属长期下架范畴,但可通过扩展标签增强业务解释性。

8.3 数据缺失与异常峰值处理

  • 针对明显的异常极值(过高或过低),建议使用
  • MAD
    或基于分位数的方法进行 winsorize(截断处理);
  • 对于缺失的库存数据,可根据相邻日期的库存变化及出入库流水进行合理推算填补;
  • 若无法可靠估算,则对应日期可暂不赋状态标签,或统一标记为
  • 未知

九、扩展方向:从规则系统到模型化(可选思路)

当前框架基于

纯规则+统计阈值

构建,具备以下优势:

  • 逻辑透明,易于解释;
  • 参数灵活可调,便于与业务方共同评审优化。

当数据量庞大、特征维度丰富时,可进一步演进为机器学习方案:

  • 首先利用上述规则在历史数据上自动生成弱监督标签;
  • 以此标签作为目标变量,训练分类模型(如 XGBoost、LightGBM 等);
  • 模型输入特征可包括:实时库存、入库量、出库量、覆盖门店数、所属品类、价格区间、是否促销等;
  • 模型能够捕捉更复杂的非线性关系,在规则模糊边界处表现更具鲁棒性。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群