这是“天枢系统”系列博客的第二篇。第一篇《我做了一套预测系统,但它还没上线——聊聊数据工作的第一性原理》讨论了系统设计的底层哲学;本篇聚焦数据层,聊一聊数据清洗的本质、方法和实践。

0. 数据清洗的本质:理解业务

很多人把数据清洗看作技术活——写几行 SQL,用统计方法识别异常值,然后删除或替换。

但在日常实践中,我发现数据清洗的本质不是技术,而是理解业务

为什么?

因为“异常”的含义是与实际业务产生偏差,它是一个业务概念,不是数学概念。一个统计上的离群点,可能是促销活动带来的真实需求;一个看似正常的数据,可能是缺货导致的虚假低销量。只有理解业务,才能区分这两者。

所以,清洗数据的过程,其实就是在理解业务的基础上进行数据分析的过程。它的目的不是得到一个看似完美(譬如符合正态分布)的数据集,而是去伪存真、还原可重复的需求历史——即客户在不受供应限制的情况下,真正想买什么、想买多少。

1. 从源头开始:为什么从销售订单取数?

天枢系统从金蝶 ERP 取数时,选择了销售订单,而不是销售出库单

数据源反映什么问题
销售出库单实际发货量缺货导致未发出的部分被漏掉
销售订单客户真实需求包含了因缺货被取消或延迟的需求

这个选择背后是一个核心认知:预测模型应该学习“客户想要什么”,而不是“仓库发了什么”

如果从出库单取数,缺货导致的需求会被掩盖,预测值会越来越低,安全库存越设越少,最终形成“预测低 → 库存少 → 缺货 → 需求数据更低 → 预测更低”的恶性循环。

因此,数据清洗的第一步,不是处理异常值,而是选对数据源。从源头(客户订单)开始确保数据质量,是所有数据工作的基础。这也要求我们在创建销售订单时,要忠实记录客户的需求日期,留下第一手,也是唯一的需求资料。

2. 识别异常值:三种方法的适用场景

天枢系统内置了三种异常检测方法,每种方法各有适用的场景和局限:

IQR(四分位距)法

原理:将数据按大小分成四等份,超出 Q1 - 1.5×IQRQ3 + 1.5×IQR 范围的值标记为异常。

适用:识别统计意义上的极端值,比如某天销量突然是平时的 10 倍。

局限:对间歇性需求(大量零值、偶尔有销量)效果差,因为零值会把四分位点拉得很低,导致正常的小额销量也被标记为异常。

环比突变法

原理:对比相邻两天的销量变化。当日销量超过昨日 3 倍,或不足昨日的 1/3,标记为异常。

适用:捕捉短期内的剧烈波动,比如促销活动、系统录入错误。

局限:无法识别长期趋势变化(比如产品进入旺季,销量逐日攀升)。

Z-Score 法

原理:计算每个数据点偏离均值的标准差倍数,超过 3 个标准差标记为异常。

适用:数据近似正态分布的场景。

局限:对长尾分布(大多数值集中在小范围,少数值极大)效果差。

选择原则:三种方法并行使用,互补短板。系统自动标记,但最终剔除或保留的决定权交给人工审核——由计划员决定剔除还是保留。人工处理时,要抓大放小,即聚焦大值的清洗,比如极端值。

注意:这三种方法扫描的是订单量,不是出库量。出库量只是辅助清洗的“尺子”,不是预测目标。供应异常的识别走的是另一条独立的业务规则(见第3节),与这里的统计异常检测互不干扰。

3. 一个容易被忽视的细节:区分“需求异常”和“供应异常”

补充说明:第1节提到“选择了销售订单而不是出库单”,而这一节将会说“同时取了订单量和出库量”——两者的角色不同:订单量是我们要预测的目标,即模型要学习的真实需求;出库量是用来清洗这个目标的辅助信息

取了出库量,不是为了把它作为训练数据,而是作为一把“尺子”,用来发现订单量与出库量之间的“不匹配”——而这种不匹配,恰恰是异常信号的来源。

订单量与出库量的差距有两种不同的成因,需要两种不同的处理方式:

第一种,订单量异常大,出库量正常(如订单1200、出库120)。这种场景的成因无法由系统自动判断——它可能是录入错误(多打了一个0,仓库纠正了),也可能是真实的团购大单(客户确实买了1200件,但仓库分批发货只发了120件)。这两种情况在数据上长得一模一样,必须由人工结合业务经验来区分。

第二种,订单量正常,出库量异常小(如订单20、出库5)。这种场景的成因是确定的——订单本身没问题,客户确实要了20件,但仓库断货了。系统可以通过一个确定性的规则自动识别:订单量没有超过历史95%分位数(说明不是录入错误),而出库量又不到订单量的一半(说明发生了缺货)。因为成因确定、处理方式固定(保留订单量),所以可以安全地自动处理,不需要人工干预。

