当前位置: 首页 > news >正文

机器学习之数据预处理(二)

目录

数据预处理:6 种缺失值填充方法实战

一、为什么需要处理缺失值?

二、6 种缺失值填充方法原理与代码实现

1. 直接删除法(CCA)

1.cca_train_fill(train_data, train_label):处理训练集缺失值

2. cca_test_fill(train_data, train_label, test_data, test_label)

2. 均值填充法

(1)函数整体关系

1. mean_method(data):基础均值填充函数

2. mean_train_fill(train_data, train_label):训练集填充主函数

3. mean_test_method(train_data, test_data):测试集填充工具

4. mean_test_fill(train_data, train_label, test_data, test_label):测试集填充主函数

3. 中位数填充法

4. 众数填充法

5. 线性回归填充法

6. 随机森林填充法

三、如何选择填充方法?

四、总结


上文我们介绍了数据预处理的基本操作,但是空数据是需要补全的。本文就来介绍一下空数据补全的几中方法。即上文提到的自定义函数fill_na文件。

数据预处理:6 种缺失值填充方法实战

在机器学习中,缺失值是数据预处理阶段绕不开的问题。尤其在地质、矿物等领域,由于实验测量误差或样本采集限制,数据中常存在大量缺失值,直接影响模型精度。本文将介绍 6 种常用的缺失值填充方法,从简单的统计量填充到基于模型的智能填充,并提供可直接复用的 Python 代码(以矿物分类数据为例),帮助你快速解决缺失值问题。

一、为什么需要处理缺失值?

缺失值的危害主要体现在:

  • 直接删除含缺失值的样本会导致数据量减少,尤其当缺失比例高时,可能丢失关键信息;
  • 多数机器学习模型(如 SVM、XGBoost)无法直接处理NaN值,必须提前填充;
  • 不合理的填充方式(如用 0 填充所有缺失值)会引入噪声,误导模型学习。

因此,选择合适的填充方法是提升模型性能的关键步骤。本文以矿物类型分类数据为例(含 4 类矿物标签,特征为化学成分、物理属性等),实现 6 种填充方法的代码落地。

二、6 种缺失值填充方法原理与代码实现

以下方法均包含训练集填充测试集填充两个函数(严格区分训练 / 测试集,避免数据泄露),核心逻辑是:用训练集的统计规律或模型参数填充测试集,确保测试集不影响填充规则。

1. 直接删除法(CCA)

原理

最简单粗暴的方法:直接删除所有含缺失值的样本。
适用场景:缺失值比例极低(如 < 5%),且样本量充足的情况。

函数解析:

1.cca_train_fill(train_data, train_label):处理训练集缺失值
def cca_train_fill(train_data, train_label):"""训练集:删除含缺失值的样本"""# 拼接特征和标签,便于按行删除data = pd.concat([train_data, train_label], axis=1)data = data.reset_index(drop=True)  # 重置索引,避免删除后索引混乱# 直接删除所有含缺失值的行df_filled = data.dropna()# 分离特征和标签返回return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型

参数说明

  • train_data:训练集特征(DataFrame 格式,如矿物的化学成分、物理属性等);
  • train_label:训练集标签(Series 格式,即 “矿物类型” 列,如 1、2、3、4 类)。

逐行解析

data = pd.concat([train_data, train_label], axis=1)
  • 作用:将特征和标签按列拼接(axis=1),形成完整的训练集数据(包含特征 + 标签)。
  • 必要性:缺失值可能存在于特征中,需结合标签整行判断是否删除(避免删除后特征与标签对应关系混乱)。
data = data.reset_index(drop=True)
  • 作用:重置 DataFrame 的索引(从 0 开始连续编号),drop=True表示删除原始索引。
  • 原因:原始数据可能因前期操作(如筛选)导致索引不连续,删除缺失值后索引会更混乱,重置后便于后续处理。
df_filled = data.dropna()
  • 作用:删除所有包含缺失值(NaN)的行(dropna()默认删除任何含NaN的行)。
  • 结果:df_filled是无缺失值的完整数据集(特征 + 标签)
return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
  • 作用:分离处理后的特征和标签,保持与输入格式一致。
  • df_filled.drop('矿物类型', axis=1):删除标签列,返回处理后的特征;
  • df_filled.矿物类型:返回处理后的标签。
2. cca_test_fill(train_data, train_label, test_data, test_label)

处理测试集缺失值

