前言:
随机森林填补缺失值的优点:
(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")
欢迎大家在评论区指正错误,我们共同进步!!