4. 数据准备与预处理:数据采集来源、数据清洗与特征工程

在工程项目预算控制中,成本预测模型的精度高度依赖于输入数据的质量。本章将系统讲解数据采集的三大来源、数据清洗的核心流程以及特征工程的实战方法,确保模型能够从原始业务数据中提取出有效的预测信号。

4.1 数据采集来源

成本预测模型的数据来源主要分为三类:历史项目数据、市场行情数据和外部宏观数据。下表对比了各来源的特点与典型字段:

数据来源 核心内容 典型字段示例 采集频率 数据质量等级
历史项目数据 企业内部已完工项目的成本台账、结算单、变更记录 项目类型、建筑面积、结构形式、单位造价、工期、变更次数 项目结束后归档 高(内部可控)
市场行情数据 材料价格、劳务单价、机械租赁费、分包指导价 钢筋价格、混凝土标号价、人工工日单价、塔吊月租费 月度/周度更新 中(需清洗)
外部宏观数据 CPI、PPI、行业景气指数、政策调整文件 建材PPI指数、贷款利率、环保停工天数 季度/年度 低(需对齐)
实战建议:优先保证历史项目数据的完整性和一致性。市场行情数据建议对接至少两个独立信息源(如造价信息网 + 地方定额站发布价),用于交叉验证。

4.2 数据清洗流程

原始数据通常存在缺失、异常、重复和格式不一致等问题。标准清洗流程包含以下五个步骤:

  1. 缺失值处理:对关键字段(如单位造价、工期)采用中位数填充或线性插值;对非关键字段可标记为“未知”。
  2. 异常值检测:使用IQR(四分位距)或Z-score方法识别单价、工程量等字段中的离群点,结合业务规则确认是否剔除。
  3. 重复数据去重:基于项目编码、合同编号等唯一标识进行精确去重;对模糊重复采用相似度阈值合并。
  4. 格式标准化:统一日期格式(YYYY-MM-DD)、货币单位(万元)、面积单位(平方米)等。
  5. 一致性校验:检查逻辑关系,如“总造价 = 直接费 + 间接费 + 利润 + 税金”是否成立。
清洗效果指标:清洗后数据应满足:缺失率 < 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()

通过以上数据准备与预处理流程,原始业务数据将被转化为结构清晰、质量可靠的特征矩阵,为后续成本预测模型的训练和接口调用奠定坚实基础。