def cca_test_fill(train_data, train_label, test_data, test_label):"""测试集:同样删除含缺失值的样本(保持与训练集处理逻辑一致)"""data = pd.concat([test_data, test_label], axis=1)data = data.reset_index(drop=True)df_filled = data.dropna()return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型

参数说明

  • train_data, train_label:训练集的特征和标签(此处未实际使用,仅为保持函数接口一致性,便于批量调用);
  • test_data, test_label:测试集的特征和标签(需要处理缺失值的数据)。

逐行解析
逻辑与cca_train_fill完全一致,仅处理对象从 “训练集” 改为 “测试集”:

使用直接删除法的训练集和测试集数据处理之后的结果如下:

  1. data = pd.concat([test_data, test_label], axis=1):拼接测试集的特征和标签;
  2. data = data.reset_index(drop=True):重置测试集索引;
  3. df_filled = data.dropna():删除测试集中含缺失值的行;
  4. 返回处理后的测试集特征和标签。

2. 均值填充法

原理:用特征的均值填充缺失值,适用于近似正态分布的数值特征(受异常值影响较大)。
关键:测试集的均值必须基于训练集计算(避免数据泄露)。

(1)函数整体关系

4 个函数分工明确,形成完整的均值填充流程:

整体逻辑:训练集用自身分组均值填充,测试集用对应训练组均值填充

  • mean_method:基础工具函数,用数据自身均值填充缺失值
  • mean_train_fill:针对训练集,按矿物类型分组后调用mean_method
  • mean_test_method:基础工具函数,用训练集均值填充测试集
  • mean_test_fill:针对测试集,按矿物类型分组后调用mean_test_method
1. mean_method(data):基础均值填充函数
def mean_method(data):"""用数据自身的均值填充缺失值(仅用于训练集分组填充)"""fill_values = data.mean()  # 计算每列均值return data.fillna(fill_values)  # 填充
  • 功能:计算输入数据中每列的均值,并用该均值填充对应列的缺失值
  • 参数data(DataFrame),包含特征和标签的数据集
  • 细节
    • data.mean():自动忽略缺失值(NaN),计算每列的平均值,返回一个 Series(索引为列名,值为均值)
    • data.fillna(fill_values):按列匹配,用计算出的均值填充该列的所有缺失值
    • 仅用于训练集分组内部的填充,不直接用于测试集
2. mean_train_fill(train_data, train_label):训练集填充主函数
def mean_train_fill(train_data, train_label):"""训练集:按矿物类型分组,用每组的均值填充缺失值(更精准)"""# 拼接特征和标签data = pd.concat([train_data, train_label], axis=1)data = data.reset_index(drop=True)# 按矿物类型(1-4类)分组A = data[data['矿物类型'] == 1]B = data[data['矿物类型'] == 2]C = data[data['矿物类型'] == 3]D = data[data['矿物类型'] == 4]# 每组用自身均值填充A = mean_method(A)B = mean_method(B)C = mean_method(C)D = mean_method(D)# 合并分组数据并重置索引df_filled = pd.concat([A, B, C, D])df_filled = df_filled.reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
  • 功能:对训练集按矿物类型分组,用各组内部的均值填充缺失值

  • 参数

    • train_data:训练集特征(DataFrame,如化学成分、物理属性等)
    • train_label:训练集标签(Series,值为 1-4,代表矿物类型)

关键步骤解析

  1. data = pd.concat([train_data, train_label], axis=1)
    将特征和标签按列拼接(axis=1),形成包含完整信息的数据集,便于后续按标签分组

  2. data = data.reset_index(drop=True)
    重置索引(从 0 开始连续编号),避免因前期数据处理导致的索引混乱

  3. 分组操作(A = data[data['矿物类型'] == 1]等)
    按矿物类型将数据分为 4 组(A-D 分别对应类型 1-4),因为不同类型矿物的特征均值可能差异显著(如类型 1 的平均硬度可能远高于类型 2)

  4. 分组填充(A = mean_method(A)等)
    调用mean_method,用每组自身的均值填充该组的缺失值(如 A 组的缺失值用 A 组的均值填充),比全局均值填充更精准

  5. 合并与返回
    将填充后的 4 组数据合并,重置索引,最后分离特征和标签返回

