我正在处理一个包含混合类别和数值变量的数据集。由于数据缺失严重,我希望通过分类器进行一些数据填补。我目前使用的是fast_knn
来自impyute.imputation.cs
。 fast_knn
是一个易于使用的函数,它使用kNN模型填补缺失值。
我的期望是将一个包含类别变量的独热编码的numpy
数组传递给fast_knn
,对于缺失的值使用np.nan
代替,同时混合了来自数值属性的数据(对于缺失的值同样使用np.nan
代替)。
难点在于确保在将类别数据转换为独热编码后,缺失值依然显而易见。如何将类别数据转换为独热编码,使得缺失值变为np.nan
(而不是一个独热编码)? 这个问题已经困扰我一段时间了——我原以为scikit
中的OneHotEncoder
会为缺失值设置为0填充的数组,但我不认为这是正确的。
我想使用一个临时示例。假设我有一个包含三个特征的数据集,两个类别特征和一个数值特征。以下是我希望的最终结构示例。前两个特征是类别特征,第三个是数值特征:
#np.nan用于任何缺失值。 [[[0, 0], [0, 1], [1, 0], [1, 1], np.nan],[[0, 0, 0], [0, 0, 1], [1, 0, 1], [1, 1, 1], np.nan] #假设这个类别有8个可能的值。 [1, 3, np.nan, 3, 5]]
fast_knn
会在np.nan
出现的地方进行填补。
希望我的问题清晰明了。请注意,类别子集相当大——145000行x5列。最好不要进行计算量大的操作。我希望找到一种技术,除了将缺失值指定为类别属性可以采用的另一种值,然后遍历独热编码将其改回np.nan
之外的技术。
回答:
1. 独热编码器(不支持未知值的np.nan)
如果你想使用独热编码方法,OneHotEncoder
确实会为未知值设置为零数组,例如考虑以下情况
from sklearn.preprocessing import OneHotEncoderimport numpy as npimport pandas as pdenc = OneHotEncoder(handle_unknown='ignore', sparse=False)s = pd.Series(list('abca'))enc.fit(s.values.reshape(-1, 1))t = enc.transform(np.array(['a', 'c', 'Other', 'b', 'Another']).reshape(-1, 1))t>>>array([[1., 0., 0.], [0., 0., 1.], [0., 0., 0.], [0., 1., 0.], [0., 0., 0.]])
未知类别Other
和Another
是零数组。要替换t
中的所有零数组
zero_cond = (t == 0).all(axis=1)t[zero_cond] = np.nant>>> array([[ 1., 0., 0.], [ 0., 0., 1.], [nan, nan, nan], [ 0., 1., 0.], [nan, nan, nan]])
现在你可以将其传递给填补器。
2. 序数编码器(未知值可以设置为np.nan)
处理你的类别变量的另一个选项是设置Nan
为未知变量的OrdinalEncoder(自scikit-learn版本0.24起)
from sklearn.preprocessing import OrdinalEncoderenc = OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=np.nan)enc.fit(s.values.reshape(-1, 1))enc.transform(np.array(['a', 'c', 'Other', 'b', 'Another']).reshape(-1, 1))>>>array([[ 0.], [ 2.], [nan], [ 1.], [nan]])