使用sklearn Imputer填充因变量时丢失数据的问题排查
问题:使用sklearn Imputer填充NaN后数据长度反而变短的原因与解决办法
首先看你的数据集输出:
Out[138]: 0 13495.0 1 16500.0 2 16500.0 3 13950.0 4 17450.0 5 15250.0 6 17710.0 7 18920.0 8 23875.0 9 NaN 10 16430.0 11 16925.0 12 20970.0 13 21105.0 14 24565.0 Name: price, dtype: float64
你执行的代码和遇到的异常:
len(y) # 15 from sklearn.preprocessing import Imputer mean_imputer_y = Imputer(strategy="mean", axis=0) imputed_y = mean_imputer_y.fit_transform(y) len(imputed_y) # 14
为什么会出现这种反直觉的情况?
核心原因在于旧版Imputer对一维输入的处理逻辑:
- 当你传入一维的
pandas Series(形状为(15,))时,Imputer会把每个元素当成一个独立的特征,而不是一条样本。 - 你设置了
axis=0(按特征/列处理),这时候它会检查每个特征是否有缺失值——第9个特征(对应原数据的NaN位置)因为全是缺失值(毕竟每个特征只有一个样本),就被直接丢弃了,最终输出剩下的14个特征,所以长度变成了14。
这完全不是你想要的“填充缺失值”的逻辑,因为你是把整个Series当作一列样本,而不是15个独立特征。
怎么修正这个问题?
有几个简单的解决办法:
1. 把一维数据转换成二维数组
把你的Series转成形状为(n_samples, 1)的二维数组,让Imputer明白这是一列样本:
len(y) # 15 from sklearn.preprocessing import Imputer mean_imputer_y = Imputer(strategy="mean", axis=0) # 用reshape把一维转二维 imputed_y = mean_imputer_y.fit_transform(y.values.reshape(-1, 1)) len(imputed_y) # 15,正常了! # 如果需要转回Series,可以用: imputed_y_series = pd.Series(imputed_y.flatten(), name='price')
2. 改用新版的SimpleImputer(推荐)
Imputer在scikit-learn 0.20版本之后就被标记为弃用了,官方推荐使用SimpleImputer,它的逻辑更清晰,对一维数据的处理也更友好:
import pandas as pd from sklearn.impute import SimpleImputer len(y) # 15 mean_imputer_y = SimpleImputer(strategy="mean") # 同样可以直接传入Series,或者转二维,SimpleImputer会自动处理 imputed_y = mean_imputer_y.fit_transform(y.values.reshape(-1, 1)) len(imputed_y) # 15 # 转回Series imputed_y_series = pd.Series(imputed_y.flatten(), index=y.index, name='price')
3. 直接用pandas自带的填充方法(最简便)
如果你只是想用均值填充pandas Series的缺失值,完全不需要依赖sklearn,pandas一行代码就能搞定:
y_filled = y.fillna(y.mean()) len(y_filled) # 15,完美解决!
内容的提问来源于stack exchange,提问作者Bestname
相关产品推荐
相关产品推荐

