处理缺失值常用的方法:
- 直接移除缺失值的行
- 以均值/中位数等方法填充
- 以一些常数(-1/-999/etc.)代替
- 重构,比如以通过模型来预测缺失值
- 选择一些能处理缺失值的模型,比如XGBoost和CatBoost
Scikit-learn整理了几种方法,对应了上述的思路
Univariate feature imputation
使用SimpleImputer
对缺失值进行填充,其提供mean
,median
,most_frequent
以及constant
等方法,如果使用constant
方法则需fill_value
参数来指定常数
import numpy as np
from sklearn.impute import SimpleImputer
# Mean imputer
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
imp.fit_transform([[1, 2], [np.nan, 3], [7, 6]])
# Constant imputer
imp = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=999)
imp.fit_transform([[1, 2], [np.nan, 3], [7, 6]])
对于categorical数据,可以试试most_frequent
方法
import pandas as pd
imp = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
X = pd.DataFrame([['a', 'x'], [np.nan, 'y'], ['a', 'z'], ['b', 'x']], dtype="category")
imp.fit_transform(X)
Multivariate feature imputation
使用Iterative Imputer
类来填充缺失值
将每个缺失值的特征作为其他特征的函数来建模,它使用该函数的值作为估算。在每次迭代中,选择一个特征作为输出y,其他所有特征作为输入的X。然后在X和y上训练一个回归器,最后用来预测y的缺失值
从上述官方翻译来的解释,并不太好理解(其实是我不怎么理解);刚好在R语言中有个非常好用的补缺包-MissForest包,而sklearn的Iterative Imputer
类则相当整合了这些常用工具(missForest,mice等等)的算法,因此可以通过MissForest的算法来帮助理解
MissForest的思路:
- 假设有个X特征矩阵,其特征S(1,...,p)有缺失值,γ是迭代次数
- 对矩阵中缺失值做初始更新,比如平均数填充等常用方法
- 对X特征矩阵中特征S按照缺失值数目(缺失率)大小进行排序
- 开始迭代,先取缺失率最小的特征S,此时将X矩阵分成4部分:S特征中有缺失部分定义为y(s)mis,S特征中无缺失部分定义为y(s)obs,除S特征以外的所有变量中对应S特征缺失索引的部分定义为X(s)mis,除S特征以外的所有变量中对应S特征无缺失索引的部分定义为X(s)obs
- 通过RF回归算法来拟合y(s)obs和X(s)obs,然后预测X(s)mis对应的y(s)mis
- 将上述预测值y(s)mis更新至X矩阵中,接着取第二小缺失率的特征S,循环所有特征S(有缺失值的),并将RF模型预测值填充至X矩阵中
- 此时只是第一次迭代,接着将更新后的X矩阵跟初始X矩阵做比较,通过收敛函数的收敛至是否满足设定的阈值;如果不满足则开始第二次迭代,直至收敛值满足阈值或者迭代次数达到设定的γ
以上参考自MissForest文献(发表自Bioinformatics):MissForest—non-parametric missing value imputation for mixed-type data
文献中有个伪算法图:
IterativeImputer可支持对个回归estimators,默认是BayesianRidge
,其他参数可根据实际情况进行选择
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
imp = IterativeImputer(max_iter=10, random_state=0)
imp.fit_transform([[1, 2], [3, 6], [4, 8], [np.nan, 4]])
此外sklearn还对不同estimators在IterativeImputer中的效果做了比较:Imputing missing values with variants of IterativeImputer,以及如何在build model前处理缺失值:Imputing missing values before building an estimator
IterativeImputer
不仅支持上述文章中所提到的几个estimators,还支持Catboost
(虽然Catboost本身就支持有缺失值的特征矩阵),但是LightGBM和XGBoost则不行
Nearest neighbors imputation
除了sklearn之外,还有两个常用的缺失值插补的包impytue和fancyimpute,除了简单的单变量之外,还支持多变量插补。比如fancyimpute的
KNN
方法
sklearn也把KNNImputer整合到inpute方法中(最新版0.22),方便在统一的框架下调用不同的补缺方法。。。。
from sklearn.impute import KNNImputer
imp = KNNImputer(n_neighbors=2, weights="uniform")
imp.fit_transform([[1, 2], [3, 6], [4, 8], [np.nan, 4]])
Marking imputed values
MissingIndicator
可以用于将数据集转化为二进制矩阵(展示特征值是否有缺失);通过调节features参数可以选择只展示缺失的特征missing-only
(默认)或者展示全部特征all
from sklearn.impute import MissingIndicator
indicator = MissingIndicator()
indicator.fit_transform([[np.nan,1,2], [3,5,np.nan]])
indicator = MissingIndicator(features="all")
indicator.fit_transform([[np.nan,1,2], [3,5,np.nan]])
如果想在estimators中整合MissingIndicator
的结果,则可以考虑用FeatureUnion
或者ColumnTransformer
,以前者为例:
from sklearn.pipeline import FeatureUnion
X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
transformer = FeatureUnion(
transformer_list=[
('features', SimpleImputer(strategy='mean')),
('indicators', MissingIndicator())])
transformer.fit_transform(X)
上述FeatureUnion
的作用:
FeatureUnion把若干个transformer object组合成一个新的estimators,原先独立的transoformers 输出的样本特征向量被以end-to-end的方式拼接成为一个更大的特征向量
现在sklearn为SimpleImputer
和IterativeImputer
提供了一个add_indicator
参数(默认是Flase),就是为了达到整合MissingIndicator
的目的,避免繁琐的使用FeatureUnion
,如这个issues所提到的;因此简单加上这个参数就能达到上述FeatureUnion的作用,如:
X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
imp = SimpleImputer(missing_values=np.nan, strategy='mean', add_indicator=True)
imp.fit_transform(X)
参考资料:
Imputation of missing values
[特征工程]数据预处理的方法和技巧
本文出自于http://www.bioinfo-scrounger.com转载请注明出处