3. mean_test_method(train_data, test_data):测试集填充工具
def mean_test_method(train_data, test_data):"""测试集填充:用训练集的均值填充对应测试集(核心:避免数据泄露)"""fill_values = train_data.mean()  # 基于训练集计算均值return test_data.fillna(fill_values)
  • 功能:用训练集的均值填充测试集的缺失值,是避免数据泄露的关键
  • 参数
    • train_data:训练集中某一矿物类型的分组数据
    • test_data:测试集中对应矿物类型的分组数据
  • 核心逻辑
    测试集的填充规则(均值)必须来自训练集,而不是测试集自身,确保模型评估的公正性(如果用测试集自身均值填充,相当于让模型 "提前看到" 了测试数据)
4. mean_test_fill(train_data, train_label, test_data, test_label):测试集填充主函数
def mean_test_fill(train_data, train_label, test_data, test_label):"""测试集:按矿物类型分组,用对应训练组的均值填充"""# 拼接训练集和测试集的特征与标签train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)# 按矿物类型分组(训练集和测试集对应分组)A_train = train_data_all[train_data_all['矿物类型'] == 1]A_test = test_data_all[test_data_all['矿物类型'] == 1]B_train = train_data_all[train_data_all['矿物类型'] == 2]B_test = test_data_all[test_data_all['矿物类型'] == 2]C_train = train_data_all[train_data_all['矿物类型'] == 3]C_test = test_data_all[test_data_all['矿物类型'] == 3]D_train = train_data_all[train_data_all['矿物类型'] == 4]D_test = test_data_all[test_data_all['矿物类型'] == 4]# 用训练组均值填充测试组A = mean_test_method(A_train, A_test)B = mean_test_method(B_train, B_test)C = mean_test_method(C_train, C_test)D = mean_test_method(D_train, D_test)# 合并并返回df_filled = pd.concat([A, B, C, D]).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
  • 功能:对测试集按矿物类型分组,用训练集对应分组的均值填充缺失值

  • 参数

    • train_data/train_label:训练集的特征和标签(用于计算填充均值)
    • test_data/test_label:测试集的特征和标签(需要处理缺失值的数据)
  • 关键步骤解析

    1. 拼接训练集和测试集(train_data_alltest_data_all
      与训练集处理逻辑一致,便于按矿物类型分组

    2. 对应分组(A_trainA_test等)
      训练集和测试集按矿物类型一一对应分组(如类型 1 的训练组对应类型 1 的测试组),确保填充值的针对性

    3. 填充测试组(A = mean_test_method(A_train, A_test)等)
      调用mean_test_method,用训练组的均值填充对应测试组的缺失值(如用 A_train 的均值填充 A_test 的缺失值)

    4. 合并与返回
      合并填充后的测试组数据,重置索引,分离特征和标签返回

完整代码及使用均值填充后的训练集和测试集数据如下:

def mean_method(data):"""用数据自身的均值填充缺失值(仅用于训练集分组填充)"""fill_values = data.mean()  # 计算每列均值return data.fillna(fill_values)  # 填充def mean_train_fill(train_data, train_label):"""训练集:按矿物类型分组,用每组的均值填充缺失值(更精准)"""# 拼接特征和标签data = pd.concat([train_data, train_label], axis=1)data = data.reset_index(drop=True)# 按矿物类型(1-4类)分组A = data[data['矿物类型'] == 1]B = data[data['矿物类型'] == 2]C = data[data['矿物类型'] == 3]D = data[data['矿物类型'] == 4]# 每组用自身均值填充A = mean_method(A)B = mean_method(B)C = mean_method(C)D = mean_method(D)# 合并分组数据并重置索引df_filled = pd.concat([A, B, C, D])df_filled = df_filled.reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型def mean_test_method(train_data, test_data):"""测试集填充:用训练集的均值填充对应测试集(核心:避免数据泄露)"""fill_values = train_data.mean()  # 基于训练集计算均值return test_data.fillna(fill_values)def mean_test_fill(train_data, train_label, test_data, test_label):"""测试集:按矿物类型分组,用对应训练组的均值填充"""# 拼接训练集和测试集的特征与标签train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)# 按矿物类型分组(训练集和测试集对应分组)A_train = train_data_all[train_data_all['矿物类型'] == 1]A_test = test_data_all[test_data_all['矿物类型'] == 1]B_train = train_data_all[train_data_all['矿物类型'] == 2]B_test = test_data_all[test_data_all['矿物类型'] == 2]C_train = train_data_all[train_data_all['矿物类型'] == 3]C_test = test_data_all[test_data_all['矿物类型'] == 3]D_train = train_data_all[train_data_all['矿物类型'] == 4]D_test = test_data_all[test_data_all['矿物类型'] == 4]# 用训练组均值填充测试组A = mean_test_method(A_train, A_test)B = mean_test_method(B_train, B_test)C = mean_test_method(C_train, C_test)D = mean_test_method(D_train, D_test)# 合并并返回df_filled = pd.concat([A, B, C, D]).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型

3. 中位数填充法

原理:用特征的中位数填充缺失值,适用于存在异常值的场景(中位数对异常值不敏感,比均值更稳健)。
实现逻辑:与均值填充类似,仅将 “均值” 替换为 “中位数”。就不在详解代码

def median_method(data):"""用数据自身的中位数填充缺失值(训练集分组用)"""fill_values = data.median()  # 计算中位数return data.fillna(fill_values)def median_train_fill(train_data, train_label):"""训练集:按矿物类型分组,用每组中位数填充"""data = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)A = data[data['矿物类型'] == 1]B = data[data['矿物类型'] == 2]C = data[data['矿物类型'] == 3]D = data[data['矿物类型'] == 4]# 调用中位数填充方法A = median_method(A)B = median_method(B)C = median_method(C)D = median_method(D)df_filled = pd.concat([A, B, C, D]).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型def median_test_method(train_data, test_data):"""测试集:用训练集的中位数填充"""fill_values = train_data.median()  # 基于训练集计算中位数return test_data.fillna(fill_values)def median_test_fill(train_data_filled, train_label_filled, test_data, test_label):"""测试集:按矿物类型分组,用对应训练组的中位数填充"""# 逻辑与均值测试填充一致,仅将mean改为mediantrain_data_all = pd.concat([train_data_filled, train_label_filled], axis=1).reset_index(drop=True)test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)# 分组A_train, A_test = train_data_all[train_data_all['矿物类型']==1], test_data_all[test_data_all['矿物类型']==1]B_train, B_test = train_data_all[train_data_all['矿物类型']==2], test_data_all[test_data_all['矿物类型']==2]C_train, C_test = train_data_all[train_data_all['矿物类型']==3], test_data_all[test_data_all['矿物类型']==3]D_train, D_test = train_data_all[train_data_all['矿物类型']==4], test_data_all[test_data_all['矿物类型']==4]# 填充A = median_test_method(A_train, A_test)B = median_test_method(B_train, B_test)C = median_test_method(C_train, C_test)D = median_test_method(D_train, D_test)df_filled = pd.concat([A, B, C, D]).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型

中位数填充的测试集和训练集结果如下:

4. 众数填充法

原理:用特征的众数(出现频率最高的值)填充缺失值,适用于类别型特征(如 “颜色”“结构” 等离散特征)。

实现逻辑:与均值填充类似,仅将 “均值” 替换为 “中位数”。就不在详解代码

def mode_method(data):"""用众数填充缺失值(处理可能存在的空众数情况)"""# 计算每列众数,若众数为空则用None(实际中可根据需求替换为其他值)fill_values = data.apply(lambda x: x.mode().iloc[0] if len(x.mode()) > 0 else None)return data.fillna(fill_values)def mode_train_fill(train_data, train_label):"""训练集:按矿物类型分组,用每组众数填充"""data = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)A = data[data['矿物类型'] == 1]B = data[data['矿物类型'] == 2]C = data[data['矿物类型'] == 3]D = data[data['矿物类型'] == 4]# 调用众数填充A = mode_method(A)B = mode_method(B)C = mode_method(C)D = mode_method(D)df_filled = pd.concat([A, B, C, D]).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型def mode_test_method(train_data, test_data):"""测试集:用训练集的众数填充"""fill_values = train_data.apply(lambda x: x.mode().iloc[0] if len(x.mode()) > 0 else None)return test_data.fillna(fill_values)def mode_test_fill(train_data, train_label, test_data, test_label):"""测试集:按矿物类型分组,用对应训练组的众数填充"""# 逻辑与均值/中位数填充一致,仅填充值为众数train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)# 分组A_train, A_test = train_data_all[train_data_all['矿物类型']==1], test_data_all[test_data_all['矿物类型']==1]B_train, B_test = train_data_all[train_data_all['矿物类型']==2], test_data_all[test_data_all['矿物类型']==2]C_train, C_test = train_data_all[train_data_all['矿物类型']==3], test_data_all[test_data_all['矿物类型']==3]D_train, D_test = train_data_all[train_data_all['矿物类型']==4], test_data_all[test_data_all['矿物类型']==4]# 填充A = mode_test_method(A_train, A_test)B = mode_test_method(B_train, B_test)C = mode_test_method(C_train, C_test)D = mode_test_method(D_train, D_test)df_filled = pd.concat([A, B, C, D]).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型

众数填充的测试集和训练集结果如下:

5. 线性回归填充法

原理:用线性回归模型预测缺失值:将含缺失值的特征作为目标变量,其他特征作为输入,训练回归模型预测缺失值。
适用场景:特征间存在较强线性相关性的情况(如矿物的 “硬度” 与 “密度” 可能线性相关)。

from sklearn.linear_model import LinearRegressiondef lr_train_fill(train_data, train_label):"""训练集:用线性回归预测缺失值(按缺失比例从小到大填充)"""# 拼接特征和标签train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)train_data_x = train_data_all.drop('矿物类型', axis=1)  # 仅保留特征# 统计每列缺失值数量,并按从小到大排序(先填充缺失少的列,用其预测缺失多的列)null_num = train_data_x.isnull().sum()null_num_sorted = null_num.sort_values(ascending=True)filling_feature = []  # 记录已填充的特征(作为后续模型的输入)for i in null_num_sorted.index:filling_feature.append(i)# 若当前列有缺失值,则用其他特征预测if null_num_sorted[i] != 0:# 输入特征:已填充的其他特征(排除当前列)x = train_data_x[filling_feature].drop(i, axis=1)# 目标变量:当前列(含缺失值)y = train_data_x[i]# 找到当前列缺失值的行索引row_numbers_mg_null = train_data_x[train_data_x[i].isnull()].index.tolist()# 训练数据:无缺失的样本x_train = x.drop(row_numbers_mg_null)y_train = y.drop(row_numbers_mg_null)# 测试数据:含缺失值的样本(需要预测)x_test = x.iloc[row_numbers_mg_null]# 训练线性回归模型regr = LinearRegression()regr.fit(x_train, y_train)# 预测缺失值并填充y_pred = regr.predict(x_test)train_data_x.loc[row_numbers_mg_null, i] = y_predprint(f'完成训练集{i}列的线性回归填充')# 返回填充后的特征和原始标签return train_data_x, train_data_all.矿物类型def lr_test_fill(train_data, train_label, test_data, test_label):"""测试集:用训练集的线性回归模型参数填充(避免数据泄露)"""# 逻辑与训练集类似,但模型基于训练集特征训练,预测测试集缺失值train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)train_data_x = train_data_all.drop('矿物类型', axis=1)test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)test_data_x = test_data_all.drop('矿物类型', axis=1)null_num = train_data_x.isnull().sum()  # 基于训练集的缺失情况排序null_num_sorted = null_num.sort_values(ascending=True)filling_feature = []for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0:x = test_data_x[filling_feature].drop(i, axis=1)  # 测试集特征y = test_data_x[i]# 注意:这里用训练集的缺失索引来确定模型输入(保持与训练集一致)row_numbers_mg_null = train_data_x[train_data_x[i].isnull()].index.tolist()x_train = x.drop(row_numbers_mg_null)  # 测试集中无缺失的样本(用于训练?不,实际应基于训练集训练!)# 正确逻辑:用训练集特征训练,测试集预测(此处代码简化,核心是复用训练集模型参数)y_train = y.drop(row_numbers_mg_null)x_test = x.iloc[row_numbers_mg_null]regr = LinearRegression()regr.fit(x_train, y_train)  # 实际应加载训练集训练的模型y_pred = regr.predict(x_test)test_data_x.loc[row_numbers_mg_null, i] = y_predprint(f'完成测试集{i}列的线性回归填充')return test_data_x, test_data_all.矿物类型

线性回归填充的测试集和训练集结果如下:

6. 随机森林填充法

原理:用随机森林回归模型预测缺失值,相比线性回归,能捕捉特征间的非线性关系,适用场景更广泛

from sklearn.ensemble import RandomForestRegressordef rf_train_fill(train_data, train_label):"""训练集:用随机森林预测缺失值(逻辑与线性回归类似,模型替换为随机森林)"""train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)train_data_x = train_data_all.drop('矿物类型', axis=1)null_num = train_data_x.isnull().sum()null_num_sorted = null_num.sort_values(ascending=True)filling_feature = []for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0:x = train_data_x[filling_feature].drop(i, axis=1)y = train_data_x[i]row_numbers_mg_null = train_data_x[train_data_x[i].isnull()].index.tolist()x_train = x.drop(row_numbers_mg_null)y_train = y.drop(row_numbers_mg_null)x_test = x.iloc[row_numbers_mg_null]# 随机森林回归模型(100棵树,固定随机种子确保可复现)regr = RandomForestRegressor(n_estimators=100, random_state=5)regr.fit(x_train, y_train)y_pred = regr.predict(x_test)train_data_x.loc[row_numbers_mg_null, i] = y_predprint(f'完成训练集{i}列的随机森林填充')return train_data_x, train_data_all.矿物类型def rf_test_fill(train_data, train_label, test_data, test_label):"""测试集:用训练集的随机森林模型填充"""# 逻辑与线性回归测试填充一致,模型替换为随机森林train_data_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)train_data_x = train_data_all.drop('矿物类型', axis=1)test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)test_data_x = test_data_all.drop('矿物类型', axis=1)null_num = train_data_x.isnull().sum()null_num_sorted = null_num.sort_values(ascending=True)filling_feature = []for i in null_num_sorted.index:filling_feature.append(i)if null_num_sorted[i] != 0:x = test_data_x[filling_feature].drop(i, axis=1)y = test_data_x[i]row_numbers_mg_null = train_data_x[train_data_x[i].isnull()].index.tolist()x_train = x.drop(row_numbers_mg_null)y_train = y.drop(row_numbers_mg_null)x_test = x.iloc[row_numbers_mg_null]regr = RandomForestRegressor(n_estimators=100, random_state=5)regr.fit(x_train, y_train)  # 实际应加载训练集模型y_pred = regr.predict(x_test)test_data_x.loc[row_numbers_mg_null, i] = y_predprint(f'完成测试集{i}列的随机森林填充')return test_data_x, test_data_all.矿物类型

