在真实世界中的数据,难免会有缺失值的情况出现,可能是收集资料时没有收集到对应的信息,也可能是整理的时候误删除导致。对于包含缺失值的数据,有两大类处理思路
1. 删除包含缺失值的行和列,这样会导致特征和样本的减少,在样本和特征的个数很多,且包含缺失值的样本和特征较少的情况下,这种简单粗暴的操作还可以接受
2. 对缺失值进行填充,填充时就需要考虑填充的逻辑了,本质是按照不同的填充逻辑来估算缺失值对应的真实数据
在scikit-learn中,通过子模块impute进行填充,提功了以下几种填充方式
1. 单变量填充
这种方式只利用某一个特征的值来进行填充,比如特征A中包含了缺失值,此时可以将该缺失值填充为一个固定的常数,也可以利用所有特征A的非缺失值,来统计出均值,中位数等,填充对应的缺失值,由于在填充时,只需要考虑该特征对应的值,所以称之为单变量填充,代码如下
代码语言:javascript复制>>> from sklearn.impute import SimpleImputer
>>> imp = SimpleImputer(missing_values=np.nan, strategy='mean')
>>> X = np.array([[np.nan, 2], [6, np.nan], [7, 6]])
>>> X
array([[nan, 2.],
[ 6., nan],
[ 7., 6.]])
>>> imp.fit_transform(X)
array([[6.5, 2. ],
[6. , 4. ],
[7. , 6. ]])
除了均值以外,还支持中位数,众数,指定的常数进行填充,代码如下
代码语言:javascript复制>>> imp = SimpleImputer(missing_values=np.nan, strategy='mean')
>>> imp = SimpleImputer(missing_values=np.nan, strategy='median')
>>> imp = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
>>> imp = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=3)
2. 多变量填充
这种方式在填充时会考虑多个特征之间的关系,比如针对特征A中的缺失值,会同时考虑特征A和其他特征的关系,将其他特征作为自变量,特征A作为因变量,然后建模,来预测特征A中缺失值对应的预测值,通过控制迭代次数,将最后一次迭代的预测值作为填充值。
代码如下
代码语言:javascript复制>>> from sklearn.experimental import enable_iterative_imputer
>>> from sklearn.impute import IterativeImputer
>>> imp = IterativeImputer(max_iter=10, random_state=0)
>>> X = np.array([[np.nan, 2], [6, np.nan], [np.nan, 6]])
>>> X
array([[nan, 2.],
[ 6., nan],
[nan, 6.]])
>>> imp.fit_transform(X)
array([[6., 2.],
[6., 4.],
[6., 6.]])
这种方式非常灵活,在拟合的时候可以选择多种模型,以决策树回归模型为例,代码如下
代码语言:javascript复制>>> from sklearn.tree import DecisionTreeRegressor
>>> imp = IterativeImputer(DecisionTreeRegressor(), max_iter=10, random_state=0)
3. KNN填充
K近邻填充,首先根据欧几里得距离计算与缺失值样本距离最近的K个样本,计算的时候只考虑非缺失值对应的维度,然后用这K个样本对应维度的均值来填充缺失值,代码如下
代码语言:javascript复制>>> from sklearn.impute import KNNImputer
>>> X = np.array([[1, 2, np.nan], [3, 4, 3], [np.nan, 6, 5], [8, 8, 7]])
>>> X
array([[ 1., 2., nan],
[ 3., 4., 3.],
[nan, 6., 5.],
[ 8., 8., 7.]])
>>> imputer = KNNImputer(n_neighbors=2, weights="uniform")
>>> imputer.fit_transform(X)
array([[1. , 2. , 4. ],
[3. , 4. , 3. ],
[5.5, 6. , 5. ],
[8. , 8. , 7. ]])
对于第一列第三行的nan,首先计算该样本距离最近的两个样本,分别为第二行和第四行的样本,然后取3和8的均值,即5.5进行填充;接下来填充第一行第三列的难,计算最近的两个样本,分别是第2行和第3行,所以用3和5的均值,4进行填充。
在实际分析中,缺失值填充的算法还有很多,但是在scikit-learn中,主要就是集成了这3种填充方法。