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 数据质量检查:六维评估模型

在清洗之前,必须对原始数据进行系统性质量评估。推荐使用以下六维检查框架:

  1. 完整性:检查必填字段(如项目ID、成本类型、金额)是否存在空值。
  2. 准确性:抽样验证数值是否在合理范围内(如人月单价不应为负数)。
  3. 一致性:同一项目在不同系统中的成本总额是否匹配。
  4. 时效性:数据时间戳是否在预期窗口内,是否存在过期数据。
  5. 唯一性:检查是否存在重复记录(如同一笔成本被多次录入)。
  6. 规范性:字段格式是否符合约定标准(如日期格式统一为 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% 重复率。低于阈值的字段需标记为“待修复”并进入清洗流程。
数据质量六维评估雷达图 完整性 准确性 一致性 时效性 唯一性 规范性 评分标准: 外圈=100%,内圈=60%

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 处理流程

  1. 标记:使用至少两种方法交叉验证,标记为“疑似异常”。
  2. 核实:回源系统确认是否为真实异常(如单据错误)。
  3. 处理:确认异常则修正或删除;真实极端值则保留并记录。
  4. 记录:将异常处理日志写入元数据表,供模型审计使用。
# 异常值检测示例(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
异常值检测与处理流程图 原始成本数据 Z-Score + IQR + 业务规则交叉验证 正常数据 → 保留 疑似异常 → 回源核实 修正 / 删除 / 保留并标记 写入异常日志 虚线表示日志回写路径

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%。只有通过验证的数据才能进入特征工程与参数化估算环节。