总结来说:人工判断负责第一种场景(订单量异常大,是录入错误还是真实大单?);系统自动处理负责第二种场景(订单量正常但出库量异常小,判定为缺货)。

3.1 天枢系统在取数时,同时取了订单量和出库量。这让我们能做一件重要的事:区分需求异常和供应异常

场景订单量出库量系统看到什么人工判断什么异常分类最终处理
真实促销850850数值偏高,订单与出库匹配确认当天有促销活动需求异常替代(促销是一次性事件,不能作为常规预测依据)
录入错误(仓库纠正)1200120订单量远大于出库量确认订单录入多了一个0需求异常保留出库量(120是真实发货)
历史缺货205订单量远大于出库量确认当天仓库断货供应异常保留订单量(20是真实需求)
正常销售100100数值正常无需处理正常保留
补充说明:如果录入错误且仓库未纠正、真的发了1200件货,那它在数据上无法和“真实促销”区分,只能靠人工根据业务经验来判断。这就是为什么数据清洗最终的决定权在人,而不是算法

需求异常是指数据在数值上偏离了常规范围,需要通过人工判断来确定其业务性质。根据判断结果,分为两种子情况:

子类型典型场景数据是否反映真实需求处理方式
真实需求,但数值极端促销囤货、团购大单✅ 反映替代为合理值(促销是一次性事件,不能作为常规预测依据)
虚假数据,不反映真实需求录入错误、退货冲销、系统bug❌ 不反映替代为合理值

供应异常(缺货记录)不是需求异常,而是真实需求被供应能力限制了。如果把它当作异常剔除或平滑掉,模型就永远不会知道这天有 20 个真实需求,只会记住发了 5 个货。长此以往,预测偏低,库存不足,继续缺货,形成恶性循环。

3.2 区分之后,怎么处理?

区分只是第一步,更关键的是不同场景的处理路径。上表中四种场景,核心逻辑是先判断“谁出了错”,再决定“真实需求是什么”

场景一:真实促销(订单850,出库850)

步骤订单量出库量说明
原始数据850850促销活动,订单与出库匹配
谁异常?异常(数值极端)正常850件远超日常销量,但确实是真实交易
真实需求= 850(但不重复)客户确实买了850件,但这属于一次性管理行为
模型学什么学替代值促销是一次性事件,不能作为常规预测依据

促销产生的销量是真实的,客户确实买了850件。但促销是一次性的管理行为,不是市场需求本身的规律。如果把这850件直接喂给模型,模型会错误地认为“这个产品未来每天都可能卖850件”,导致常规预测偏高、库存积压。

因此,促销数据应该被标记、从常规训练数据中替代——用前后7天中位数或整体均值还原这个位置。但促销数据本身并非无用,它会被保留在单独的促销数据表中,供未来促销计划的预测使用。

处理方式:CleanedQty = 替代值,标记为 需求异常-促销替代。原始数据(850)保留在促销数据表中。

场景二:录入错误,仓库纠正(订单1200,出库120)

步骤订单量出库量说明
原始数据1200120订单录错了(多打一个0),仓库纠正了
谁异常?异常正常订单量1200不符合常理
真实需求= 120仓库实际发货量就是真实需求
模型学什么学120扔掉虚假的1200

处理方式:CleanedQty = 出库量(120),标记为 需求异常-已替代

场景三:历史缺货(订单20,出库5)

步骤订单量出库量说明
原始数据205客户要20件,仓库断货只发了5件
谁异常?正常异常出库量5被供应不足压缩了
真实需求= 20客户订单量就是真实需求
模型学什么学20恢复被阉割的真实需求

处理方式:CleanedQty = 订单量(20),标记为 供应异常-保留订单量

场景四:正常销售(订单100,出库100)

步骤订单量出库量说明
原始数据100100常规销售,订单与出库一致
谁异常?正常正常数值在常规范围内,无需处理
真实需求= 100直接作为训练数据
模型学什么学100正常记录,原值保留

处理方式:CleanedQty = 100,标记为 正常

3.3 供应异常(历史缺货)的后续处理

当系统识别出供应异常记录后,它们会走一条不同于需求异常的“特殊通道”:

3.3.1 独立识别,不依赖异常检测算法

供应异常的识别走的是独立的业务规则,不依赖第2节的三种异常检测方法。因为 IQR、环比、Z-Score 扫描的是订单量,而出库量只是辅助信息——大多数供应异常记录的订单量完全正常(如订单20件),根本不会触发异常检测。它们是通过“订单量正常 + 出库量显著低于订单量”这条规则被独立发现的。

3.3.2 自动处理,不进入人工审核

供应异常的处理方式是固定的——保留订单量作为真实需求。这个决策不需要人工逐条判断,系统自动执行。这样既避免了计划员误操作(把缺货记录当成异常剔除),也减少了人工审核的工作量。

系统之所以能自动处理,是因为供应异常有一条清晰的、可由系统自动判定的规则:订单量在历史正常范围内,但出库量显著低于订单量

