4、缺失值处理:缺失值类型与处理方法

做金融时间序列分析,缺失值是个绕不开的坎。

我刚开始做量化策略时,拿到一份日频收益率数据,心想直接跑模型吧。结果一跑,报错。一看数据,中间缺了三天。嗯,这就是典型的缺失值问题。今天咱们就把这块彻底讲透。

4.1 缺失值的三种类型

搞懂缺失值的类型,比学会插补方法更重要。为什么?因为不同类型,处理策略完全不同。

我个人习惯把缺失值分成三类:

类型 全称 通俗理解 金融场景举例
MCAR 完全随机缺失 缺失纯属偶然,跟数据本身无关 某天交易所系统故障,所有股票都缺数据
MAR 随机缺失 缺失跟其他变量有关,跟自身无关 小市值股票更容易缺失流动性数据
MNAR 非随机缺失 缺失跟自身取值有关 收益率特别低的股票,主动不披露数据

核心判断标准:缺失的原因是否与缺失值本身有关。有关就是MNAR,无关就是MCAR或MAR。

我在项目中遇到过最头疼的就是MNAR。比如某只债券连续几天没有成交价,你以为只是流动性差,其实是因为它要违约了,没人敢交易。这种缺失,你插补出来的值全是错的。

4.2 删除法:简单粗暴,但有代价

删除法是最直接的方法。说白了就是「眼不见为净」。

行删除

把包含缺失值的整行删掉。适用于MCAR场景,且缺失比例很小(比如5%以内)。

# 行删除示例
df_clean = df.dropna()  # 删除所有含缺失值的行
print(f"删除前:{len(df)}行,删除后:{len(df_clean)}行")

注意:金融时间序列中,行删除可能导致时间不连续。比如你删掉某天的数据,后续的滞后特征计算就全乱了。

列删除

如果某一列缺失太多(比如超过50%),我建议直接删掉这列。留着也是鸡肋。

# 列删除示例
threshold = 0.5  # 缺失比例阈值
df_clean = df.loc[:, df.isnull().mean() < threshold]

我曾经处理过一份300只股票的日频数据,其中一只股票有80%的数据缺失。我当时犹豫要不要保留,后来发现这只股票已经退市了。嗯,果断删掉。

4.3 插补法:更精细的处理方式

删除法太浪费数据了。金融数据本来就贵,删了心疼。所以大多数时候,我们选择插补。

均值/中位数插补

最简单的插补方式。用该列的均值或中位数填充缺失值。

# 均值插补
df['close'].fillna(df['close'].mean(), inplace=True)

# 中位数插补(更稳健,适合有异常值的情况)
df['close'].fillna(df['close'].median(), inplace=True)

我的建议:金融数据通常有尖峰厚尾特征,中位数比均值更靠谱。比如某只股票突然暴涨10倍,均值会被拉高,但中位数不受影响。

前向填充与后向填充

时间序列特有的插补方式。用上一个或下一个有效值填充。

# 前向填充:用上一个值填充
df['close'].fillna(method='ffill', inplace=True)

# 后向填充:用下一个值填充
df['close'].fillna(method='bfill', inplace=True)

前向填充在金融中很常用。比如股票停牌一天,复牌后价格通常沿用停牌前的收盘价。但要注意,如果连续缺失太多天,前向填充会引入偏差。

避坑指南:我曾经用前向填充处理过连续10天的缺失数据,结果模型训练出来全是错的。后来发现那10天发生了重大政策变化,前向填充完全忽略了市场突变。

线性插值

假设缺失值前后是线性关系,用直线上的点来填充。

# 线性插值
df['close'].interpolate(method='linear', inplace=True)

线性插值比前向填充更平滑。适合处理收益率、波动率这类连续变化的指标。但如果是跳跃性数据(比如突然的涨跌停),线性插值就不太合适了。

KNN插补

用K个最相似的样本的均值来填充。这是机器学习的方法,效果通常更好。

from sklearn.impute import KNNImputer

imputer = KNNImputer(n_neighbors=5)
df_imputed = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)

KNN插补的优点是能利用多个维度的信息。比如某只股票缺失了收盘价,但它的成交量、开盘价、行业指数都正常,KNN就能通过这些信息推断出合理的收盘价。

选择建议:

  • 缺失比例<5%:行删除或均值插补
  • 缺失比例5%-20%:前向填充或线性插值
  • 缺失比例>20%:KNN插补,或考虑列删除
  • MNAR类型:不要插补,先分析缺失原因

4.4 知识体系总览

下面这张图,是我梳理的缺失值处理全流程。你保存下来,以后遇到缺失值问题,照着走就行。

缺失值处理决策流程 发现缺失值 判断缺失类型:MCAR/MAR/MNAR? MCAR:完全随机缺失 MAR:随机缺失 MNAR:非随机缺失 缺失<5%:行删除 缺失>5%:均值/中位数插补 前向填充/线性插值 KNN插补 先分析缺失原因 不要盲目插补! 验证插补效果,评估对模型影响 完成缺失值处理

这张图的核心逻辑很简单:先判断类型,再选方法。MCAR和MAR可以放心处理,MNAR要格外小心。

最后说一句:没有万能的方法。我每次处理缺失值,都会先画个缺失值分布图,看看缺失模式。有时候缺失值本身就在告诉你一些信息——比如某只股票频繁缺失数据,可能意味着它流动性差,或者有潜在风险。


公众号:蓝海资料掘金营,微信deep3321