4. 数据采集与清洗
在智能成本估算接口的调试与模型训练中,数据质量直接决定估算精度。本章聚焦于成本历史数据的全生命周期处理:从多源采集、质量检查,到缺失值与异常值的系统性修复。只有经过严格清洗的数据,才能为参数化估算模型提供可靠的训练基础。
4.1 成本历史数据的来源与采集策略
成本历史数据通常分散在多个异构系统中,采集时需兼顾覆盖率与一致性。常见来源包括:
| 数据来源 | 典型系统/格式 | 采集方式 | 注意事项 |
|---|---|---|---|
| ERP 系统 | SAP、Oracle EBS | API 接口 / 数据库直连 | 注意会计期间与成本中心映射 |
| 项目管理工具 | Jira、MS Project | REST API / CSV 导出 | 工时与成本字段需对齐单位 |
| 采购与合同系统 | Ariba、Coupa | SFTP 文件 / 批量导入 | 汇率与税率字段易遗漏 |
| 历史估算文档 | Excel、Google Sheets | 手动上传 / 解析库 | 格式不统一,需模板校验 |
| 第三方基准库 | ISBSG、中国软件行业基准数据 | 订阅 API / 离线数据包 | 注意数据年份与地域匹配 |
采集最佳实践:优先使用 API 增量同步,避免全量导出带来的性能压力。每次采集后立即生成数据清单(Data Lineage),记录来源、时间戳与采集批次号。
4.2 数据质量检查:六维评估模型
在清洗之前,必须对原始数据进行系统性质量评估。推荐使用以下六维检查框架:
- 完整性:检查必填字段(如项目ID、成本类型、金额)是否存在空值。
- 准确性:抽样验证数值是否在合理范围内(如人月单价不应为负数)。
- 一致性:同一项目在不同系统中的成本总额是否匹配。
- 时效性:数据时间戳是否在预期窗口内,是否存在过期数据。
- 唯一性:检查是否存在重复记录(如同一笔成本被多次录入)。
- 规范性:字段格式是否符合约定标准(如日期格式统一为 YYYY-MM-DD)。
# 数据质量检查示例(Python 伪代码)
def quality_check(df):
report = {}
report['completeness'] = df[['project_id', 'cost_amount']].isnull().sum()
report['accuracy'] = (df['cost_amount'] < 0).sum()
report['uniqueness'] = df.duplicated(subset=['project_id', 'cost_date']).sum()
return report
质量阈值参考:完整性 > 95%,准确性 > 99%,唯一性 < 1% 重复率。低于阈值的字段需标记为“待修复”并进入清洗流程。
4.3 缺失值处理策略
成本数据中的缺失值通常由系统对接遗漏或人工录入疏忽导致。处理策略需根据缺失率与字段重要性分级:
| 缺失率 | 字段类型 | 推荐策略 | 适用场景 |
|---|---|---|---|
| < 5% | 数值型(如金额) | 均值/中位数填充 | 成本分布近似正态时 |
| 5% - 20% | 类别型(如成本中心) | 众数填充 / 模型预测 | 类别分布稳定时 |
| 20% - 50% | 关键字段(如项目ID) | 业务规则推导 / 回源补录 | 存在关联系统可追溯时 |
| > 50% | 非关键字段 | 删除该字段或整行 | 字段对估算模型贡献度低时 |
# 缺失值处理示例
import pandas as pd
import numpy as np
def handle_missing(df, strategy='median'):
# 数值型字段:中位数填充
num_cols = df.select_dtypes(include=[np.number]).columns
for col in num_cols:
if df[col].isnull().mean() < 0.2:
df[col].fillna(df[col].median(), inplace=True)
# 类别型字段:众数填充
cat_cols = df.select_dtypes(include=['object']).columns
for col in cat_cols:
if df[col].isnull().mean() < 0.15:
df[col].fillna(df[col].mode()[0], inplace=True)
return df
注意:切勿对时间序列成本数据使用全局均值填充,应使用前向填充(ffill)或插值法,避免破坏时间趋势。
4.4 异常值检测与处理
成本数据中的异常值可能源于录入错误、系统故障或真实极端事件(如突发采购)。检测方法需结合统计与业务规则:
4.4.1 常用检测方法对比
| 方法 | 原理 | 适用数据分布 | 阈值设定 |
|---|---|---|---|
| Z-Score | 基于标准差偏离程度 | 近似正态分布 | |Z| > 3 |
| IQR 四分位距 | 基于箱线图上下边界 | 偏态分布 | Q1 - 1.5*IQR 或 Q3 + 1.5*IQR |
| 孤立森林 | 基于随机森林的隔离深度 | 高维数据 | 异常分数 > 0.6 |
| 业务规则 | 基于领域知识设定上下限 | 所有分布 | 如人月单价 > 100万视为异常 |
4.4.2 处理流程
- 标记:使用至少两种方法交叉验证,标记为“疑似异常”。
- 核实:回源系统确认是否为真实异常(如单据错误)。
- 处理:确认异常则修正或删除;真实极端值则保留并记录。
- 记录:将异常处理日志写入元数据表,供模型审计使用。
# 异常值检测示例(IQR 方法)
def detect_outliers_iqr(df, column):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
return outliers, lower_bound, upper_bound
4.5 清洗后的数据验证与版本管理
清洗完成后,必须进行数据验证以确保清洗逻辑未引入系统性偏差:
- 分布对比:绘制清洗前后的成本分布直方图,检查均值与标准差变化是否在可接受范围(通常 < 5%)。
- 业务规则校验:随机抽取 50 条记录,人工核对清洗结果是否符合业务逻辑。
- 版本标记:每次清洗生成一个数据版本号(如 v1.2.0),并记录清洗规则快照。
# 数据版本管理示例
data_version = {
"version": "1.2.0",
"timestamp": "2025-03-21T14:30:00Z",
"source_count": 12500,
"after_clean_count": 11820,
"rules_applied": ["median_fill_cost", "iqr_outlier_removal", "business_rule_unit_price"]
}
关键指标:清洗后的数据应满足:缺失率 < 2%,异常值占比 < 1%,字段一致性 100%。只有通过验证的数据才能进入特征工程与参数化估算环节。