数据预处理基础:缺失值处理、异常值识别与处理、数据标准化与归一化

在量化研究与因子挖掘流程中,原始数据几乎不可能直接用于建模。缺失值、异常值以及量纲不统一是三大最常见的“数据污染”来源。本章系统讲解这三类问题的诊断方法与处理技术,确保后续变量衍生与分箱操作建立在干净、稳定的数据基础之上。

2.1 缺失值处理

缺失值产生的原因包括:数据采集设备故障、传输丢包、人工录入遗漏、或某些指标在特定条件下天然不存在(如停牌期间的交易量)。处理缺失值前,必须先判断其缺失机制。

缺失机制 定义 典型场景 处理策略
完全随机缺失(MCAR) 缺失与否完全独立于任何观测值 传感器随机故障 删除或简单插补
随机缺失(MAR) 缺失依赖于其他已观测变量 高波动率日更容易缺失报价数据 模型插补(回归/多重插补)
非随机缺失(MNAR) 缺失依赖于缺失变量本身 亏损严重的股票更可能不披露财务细节 需引入外部信息或专用模型

2.1.1 缺失值诊断

使用 pandas 进行快速诊断:

import pandas as pd
import numpy as np

# 生成示例数据
df = pd.DataFrame({
    'close': [100, 102, np.nan, 105, 107],
    'volume': [1e6, np.nan, 1.2e6, 1.1e6, np.nan],
    'pe_ratio': [15, 16, 15.5, np.nan, 14.8]
})

# 缺失值统计
missing_count = df.isnull().sum()
missing_ratio = df.isnull().mean() * 100
print("缺失数量:\n", missing_count)
print("\n缺失比例(%):\n", missing_ratio)

2.1.2 常用处理方法

  • 删除法:适用于 MCAR 且缺失比例 < 5% 的场景。使用 df.dropna() 按行或按列删除。
  • 固定值填充:对价格类数据可用前一日收盘价(ffill);对比率类数据可用行业均值或中位数。
  • 统计量插补:均值、中位数、众数填充。注意:均值对异常值敏感,金融数据优先使用中位数。
  • 模型插补:KNN、线性回归、随机森林等利用其他特征预测缺失值。
量化实战建议:对于时间序列因子(如动量、波动率),优先使用前向填充(ffill)或线性插值(interpolate),避免引入未来信息。
# 前向填充与线性插值示例
df['close_ffill'] = df['close'].ffill()
df['volume_interp'] = df['volume'].interpolate(method='linear')
print(df[['close', 'close_ffill', 'volume', 'volume_interp']])

2.2 异常值识别与处理

异常值(Outliers)是指显著偏离数据整体分布的观测点。在量化因子中,异常值可能来自数据录入错误、极端市场事件(如闪崩),或真实的稀有事件。不加处理直接建模,会严重扭曲因子与收益之间的关系。

2.2.1 异常值识别方法

方法 原理 适用场景 参数
Z-Score 法 假设正态分布,超过均值±3σ视为异常 近似正态分布的因子 阈值通常取 3
IQR 四分位距法 Q1 - 1.5×IQR 以下或 Q3 + 1.5×IQR 以上 偏态分布、含厚尾的金融数据 系数 1.5(极端用 3)
MAD 法 基于中位数绝对偏差,稳健性强 存在多个异常值或分布严重偏斜 MAD 乘数通常取 3~5
# IQR 法识别异常值
def detect_outliers_iqr(series, multiplier=1.5):
    Q1 = series.quantile(0.25)
    Q3 = series.quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - multiplier * IQR
    upper_bound = Q3 + multiplier * IQR
    return (series < lower_bound) | (series > upper_bound)

# 示例
data = pd.Series([10, 12, 11, 13, 100, 12, 11, 14, 9, 200])
outliers = detect_outliers_iqr(data)
print("异常值索引:", data[outliers].index.tolist())
print("异常值:", data[outliers].values)

2.2.2 异常值处理策略

  • 截尾(Winsorization):将异常值替换为边界值(如 99% 分位数),保留样本量且减少极端值影响。
  • 删除:仅当确认异常值来自数据错误且比例极低时使用。
  • 缺失化后插补:先将异常值标记为缺失,再用缺失值处理方法填充。
