3. 数据清洗入门
在采购支出分析中,原始数据通常来自ERP、SRM、财务系统或手工Excel报表,脏数据比例往往高达15%–30%。如果不经过清洗直接进行合同符合率计算,结果将严重失真。本章聚焦三类最常见的脏数据类型,并对比Excel与Python两种清洗工具的适用场景。
核心认知: 数据清洗不是一次性工作,而是贯穿采购分析全流程的迭代过程。合同符合率排查的准确性,80%取决于数据清洗质量。
3.1 常见脏数据类型
根据采购支出数据的实际审计经验,脏数据可归纳为三大类:空值、重复、格式不一致。下表列出了每类的典型表现与影响。
| 脏数据类型 | 典型表现 | 对合同符合率的影响 | 示例 |
|---|---|---|---|
| 空值 | 采购金额、合同编号、供应商名称字段为空 | 无法匹配合同,导致符合率偏低或计算中断 | 采购订单金额列为空,无法判断是否超合同价 |
| 重复 | 同一笔采购记录出现多次,或合同号重复 | 重复计算支出,虚增或虚减符合率 | 同一张发票号在系统中录入两次 |
| 格式不一致 | 日期格式、货币单位、供应商名称写法不统一 | 匹配失败,或聚合统计出错 | “2024/01/01” vs “2024-01-01” |
3.1.1 空值处理策略
空值不能简单删除,需要根据字段业务含义采取不同策略:
- 关键字段(合同号、采购金额):优先追溯源系统补全;无法补全时标记为“待核查”,不参与符合率计算。
- 非关键字段(备注、部门):可用“未知”或“N/A”填充,或使用均值/中位数填充(仅限数值型)。
- 时间字段:若为空且无法补全,建议剔除该记录,避免时间匹配错误。
避坑提示: 不要对所有空值统一填充0或“无”。例如采购金额为空时填充0,会导致合同符合率虚高,掩盖实际超支问题。
3.1.2 重复数据处理
重复数据分为完全重复和部分重复。完全重复可直接去重;部分重复需要根据业务规则判断保留哪一条。
- 完全重复:所有字段值相同,保留第一条即可。
- 部分重复:例如同一采购订单号对应两条记录,但金额不同。此时需检查是否为冲销、更正或拆分订单,不能简单去重。
- 去重优先级:按“更新时间最新”或“审批状态最完整”保留。
3.1.3 格式不一致处理
格式不一致是采购数据中最隐蔽的脏数据类型,常见场景包括:
- 日期格式:统一为 YYYY-MM-DD 标准格式。
- 货币单位:统一为“元”或“万元”,并保留两位小数。
- 供应商名称:去除空格、全半角统一、简称转全称(如“华为”转“华为技术有限公司”)。
- 合同编号:去除前后空格、统一大小写、补全前导零。
3.2 数据清洗流程框架
下图展示了从原始数据到清洗后数据的标准流程,适用于合同符合率排查场景。
3.3 数据清洗工具选择:Excel vs Python
Excel和Python是采购分析中最常用的两种清洗工具。下表从多个维度对比两者的适用性。
| 对比维度 | Excel | Python(Pandas) |
|---|---|---|
| 学习门槛 | 低,大部分采购人员已掌握基础操作 | 中高,需要编程基础 |
| 处理数据量 | 建议不超过10万行,超过会卡顿 | 可处理百万级甚至千万级数据 |
| 空值处理 | 手动筛选、替换或使用IF函数 | dropna()、fillna() 一行代码完成 |
| 去重能力 | “删除重复项”功能,但无法处理部分重复 | drop_duplicates() 支持按列去重、保留规则自定义 |
| 格式统一 | 分列、TEXT函数、手动替换 | 正则表达式、str.replace()、pd.to_datetime() |
| 可重复性 | 低,每次清洗需手动操作 | 高,脚本可重复执行,适合月度/季度清洗 |
| 适用场景 | 小规模数据、快速探查、临时分析 | 大规模数据、自动化流程、复杂清洗规则 |
3.3.1 Excel清洗实战要点
使用Excel进行数据清洗时,建议掌握以下核心操作:
- 空值定位:Ctrl+G → 定位条件 → 空值,快速选中所有空单元格。
- 去重:数据选项卡 → 删除重复项,注意勾选关键列(如合同号+采购订单号)。
- 格式统一:使用TEXT函数转换日期格式,使用TRIM去除空格,使用SUBSTITUTE替换不规范字符。
- 条件格式:高亮重复值、空值或异常值,辅助人工核查。
Excel局限提醒: 当采购数据超过5万行,或需要跨多个文件进行关联清洗时,Excel性能明显下降,且容易因手动操作引入新错误。此时建议切换到Python。
3.3.2 Python清洗实战要点
Python结合Pandas库是采购数据清洗的工业级方案。以下是一段典型的清洗代码示例:
import pandas as pd
# 读取采购数据
df = pd.read_excel('采购支出数据.xlsx')
# 1. 空值处理:删除合同号为空的行,填充金额空值为0
df = df.dropna(subset=['合同编号'])
df['采购金额'] = df['采购金额'].fillna(0)
# 2. 去重:按采购订单号去重,保留最新记录
df = df.sort_values('更新时间').drop_duplicates(subset=['采购订单号'], keep='last')
# 3. 格式统一:日期统一为YYYY-MM-DD,供应商名称去除空格
df['采购日期'] = pd.to_datetime(df['采购日期']).dt.strftime('%Y-%m-%d')
df['供应商名称'] = df['供应商名称'].str.strip().str.replace(' ', ' ')
# 4. 数据验证:检查金额是否为负数
if (df['采购金额'] < 0).any():
print('警告:存在负金额记录,请核查')
# 输出清洗后数据
df.to_excel('采购支出数据_清洗后.xlsx', index=False)
3.4 工具选择决策流程
下图帮助你在实际工作中快速决定使用Excel还是Python进行数据清洗。
3.5 本章小结
- 采购数据清洗的三大核心任务:空值处理、重复数据去重、格式统一。
- 空值不能一刀切删除,需根据字段业务含义选择填充、标记或剔除。
- 重复数据需区分完全重复和部分重复,部分重复必须结合业务规则判断。
- 格式不一致是合同匹配失败的主要原因之一,建议在清洗阶段统一为标准格式。
- Excel适合小规模、一次性、快速探查场景;Python适合大规模、重复执行、复杂规则场景。
- 建议采购分析团队同时掌握两种工具,根据数据量和重复频率灵活切换。
实战建议: 在开始合同符合率排查之前,先花30分钟对原始数据进行一次完整的清洗检查。这30分钟往往能节省后续数小时的排查时间,并大幅提升分析结果的可靠性。