Python利用随机森林对数据的缺失值进行填充的教程(实例附完整代码)

前言:

随机森林填补缺失值的优点:

(1)随机森林填补通过构造多棵决策树对缺失值进行填补,使填补的数据具有随机性和不确定性,更能反映出这些未知数据的真实分布;
(2)由于在构造决策树过程中,每个分支节点选用随机的部分特征而不是全部特征,所以能很好的应用到高维数据的填补;
(3)随机森林算法本身就具有很好的分类精度,从而也更进一步确保了得到的填补值的准确性和可靠性。

废话不多说,直接上python代码:

首先导入需要的包:

# 准备需要的包
import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestRegressor

导入原始数据:

data = pd.read_excel(r"C:\Users\xw\Desktop\预测数据.xlsx")# 导入原始数据
target = data['车辆 id']
# 这里的‘车辆 id’是指没有数据缺失的那一列的名称,选取一列即可
# 如果每一列的数据都缺失了,可以再创建一列都是1的完整数据并填写名称
features = data.iloc[:,1:-1]
#注意这里没有我没有取最后一列,可根据自己的情况改动

进行随机森林预测(这段代码可不用改动):

X_full, y_full = features,target
n_samples = X_full.shape[0] # 样本
n_features = X_full.shape[1] # 特征
print(n_samples)
print(n_features)

#首先确定我们希望放入的缺失值数据的比例,在这里我假设是50%,可以自己改动
rng = np.random.RandomState(0)
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features *missing_rate))
#np.floor  向下取整
#所有数据要随机遍布在数据集的各行各列当中,而一个确实的数据会需要一盒行索引和一个列索引
#如果能够创造一个数组,就可以利用索引来赋空值

X_missing_reg = X_full.copy()
# 查看缺失情况
missing = X_missing_reg .isna().sum()
missing = pd.DataFrame(data={'特征': missing.index,'缺失值个数':missing.values})
#通过~取反,选取不包含数字0的行
missing = missing[~missing['缺失值个数'].isin([0])]
# 缺失比例
missing['缺失比例'] =  missing['缺失值个数']/X_missing_reg .shape[0]
X_df = X_missing_reg.isnull().sum()
# 得出列名 缺失值最少的列名 到 缺失值最多的列名
colname = X_df[~X_df.isin([0])].sort_values().index.values
# 缺失值从小到大的特征顺序
sortindex = []
for i in colname:
    sortindex.append(X_missing_reg.columns.tolist().index(str(i)))
# 遍历所有的特征,从缺失最少的开始进行填补,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填补下一个特征
for i in sortindex:
    # 构建我们的新特征矩阵和新标签
    df = X_missing_reg  # 充当中间数据集
    fillc = df.iloc[:, i]  # 缺失值最少的特征列
    # 除了第 i 特征列,剩下的特征列+原有的完整标签 = 新的特征矩阵
    df = pd.concat([df.drop(df.columns[i], axis=1), pd.DataFrame(y_full)], axis=1)
    # 在新特征矩阵中,对含有缺失值的列,进行0的填补 ,没循环一次,用0填充的列越来越少
    df_0 = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0).fit_transform(df)
    # 找出训练集和测试集
    # 标签
    Ytrain = fillc[fillc.notnull()]  # 没有缺失的部分,就是 Y_train
    Ytest = fillc[fillc.isnull()]  # 不是需要Ytest的值,而是Ytest的索引
    # 特征矩阵
    Xtrain = df_0[Ytrain.index, :]
    Xtest = df_0[Ytest.index, :]  # 有缺失值的特征情况
    rfc = RandomForestRegressor(n_estimators=100)  # 实例化
    rfc = rfc.fit(Xtrain, Ytrain)  # 训练
    Ypredict = rfc.predict(Xtest)  # 预测结果,就是要填补缺失值的值
    # 将填补好的特征返回到我们的原始的特征矩阵中
    X_missing_reg.loc[X_missing_reg.iloc[:, i].isnull(), X_missing_reg.columns[i]] = Ypredict
# 最后,再次查看缺失值是否全部被替换
missing2 = X_missing_reg.isna().sum()
missing2 = pd.DataFrame(data={'列名': missing2.index, '缺失值个数': missing2.values})
# 通过~取反,选取不包含数字0的行
missing3=missing2[~missing2['缺失值个数'].isin([0])]
print(missing2)
print(missing3)

