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")

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

### 随机森林用于缺失数据插补及设置阈值的训练示例 随机森林是一种强大的机器学习算法,可以用来处理分类回归问题。它也可以扩展到解决缺失数据插补的任务中。以下是基于 Python 的实现方法。 #### 使用 Scikit-Learn 实现随机森林进行缺失数据插补 Scikit-learn 提供了一个名为 `IterativeImputer` 的工具,它可以利用各种估计器(包括随机森林)来完成迭代式的缺失值填充过程[^4]: ```python from sklearn.experimental import enable_iterative_imputer # noqa from sklearn.impute import IterativeImputer from sklearn.ensemble import RandomForestRegressor # 创建随机森林回归模型实例 rf_regressor = RandomForestRegressor(n_estimators=100) # 初始化 IterativeImputer 并指定使用随机森林作为估算器 imputer = IterativeImputer(estimator=rf_regressor, max_iter=10, random_state=0) # 假设 X 是具有缺失值数据矩阵 X_with_missing_values = [[np.nan, 2], [6, np.nan], [7, 6]] # 对数据执行插补操作 X_imputed = imputer.fit_transform(X_with_missing_values) print(X_imputed) ``` 上述代码片段展示了如何通过 `RandomForestRegressor` 来填补数值型特征中的缺失值。这里的关键在于将随机森林作为核心估算器传递给 `IterativeImputer`,从而允许其逐步逼近最佳可能的填充值[^4]。 #### 设置阈值以控制随机森林的行为 在构建随机森林时,可以通过调整超参数来间接影响决策树的选择标准以及最终预测的质量。例如,在某些情况下,您希望限制单棵树的最大深度或者最小样本分割数以防止过拟合;而在其他场景下,则可能需要设定特定的概率阈值来进行二元分类判断。下面是一个简单的例子说明如何配置这些选项并应用自定义概率阈值: ```python import numpy as np from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier # 构造模拟数据集 X, y = make_classification( n_samples=1000, n_features=20, n_informative=2, n_redundant=10, flip_y=0.3, class_sep=0.5, weights=[0.7], random_state=42 ) # 划分训练集与测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42) # 定义随机森林分类器及其参数 clf = RandomForestClassifier( n_estimators=100, criterion='gini', max_depth=None, min_samples_split=2, min_samples_leaf=1, bootstrap=True, oob_score=False, warm_start=False, class_weight="balanced", random_state=42 ) # 训练模型 clf.fit(X_train, y_train) # 获取预测概率 y_proba = clf.predict_proba(X_test)[:, 1] # 自定义阈值 (e.g., 0.6 instead of default 0.5) threshold = 0.6 y_pred_custom_threshold = (y_proba >= threshold).astype(int) # 输出结果对比 print(f"Default Threshold Predictions:\n{clf.predict(X_test)}\n") print(f"Custom ({threshold}) Threshold Predictions:\n{y_pred_custom_threshold}") ``` 此部分演示了如何修改默认行为并通过引入新的逻辑条件改变原始输出标签分配方式。值得注意的是,当涉及到不平衡类别分布等问题时,这种方法尤其有用[^5]。 --- #### 关于混淆矩阵可视化 如果您还关心评估指标的表现形式之一——即绘制带有标签标注功能的混淆矩阵图谱的话,那么可以参考如下链接所提供的解决方案[^2]: ```python import matplotlib.pyplot as plt import seaborn as sns from sklearn.metrics import confusion_matrix def plot_confusion_matrix(y_true, y_pred, classes): cm = confusion_matrix(y_true, y_pred) fig, ax = plt.subplots(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False, square=True, xticklabels=classes, yticklabels=classes) ax.set_xlabel('Predicted Labels') ax.set_ylabel('True Labels') ax.set_title('Confusion Matrix') plot_confusion_matrix(y_test, y_pred_custom_threshold, ['Class_0', 'Class_1']) plt.show() ``` 这段脚本能够帮助直观理解不同类别的实际匹配情况,并进一步优化您的建模流程。 ---
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YinHeCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值