算法思路
原始的问题可能是:一个X(包含x1,x2,缺失x,x3…) =====预测=> y
模型填充缺失值:使用:x1,x2,x3… y =====预测=> 缺失x
所以我们把缺失值作为预测任务的label,把原始的预测y作为特征的一部分,反向推出缺失值
示例代码
import pandas as pd
import numpy as np
def get_dataset():
"""得到数据
:return data_x:有缺失值的数据
:return true_value:缺失数据的原始真实值
:return data_y:原问题中待预测的label
"""
import copy
from sklearn.datasets import make_classification
data_x, data_y = make_classification(n_samples=100, n_classes=4, n_features=6, n_informative=4,
random_state=0) # 6个特征
data_x = pd.DataFrame(data_x)
data_x.columns = ['x1', 'x2', 'x3', 'x4', 'x5', 'miss_line']
true_data = copy.deepcopy(data_x)
# 在miss_line这一列删除20%的数据
drop_index = data_x.sample(frac=0.2).index
data_x.loc[drop_index, "miss_line"] = np.nan
true_value = true_data.loc[drop_index, 'miss_line'] # 空值的真实值
return data_x, true_value, data_y
def train_model(train_x, train_y, test_x): # 训练模型
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor(n_estimators=100)
rfr = rfr.fit(train_x, train_y)
predict_y = rfr.predict(test_x)
return predict_y
def fill_missing_rf(x_data: pd.DataFrame, y_data=None, fill_column_name: str = None):
"""
使用随机森林填补一个特征的缺失值的函数
:param x_data 带缺失值的特征矩阵
:param y_data 标签列,可以为空
:param fill_column_name 缺失列的名称
"""
# 将实际用来预测的label加入x中,作为特征预测缺失列
if y_data is not None:
x_data = pd.concat([x_data, pd.DataFrame(y_data)], axis=1)
# 得到训练集(未缺失数据)与测试集(缺失数据)
train_df = x_data[x_data[fill_column_name].notnull()]
test_df = x_data[x_data[fill_column_name].isnull()]
# 得到训练集与测试集
train_x = train_df.drop([fill_column_name], axis=1)
train_y = train_df.loc[:, fill_column_name]
test_x = test_df.drop([fill_column_name], axis=1)
test_y = test_df.loc[:, fill_column_name]
# 找出我们的训练集和测试集
pre_y = train_model(train_x, train_y, test_x)
pre_y = pd.Series(pre_y, index=test_y.index)
return pre_y
if __name__ == '__main__':
value_x, true_value_x, value_y = get_dataset()
fill_value = fill_missing_rf(value_x, value_y, "miss_line")
value_x['miss_line'].update(fill_value) # 用预测的结果填充到原始的缺失值