4. 数据采集与预处理:结算数据的来源、清洗与标准化
工程项目结算审核的准确性,高度依赖底层数据的质量。原始结算数据通常来自多个异构系统,包含大量噪声、缺失和异常信息。本章将系统讲解结算数据的来源渠道、数据清洗的三大核心任务以及数据标准化的方法,为后续偏差分析模型提供干净、一致的数据基础。
4.1 结算数据的来源与结构
结算审核涉及的数据源主要包括四类:合同文件、工程量清单、现场签证单和设计变更单。每类数据的格式、字段和语义差异显著,需在采集阶段统一识别。
| 数据来源 | 核心字段 | 常见格式 | 数据特点 |
|---|---|---|---|
| 合同文件 | 合同编号、签约金额、工期、付款条款 | PDF / Word / 扫描件 | 结构化程度低,需人工提取关键字段 |
| 工程量清单 | 项目编码、项目名称、单位、数量、综合单价 | Excel / 计价软件导出 | 字段规范,但存在版本混乱问题 |
| 现场签证单 | 签证编号、内容描述、工程量、签认日期 | 纸质扫描 / 图片 / PDF | 手写内容多,OCR 识别误差大 |
| 设计变更单 | 变更编号、变更内容、费用增减、审批状态 | PDF / 系统流程记录 | 变更与签证易混淆,需关联审核 |
实务提示: 在采集阶段建议建立“数据来源登记表”,记录每份文件的版本号、接收日期和提供方,避免因版本不一致导致后续分析偏差。
4.2 数据清洗:缺失值、重复值与异常值处理
原始数据进入分析管道前,必须经过三步清洗:缺失值处理、重复值去重、异常值识别与修正。以下分别阐述各步骤的常用方法。
4.2.1 缺失值处理
缺失值在结算数据中常见于“签证工程量”“变更费用”等字段。处理策略取决于缺失比例和字段重要性:
- 删除法: 当缺失比例 > 50% 或字段为非关键描述字段时,直接删除该字段或记录。
- 填充法: 数值型字段(如工程量)使用同类清单的均值或中位数填充;类别型字段(如签证类型)使用众数填充。
- 插值法: 对时间序列类数据(如按月上报的进度款),采用线性插值或前向填充。
- 标记法: 保留缺失值并添加“是否缺失”标记列,供模型学习缺失模式。
4.2.2 重复值处理
重复数据主要来源于系统多次导入、同一签证被不同部门重复提交。处理流程如下:
- 精确去重: 基于主键(如合同编号+清单项目编码+签证编号)完全匹配,保留第一条记录。
- 模糊去重: 对文本描述字段(如签证内容)使用编辑距离或 Jaccard 相似度,阈值设为 0.85 以上视为重复。
- 业务规则去重: 同一签证单号出现多次时,以最新签认日期为准,删除历史版本。
4.2.3 异常值处理
异常值指明显偏离正常范围的数据点,如综合单价超出市场价 10 倍、签证工程量为负数等。常用检测方法包括:
| 检测方法 | 适用场景 | 判断标准 |
|---|---|---|
| Z-Score 法 | 近似正态分布的数值字段 | |Z| > 3 视为异常 |
| IQR 四分位法 | 偏态分布或存在离群点 | 超出 Q1-1.5IQR 或 Q3+1.5IQR |
| 业务规则法 | 单价、费率等有明确上下限 | 超出合同约定范围或政府指导价 |
注意: 异常值不一定是错误值。例如,因设计变更导致某清单项工程量突增 5 倍,属于业务合理异常,应保留并标记,而非直接删除。
4.3 数据标准化
不同来源的数据在量纲、编码规则和格式上存在差异,标准化是确保模型输入一致性的关键步骤。标准化包括以下三个层面:
- 数值标准化: 对金额、工程量等连续变量进行 Z-Score 标准化或 Min-Max 归一化,消除量纲影响。
- 编码标准化: 统一项目编码规则(如国标 GB50500 清单编码),将不同系统的编码映射为标准码表。
- 格式标准化: 日期统一为 YYYY-MM-DD 格式;金额统一保留两位小数;文本描述去除多余空格和特殊符号。
标准化示例: 某项目原始数据中“综合单价”字段存在“1200元/m³”“1200.00”“1,200”三种格式,标准化后统一为数值型 1200.00,并去除单位符号。
4.4 数据采集与预处理流程总图
下图展示了从多源数据采集到标准化输出的完整预处理流水线,涵盖清洗、去重、异常检测与标准化四个核心环节。
4.5 数据预处理代码示例(Python)
以下代码片段展示了使用 Pandas 对结算数据进行清洗与标准化的典型操作,涵盖缺失值填充、重复值删除和异常值检测。
import pandas as pd
import numpy as np
# 加载原始结算数据
df = pd.read_excel('settlement_data.xlsx')
# 1. 缺失值处理:用中位数填充工程量缺失值
df['quantity'] = df['quantity'].fillna(df['quantity'].median())
# 2. 重复值处理:基于合同编号+清单编码去重,保留最新记录
df = df.sort_values('submit_date').drop_duplicates(
subset=['contract_id', 'item_code'], keep='last'
)
# 3. 异常值检测:IQR 法标记综合单价异常
Q1 = df['unit_price'].quantile(0.25)
Q3 = df['unit_price'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
df['price_anomaly'] = ((df['unit_price'] < lower_bound) |
(df['unit_price'] > upper_bound)).astype(int)
# 4. 数值标准化:Min-Max 归一化
df['quantity_norm'] = (df['quantity'] - df['quantity'].min()) / \
(df['quantity'].max() - df['quantity'].min())
# 5. 格式标准化:日期统一格式
df['sign_date'] = pd.to_datetime(df['sign_date'], format='%Y-%m-%d')
print(f"清洗后数据量: {len(df)} 条,异常标记: {df['price_anomaly'].sum()} 条")
关键说明: 上述代码中,异常值仅做标记(price_anomaly 列)而非直接删除,保留业务判断空间。标准化后的数据可直接输入后续偏差分析模型。
4.6 数据质量评估指标
预处理完成后,需通过量化指标评估数据质量,确保清洗效果满足模型要求。常用指标如下:
| 指标名称 | 计算公式 | 合格标准 |
|---|---|---|
| 完整率 | 非空记录数 / 总记录数 × 100% | ≥ 95% |
| 唯一率 | 去重后记录数 / 去重前记录数 × 100% | ≥ 90% |
| 异常率 | 异常标记数 / 总记录数 × 100% | ≤ 5% |
| 标准化覆盖率 | 已标准化字段数 / 需标准化字段数 × 100% | 100% |
通过上述数据采集、清洗与标准化流程,可构建高质量、高一致性的结算数据集,为后续偏差分析模型验证与调优奠定坚实基础。