参考: https://github.com/YC-Coder-Chen/feature-engineering-handbook
单变量特征插补
假设第 i 列中有缺失值,那么我们将用常数或第 i 列的统计数据(平均值、中值或众数)对其进行估算
from sklearn.impute import SimpleImputer
test_set = X[0:10,0].copy() # 选择前十个变量作为测试集,无缺失值
# 返回 array([8.3252, 8.3014, 7.2574, 5.6431, 3.8462, 4.0368, 3.6591, 3.12, 2.0804, 3.6912])
# 手动生成缺失值
test_set[3] = np.nan
test_set[6] = np.nan
# 现在测试集变成如下:
# array([8.3252, 8.3014, 7.2574, nan, 3.8462, 4.0368, nan, 3.12 ,2.0804, 3.6912])
# 生成训练集,选择其余的样本作为训练集并手动生成缺失值
train_set = X[10:,0].copy()
train_set[3] = np.nan
train_set[6] = np.nan
imputer = SimpleImputer(missing_values=np.nan, strategy='mean') # 使用样本均值来填补缺失值
# 其余的填补方法: 'mean', 'median', 'most_frequent', 'constant'
imputer.fit(train_set.reshape(-1,1)) # 在训练集上训练
# 转换填补训练集与测试集
imputed_train = imputer.transform(train_set.reshape(-1,1)).reshape(-1) # 转换训练集
imputed_test = imputer.transform(test_set.reshape(-1,1)).reshape(-1) # 转换测试集
# 以测试集结果为例:
# imputed_test = array([8.3252 , 8.3014 , 7.2574 , 3.87023658, 3.8462 ,
# 4.0368 , 3.87023658, 3.12 , 2.0804 , 3.6912 ])
# 所有的缺失值将会被 3.87023658填补
# 3.87023658 = np.nanmean(train_set)
# 3.87023658 恰恰是训练集中除去缺失值后的均值
多元特征插补
多元特征插补利用整个数据集的信息来估计和插补缺失值。
在每一步中,一个包含缺失值的特征列被指定为输出 y,其他特征列被视为输入 X。一个回归器在X上被训练然后用以预测y中的缺失值。
1. 使用线性模型预测填补
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.linear_model import BayesianRidge
test_set = X[0:10,:].copy() # 无缺失值,选择所有变量的前十个样本作为测试集
# 第一个变量为
# array([8.3252, 8.3014, 7.2574, 5.6431, 3.8462, 4.0368, 3.6591, 3.12, 2.0804, 3.6912])
# 手动生成一些缺失值
test_set[3,0] = np.nan
test_set[6,0] = np.nan
test_set[3,1] = np.nan
# 现在第一个变量将变为
# array([8.3252, 8.3014, 7.2574, nan, 3.8462, 4.0368, nan, 3.12 ,2.0804, 3.6912])
# 生成训练集,选择其余的样本作为训练集并手动生成缺失值
train_set = X[10:,:].copy()
train_set[3,0] = np.nan
train_set[6,0] = np.nan
train_set[3,1] = np.nan
impute_estimator = BayesianRidge()
imputer = IterativeImputer(max_iter = 10,
random_state = 0,
estimator = impute_estimator)
imputer.fit(train_set) # 在训练集上训练
# 转换填补训练集与测试集
imputed_train = imputer.transform(train_set) # 转换训练集
imputed_test = imputer.transform(test_set)# 转换测试集
result = imputer.transform(test_set)[:,0] # 仅选择第一个变量来展示结果
# result = array([8.3252 , 8.3014 , 7.2574 , 4.6237195 , 3.8462 ,
# 4.0368 , 4.00258149, 3.12 , 2.0804 , 3.6912 ]) # 可见缺失值已被填补
2. 使用树模型预测填补
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.ensemble import ExtraTreesRegressor
test_set = X[0:10,:].copy() # 无缺失值,选择所有变量的前十个样本作为测试集
# 第一个变量为
# array([8.3252, 8.3014, 7.2574, 5.6431, 3.8462, 4.0368, 3.6591, 3.12, 2.0804, 3.6912])
# 手动生成一些缺失值
test_set[3,0] = np.nan
test_set[6,0] = np.nan
test_set[3,1] = np.nan
# 现在第一个变量将变为
# array([8.3252, 8.3014, 7.2574, nan, 3.8462, 4.0368, nan, 3.12 ,2.0804, 3.6912])
# 生成训练集,选择其余的样本作为训练集并手动生成缺失值
train_set = X[10:,:].copy()
train_set[3,0] = np.nan
train_set[6,0] = np.nan
train_set[3,1] = np.nan
impute_estimator = ExtraTreesRegressor(n_estimators=10, random_state=0)
imputer = IterativeImputer(max_iter = 10,
random_state = 0,
estimator = impute_estimator)
imputer.fit(train_set) # 在训练集上训练
# 转换填补训练集与测试集
imputed_train = imputer.transform(train_set) # 转换训练集
imputed_test = imputer.transform(test_set)# 转换测试集
result = imputer.transform(test_set)[:,0] # 仅选择第一个变量来展示结果
# result = array([8.3252 , 8.3014 , 7.2574 , 4.63813, 3.8462 , 4.0368 , 3.24721,
# 3.12 , 2.0804 , 3.6912 ]) # 可见缺失值已被填补
3. 使用 K 近邻(KNN)预测填补
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.neighbors import KNeighborsRegressor
test_set = X[0:10,:].copy() # 无缺失值,选择所有变量的前十个样本作为测试集
# 第一个变量为
# array([8.3252, 8.3014, 7.2574, 5.6431, 3.8462, 4.0368, 3.6591, 3.12, 2.0804, 3.6912])
# 手动生成一些缺失值
test_set[3,0] = np.nan
test_set[6,0] = np.nan
test_set[3,1] = np.nan
# 现在第一个变量将变为
# array([8.3252, 8.3014, 7.2574, nan, 3.8462, 4.0368, nan, 3.12 ,2.0804, 3.6912])
# 生成训练集,选择其余的样本作为训练集并手动生成缺失值
train_set = X[10:,:].copy()
train_set[3,0] = np.nan
train_set[6,0] = np.nan
train_set[3,1] = np.nan
impute_estimator = KNeighborsRegressor(n_neighbors=10,
p = 1) # 设置 p=1 使用曼哈顿距离
# 相比于平方差距离,曼哈顿距离对异常值没有那么敏感
imputer = IterativeImputer(max_iter = 10,
random_state = 0,
estimator = impute_estimator)
imputer.fit(train_set) # 在训练集上训练
# 转换填补训练集与测试集
imputed_train = imputer.transform(train_set) # 转换训练集
imputed_test = imputer.transform(test_set)# 转换测试集
result = imputer.transform(test_set)[:,0] # 仅选择第一个变量来展示结果
# result = array([8.3252, 8.3014, 7.2574, 3.6978, 3.8462, 4.0368, 4.052 , 3.12 ,
# 2.0804, 3.6912]) # 可见缺失值已被填补