4. 数据准备与预处理:数据采集来源、数据清洗与特征工程
在工程项目预算控制中,成本预测模型的精度高度依赖于输入数据的质量。本章将系统讲解数据采集的三大来源、数据清洗的核心流程以及特征工程的实战方法,确保模型能够从原始业务数据中提取出有效的预测信号。
4.1 数据采集来源
成本预测模型的数据来源主要分为三类:历史项目数据、市场行情数据和外部宏观数据。下表对比了各来源的特点与典型字段:
| 数据来源 | 核心内容 | 典型字段示例 | 采集频率 | 数据质量等级 |
|---|---|---|---|---|
| 历史项目数据 | 企业内部已完工项目的成本台账、结算单、变更记录 | 项目类型、建筑面积、结构形式、单位造价、工期、变更次数 | 项目结束后归档 | 高(内部可控) |
| 市场行情数据 | 材料价格、劳务单价、机械租赁费、分包指导价 | 钢筋价格、混凝土标号价、人工工日单价、塔吊月租费 | 月度/周度更新 | 中(需清洗) |
| 外部宏观数据 | CPI、PPI、行业景气指数、政策调整文件 | 建材PPI指数、贷款利率、环保停工天数 | 季度/年度 | 低(需对齐) |
实战建议:优先保证历史项目数据的完整性和一致性。市场行情数据建议对接至少两个独立信息源(如造价信息网 + 地方定额站发布价),用于交叉验证。
4.2 数据清洗流程
原始数据通常存在缺失、异常、重复和格式不一致等问题。标准清洗流程包含以下五个步骤:
- 缺失值处理:对关键字段(如单位造价、工期)采用中位数填充或线性插值;对非关键字段可标记为“未知”。
- 异常值检测:使用IQR(四分位距)或Z-score方法识别单价、工程量等字段中的离群点,结合业务规则确认是否剔除。
- 重复数据去重:基于项目编码、合同编号等唯一标识进行精确去重;对模糊重复采用相似度阈值合并。
- 格式标准化:统一日期格式(YYYY-MM-DD)、货币单位(万元)、面积单位(平方米)等。
- 一致性校验:检查逻辑关系,如“总造价 = 直接费 + 间接费 + 利润 + 税金”是否成立。
清洗效果指标:清洗后数据应满足:缺失率 < 5%,异常值占比 < 2%,重复率 = 0%,字段格式一致率 = 100%。
4.3 特征工程
特征工程是将原始数据转化为模型可理解的特征向量的过程。在成本预测场景中,特征工程主要包含以下三类操作:
4.3.1 数值型特征处理
- 归一化/标准化:对单位造价、建筑面积等连续变量进行Min-Max缩放或Z-score标准化,消除量纲影响。
- 对数变换:对偏态分布的成本数据(如大型项目总造价)取对数,使其更接近正态分布。
- 分箱离散化:将工期、层数等连续变量按业务经验划分为“短/中/长”、“低层/多层/高层”等类别。
4.3.2 类别型特征编码
- 独热编码:适用于项目类型(住宅/商业/工业)、结构形式(框架/剪力墙/钢结构)等无序类别。
- 目标编码:对地区、分包商等高频类别,用历史平均单位造价替代原始标签,减少维度爆炸。
4.3.3 时间与衍生特征
- 时间特征:提取开工季度、施工月份、是否跨年等周期性特征。
- 复合特征:构造“单位面积钢筋含量 = 钢筋总用量 / 建筑面积”、“工期压缩比 = 实际工期 / 定额工期”等业务指标。
避坑提示:避免引入与目标变量(单位造价)存在直接线性关系的特征,如“总造价 / 建筑面积”在训练集上会导致数据泄露。应使用原始字段构造独立特征。
4.4 数据预处理流程架构
下图展示了从数据采集到特征工程完成的完整预处理流水线:
4.5 实战代码示例:数据清洗与特征构造
以下代码展示了使用Python对历史项目数据进行清洗和特征构造的典型实现:
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, LabelEncoder
# 加载原始数据
df = pd.read_csv('historical_projects.csv')
# ====== 数据清洗 ======
# 1. 缺失值处理:单位造价用中位数填充
df['unit_cost'].fillna(df['unit_cost'].median(), inplace=True)
# 2. 异常值检测:使用IQR剔除单位造价异常
Q1 = df['unit_cost'].quantile(0.25)
Q3 = df['unit_cost'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
df = df[(df['unit_cost'] >= lower_bound) & (df['unit_cost'] <= upper_bound)]
# 3. 重复去重
df.drop_duplicates(subset=['project_code'], keep='first', inplace=True)
# 4. 格式标准化:日期统一
df['start_date'] = pd.to_datetime(df['start_date'], format='%Y-%m-%d')
# ====== 特征工程 ======
# 1. 数值特征:标准化
scaler = StandardScaler()
df['scaled_area'] = scaler.fit_transform(df[['building_area']])
# 2. 类别特征:独热编码
df = pd.get_dummies(df, columns=['project_type', 'structure_type'], drop_first=True)
# 3. 衍生特征:单位面积钢筋含量
df['steel_density'] = df['steel_total_weight'] / df['building_area']
# 4. 时间特征:开工季度
df['start_quarter'] = df['start_date'].dt.quarter
print(f"清洗后数据量: {len(df)} 条")
print(f"特征维度: {df.shape[1]} 列")
关键说明:上述代码中,
unit_cost 为目标变量(单位造价),在特征工程中不应将其自身或其线性组合(如总造价/面积)作为输入特征。衍生特征 steel_density 使用原始字段 steel_total_weight 和 building_area 构造,与目标变量无直接线性关系,符合建模规范。
4.6 数据质量评估矩阵
在完成预处理后,建议使用以下矩阵对数据质量进行量化评估:
| 评估维度 | 指标 | 合格标准 | 检查方法 |
|---|---|---|---|
| 完整性 | 字段缺失率 | < 5% | df.isnull().mean() |
| 准确性 | 异常值占比 | < 2% | IQR / Z-score 统计 |
| 一致性 | 逻辑校验通过率 | 100% | 自定义规则验证 |
| 时效性 | 数据时间跨度 | 覆盖近3年 | 日期范围检查 |
| 唯一性 | 重复记录比例 | 0% | df.duplicated().sum() |
通过以上数据准备与预处理流程,原始业务数据将被转化为结构清晰、质量可靠的特征矩阵,为后续成本预测模型的训练和接口调用奠定坚实基础。