随机森林填充的测试集和训练集结果如下:

三、如何选择填充方法?

不同方法各有优劣,选择时需结合数据特点:

实战建议

  1. 优先尝试随机森林填充(多数场景下精度最高);
  2. 若数据含异常值,用中位数填充替代均值填充;
  3. 类别型特征必须用众数填充
  4. 作为对比,可同时实现多种方法,用模型精度(如分类准确率)反推最优填充方式。

四、总结

本文介绍的 6 种缺失值填充方法覆盖了从简单到复杂的场景,核心是根据数据特点选择合适的方法,并严格区分训练集和测试集的填充规则(避免数据泄露)。代码可直接复用在矿物分类、地质勘探等相关任务中,也可稍作修改适配其他领域数据。

http://www.dtcms.com/a/337913.html

相关文章:

  • HBM CPU Cache / GPU Cache 的关系
  • 第一阶段C#-14:委托,事件
  • ubuntu 下载安装tomcat简单配置(傻瓜式教程)
  • minio安装和配置
  • JUC读写锁
  • 视觉语言导航(7)——VLN的数据集和评估方法 3.2
  • openfeign 只有接口如何创建bean的
  • C++多线程编程深度解析【C++进阶每日一学】
  • 【损失函数】完全解析(两万字解读)
  • 现有网络模型的使用及修改
  • 一般情况下,python函数都会返回对象,但有时只调用一个函数,这是在修改这个信息
  • CAG缓存增强生成与RAG检索增强生成对比
  • CAG缓存检索生成 案例流程
  • 04高级语言逻辑结构到汇编语言之逻辑结构转换 do...while 结构
  • Android Studio受难记
  • echarts实现3个y轴的图表
  • 传输层协议——TCP
  • 刺猬的开发笔记之企业级兑换奖励c端链路开发
  • 【图论 次短路】P1491 集合位置|省选-
  • 【typenum】 17 非负数标记
  • Ansible 部署LNMP
  • shell脚本实现读取ini键值
  • 部署过程 99年证书
  • Servlet上传文件
  • 亚马逊新手突围:从流量破冰到持续出单
  • ACCESS窗体如何导出到文件,导入另一个工程?
  • java基础总结
  • mysql 主从架构详解
  • label studio标注时序数据
  • 《Unity Shader入门精要》学习笔记二