注意:不要对训练集和测试集分别计算分位数边界。应在训练集上计算截尾阈值,并应用到测试集,避免数据泄露。
# 截尾处理示例
def winsorize_series(series, lower=0.01, upper=0.99):
    q_low = series.quantile(lower)
    q_high = series.quantile(upper)
    return series.clip(lower=q_low, upper=q_high)

df['pe_winsorized'] = winsorize_series(df['pe_ratio'], lower=0.05, upper=0.95)
量化实战对比:Z-Score 法对极端值敏感(均值和标准差本身会被异常值拉偏),而 IQR 和 MAD 法基于分位数或中位数,稳健性更强。在因子预处理中,推荐优先使用 IQR 法或 MAD 法。

2.3 数据标准化与归一化

不同因子往往具有不同的量纲和数值范围(如市盈率 10~50,成交量 10^6~10^9)。标准化与归一化将因子映射到统一尺度,避免量纲差异主导模型训练,同时提升梯度下降类算法的收敛速度。

2.3.1 核心方法对比

方法 公式 输出范围 对异常值敏感度 适用模型
Z-Score 标准化 \( z = \frac{x - \mu}{\sigma} \) 无固定范围,均值为 0,标准差为 1 高 线性回归、SVM、PCA、神经网络
Min-Max 归一化 \( x' = \frac{x - x_{min}}{x_{max} - x_{min}} \) [0, 1] 极高 距离类模型(KNN、K-Means)
Robust 标准化 \( x' = \frac{x - median}{IQR} \) 无固定范围,中位数为 0 低 含较多异常值的金融因子
Rank 排序归一化 将原始值替换为百分位排名 [0, 1] 或 [1, N] 不敏感 非参数模型、因子组合
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler

# 示例数据
factor_data = [[100], [200], [150], [300], [1000]]  # 含异常值 1000

# Z-Score 标准化
scaler_std = StandardScaler()
z_scores = scaler_std.fit_transform(factor_data)
print("Z-Score:\n", z_scores)

# Robust 标准化
scaler_robust = RobustScaler()
robust_scores = scaler_robust.fit_transform(factor_data)
print("Robust:\n", robust_scores)
量化实战建议:在因子分箱前,推荐使用 Rank 排序归一化或 Robust 标准化。这两种方法对异常值不敏感,且能保留因子的相对排序信息,非常适合截面因子处理。

2.4 数据预处理流程总览

下图展示了从原始数据到干净、标准化因子的完整预处理流水线:

数据预处理流程总览 原始数据 缺失值处理 异常值识别与处理 标准化 / 归一化 干净因子数据 说明:每一步的输出都需进行质量检查(缺失比例、异常值数量、分布形态),确保进入下一步的数据可靠。

2.5 预处理顺序与注意事项

  1. 先处理缺失值,再识别异常值:缺失值会导致统计量(均值、标准差、分位数)失真,影响异常值判断。
  2. 标准化/归一化放在最后:缺失值填充和异常值截尾会改变数据分布,应在分布稳定后再进行尺度变换。
  3. 截面与时间序列的区别:截面因子(如市值、市盈率)可在每个时间截面上独立标准化;时间序列因子(如过去 20 日收益率)应使用滚动窗口标准化,避免未来信息。
  4. 保存变换参数:对训练集拟合的标准化参数(均值、标准差、分位数等)必须保存,用于后续测试集和线上推理。
实战检查清单:
✅ 缺失比例 < 30% 时优先插补,否则考虑删除该特征。
✅ 异常值截尾边界在训练集上计算,固定后应用到全量数据。
✅ 标准化方法选择与模型类型匹配:树模型不需要标准化,线性模型和神经网络必须标准化。
✅ 每次预处理后绘制分布直方图或箱线图,确认数据形态变化。

完成本章的数据预处理后,因子数据将具备完整性、稳健性和可比性,为后续的变量衍生与因子分箱奠定坚实基础。