具体来说,系统用该产品过去 90 天的订单量分布作为基准:如果订单量没有超过历史 95% 分位数(说明不是录入错误),而出库量又不到订单量的一半(说明发生了缺货),则自动判定为供应异常,直接保留订单量作为真实需求。这个判定逻辑是确定性的,不需要人的主观判断,因此可以安全地自动化。

3.3.3 标记处理类型,便于追溯

每一条记录都会被打上处理标签。供应异常的标签是 供应异常-保留订单量,区别于 需求异常-已替代正常。这样你可以随时查询历史上哪些日子发生过缺货。

3.3.4 汇总为缺货分析报告

这些标记过的供应异常记录,还可以定期汇总成报告,回答几个关键问题:过去一年有多少天发生了缺货?哪些产品缺货最频繁?当前的供应满足率是多少?如果供应满足率低于目标服务水平,说明当前的安全库存设置或补货策略需要调整。

4. 处理极端值:不是删除,而是还原

对于确认是需要处理的异常值(如促销囤货、录入错误),天枢系统采用替代而非删除的策略。

基本原则:能用局部信息,就用局部信息;局部信息不足,才用全局信息。

  1. 优先用“前后 7 天中位数”:如果异常值周围有足够多的邻居数据(≥5 个非零值),取这些邻居的中位数作为替代值。中位数比均值更“稳”,不受极端值影响。
  2. 邻居不足时,退回到“整体均值”:如果该产品是长尾物料,前后 7 天几乎没有有效数据,则用产品整体的平均销量来替代。

这个逻辑的核心是:对于极端值,我们要根据历史实际做还原,而不是简单删除

5. 天枢系统数据清洗架构

                          天枢系统数据清洗架构

金蝶ERP系统
  · 销售订单(订单量)
  · 销售出库单(出库量,仅用于清洗)
        │
        ▼ 只读视图
天枢数据库(SalesForecast)
        │
        ▼
数据清洗引擎
        │
        ├── 规则A:异常检测
        │     · IQR(四分位距)法
        │     · 环比突变法
        │     · Z-Score 法
        │     (扫描订单量,标记数值异常)
        │
        └── 规则B:供应异常识别
              · 订单量 ≤ 历史95%分位
              · 出库量 < 订单量 × 50%
              → 自动判定为供应异常
        │
        ▼
   ┌────────────────────────┐
   │  分流处理                │
   │                        │
   │  供应异常 → 自动处理     │
   │  · CleanedQty = 订单量  │
   │                        │
   │  需求异常 → 人工审核     │
   │  · 判断真实 vs 虚假     │
   └───────────┬────────────┘
               │
               ▼
        SalesClean 表
        · CleanedQty(训练值)
        · ProcessType(处理标签)
        · IsShortage(缺货标记)

6. 数据清洗的一些好习惯

在实际操作中,天枢系统的数据清洗遵循这些原则:

  1. 如果不清楚来源,不要相信任何数据。拿到数据的第一件事,是弄清楚它是怎么产生的。
  2. 从源头(客户订单)开始确保数据质量。不要等到数据进了分析系统再处理,最好在录入端就有校验。
  3. 贴近业务,做销售的业务伙伴。理解业务端是怎么改变需求的,理解促销、新品导入、老品退市对数据的影响。
  4. 记录清洗的逻辑和假设。不管是手工还是自动清洗,每一步操作都要有记录,可追溯、可复盘。
  5. 数据清洗不是个单纯的计算活儿。先从业务着手,理解业务、理解数据。把那些规则清晰、能标准化的部分,交给计算机自动处理;规则模糊、需要判断的,留给人来决定。
  6. 聚焦大的清洗。不要花 80% 的时间去处理那些影响微小的边缘情况。对极端值、脏数据的根因,要做根源分析和纠偏。

7. 总结

数据清洗不是技术活,而是理解业务的过程。

  • 数据源的选择决定了模型看到的是“真实需求”还是“被阉割的需求”。
  • 异常检测需要多种方法互补,但最终判断权在人。
  • 区分需求异常和供应异常,是避免预测陷入“越来越低”恶性循环的关键。需求异常需要区分“真实但极端”和“虚假”两种子情况:前者如促销,应替代为合理值并从常规训练中移除;后者如录入错误,同样需要替代。供应异常是真实需求被供应能力限制,必须保留订单量作为训练值。
  • 极端值的处理是还原,不是删除。
  • 记录和追溯是数据治理的基石。

在下一篇博客中,我们将进入预测的核心——9 种模型同台竞技的设计哲学。聊聊为什么需要九种模型,它们如何“模拟考试”,以及那个最重要的铁律:一个好预测必须同时满足准确度高和没有系统性偏差


天枢系统,是一个基于 SQL Server 的销售预测与库存计划引擎。它从金蝶 ERP 取数,经过数据清洗、物料分层、九模型竞赛择优,输出未来 7 天的销量预测和库存建议。项目尚未上线,正在持续迭代中。