最后导出完整的数据:

#导出完整的数据
X_missing_reg.to_excel(r"C:\Users\xw\Desktop\完整数据.xlsx")

到这里就完成了!

附上完整代码:

# 准备需要的包
import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestRegressor
data = pd.read_excel(r"C:\Users\xw\Desktop\预测数据.xlsx")# 导入原始数据
target = data['车辆 id']
# 这里的‘车辆 id’是指没有数据缺失的那一列的名称
# 如果每一列的数据都缺失了,可以再创建一列都是1的完整数据并填写名称
features = data.iloc[:,1:-1]
#注意这里没有我没有取最后一列,可根据自己的情况改动

X_full, y_full = features,target
n_samples = X_full.shape[0] # 样本
n_features = X_full.shape[1] # 特征
print(n_samples)
print(n_features)

#首先确定我们希望放入的缺失值数据的比例,在这里我假设是50%,可以自己改动
rng = np.random.RandomState(0)
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features *missing_rate))
#np.floor  向下取整
#所有数据要随机遍布在数据集的各行各列当中,而一个确实的数据会需要一盒行索引和一个列索引
#如果能够创造一个数组,就可以利用索引来赋空值

X_missing_reg = X_full.copy()
# 查看缺失情况
missing = X_missing_reg .isna().sum()
missing = pd.DataFrame(data={'特征': missing.index,'缺失值个数':missing.values})
#通过~取反,选取不包含数字0的行
missing = missing[~missing['缺失值个数'].isin([0])]
# 缺失比例
missing['缺失比例'] =  missing['缺失值个数']/X_missing_reg .shape[0]
X_df = X_missing_reg.isnull().sum()
# 得出列名 缺失值最少的列名 到 缺失值最多的列名
colname = X_df[~X_df.isin([0])].sort_values().index.values
# 缺失值从小到大的特征顺序
sortindex = []
for i in colname:
    sortindex.append(X_missing_reg.columns.tolist().index(str(i)))
# 遍历所有的特征,从缺失最少的开始进行填补,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填补下一个特征
for i in sortindex:
    # 构建我们的新特征矩阵和新标签
    df = X_missing_reg  # 充当中间数据集
    fillc = df.iloc[:, i]  # 缺失值最少的特征列
    # 除了第 i 特征列,剩下的特征列+原有的完整标签 = 新的特征矩阵
    df = pd.concat([df.drop(df.columns[i], axis=1), pd.DataFrame(y_full)], axis=1)
    # 在新特征矩阵中,对含有缺失值的列,进行0的填补 ,没循环一次,用0填充的列越来越少
    df_0 = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0).fit_transform(df)
    # 找出训练集和测试集
    # 标签
    Ytrain = fillc[fillc.notnull()]  # 没有缺失的部分,就是 Y_train
    Ytest = fillc[fillc.isnull()]  # 不是需要Ytest的值,而是Ytest的索引
    # 特征矩阵
    Xtrain = df_0[Ytrain.index, :]
    Xtest = df_0[Ytest.index, :]  # 有缺失值的特征情况
    rfc = RandomForestRegressor(n_estimators=100)  # 实例化
    rfc = rfc.fit(Xtrain, Ytrain)  # 训练
    Ypredict = rfc.predict(Xtest)  # 预测结果,就是要填补缺失值的值
    # 将填补好的特征返回到我们的原始的特征矩阵中
    X_missing_reg.loc[X_missing_reg.iloc[:, i].isnull(), X_missing_reg.columns[i]] = Ypredict
# 最后,再次查看缺失值是否全部被替换
missing2 = X_missing_reg.isna().sum()
missing2 = pd.DataFrame(data={'列名': missing2.index, '缺失值个数': missing2.values})
# 通过~取反,选取不包含数字0的行
missing3=missing2[~missing2['缺失值个数'].isin([0])]
print(missing2)
print(missing3)
#导出完整的数据
X_missing_reg.to_excel(r"C:\Users\xw\Desktop\完整数据.xlsx")

欢迎大家在评论区指正错误,我们共同进步!!

上一篇:右键创建markdown文档


下一篇:python winreg部分封装