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

运用4种填充方法补充缺失数据的案例

代码实现:

import pandas as pd
import fill_data
# 导入数据
data = pd.read_excel('矿物数据.xls')
# 删除结果为E的行
data = data[data['矿物类型']!='E']
# 提取X和y值
X_whole = data.drop('序号',axis=1).drop('矿物类型',axis=1)
y_whole = data['矿物类型']
# 将结果中的中文字符改为英文字符
label_dict = {'A':0,'B':1,'C':2,'D':3}
xg_label = [label_dict[label] for label in y_whole]
y_whole = pd.Series(xg_label,name="矿物类型")
# 处理特征中不合法的数值,并改成nan
for column_name in X_whole.columns:X_whole[column_name] = pd.to_numeric(X_whole[column_name], errors='coerce')
# (z标准化)
from sklearn.preprocessing import StandardScaler
sds = StandardScaler()
X_whole_z = sds.fit_transform(X_whole)
X_whole = pd.DataFrame(X_whole_z,columns=X_whole.columns)
# 切分测试集和训练集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(X_whole,y_whole,test_size=0.3,random_state=2000)
'''6中填充方法'''
# 1、 删除空值行
# x_train_fill,y_train_fill = fill_data.cca_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.cca_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 2、 平均值填充
# x_train_fill,y_train_fill = fill_data.mean_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.mean_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 3、 中位数填充
# x_train_fill,y_train_fill = fill_data.median_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.median_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 4、 众数填充
# x_train_fill,y_train_fill = fill_data.mode_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.mode_test_fill(x_train_fill,y_train_fill,x_test,y_test)# smote拟合数据
from imblearn.over_sampling import SMOTE
oversampler =SMOTE(k_neighbors=1,random_state=42)
os_x_train, os_y_train = oversampler.fit_resample(x_train_fill,y_train_fill)
# 将数据存入excel
data_train = pd.concat([os_y_train,os_x_train],axis=1).sample(frac=1,random_state=4)
data_test = pd.concat([y_test_fill,x_test_fill],axis=1)data_train.to_excel(r'.//temp_data//训练数据集[随机森林填充].xlsx',index=False)
data_test.to_excel(r'.//temp_data//测试数据集[随机森林填充].xlsx',index=False)

引用的函数:

import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
def cca_train_fill(train_data,train_label):data = pd.concat([train_data,train_label],axis =1)data = data.reset_index(drop=True)df = data.dropna()return df.drop('矿物类型', axis=1),df.矿物类型
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 = data.dropna()return df.drop('矿物类型', axis=1),df.矿物类型def mean_train_method(data):pjz = data.mean()return data.fillna(pjz)
def mean_train_fill(train_data,train_label):data = pd.concat([train_data,train_label], axis=1)data = data.reset_index(drop=True)A = data[data['矿物类型'] == 0]B = data[data['矿物类型'] == 1]C = data[data['矿物类型'] == 2]D = data[data['矿物类型'] == 3]A = mean_train_method(A)B = mean_train_method(B)C = mean_train_method(C)D = mean_train_method(D)df = pd.concat([A,B,C,D])df = df.reset_index(drop=True)return df.drop('矿物类型',axis=1),df.矿物类型def mean_test_method(train_data,test_data):pjz = train_data.mean()return test_data.fillna(pjz)
def mean_test_fill(train_data,train_label,test_data,test_label):train_data_all = pd.concat([train_data,train_label], axis=1)train_data_all = train_data_all.reset_index(drop=True)test_data_all = pd.concat([test_data,test_label], axis = 1)test_data_all = test_data_all.reset_index(drop=True)A_train = train_data_all[train_data_all['矿物类型'] == 0]B_train = train_data_all[train_data_all['矿物类型'] == 1]C_train = train_data_all[train_data_all['矿物类型'] == 2]D_train = train_data_all[train_data_all['矿物类型'] == 3]A_test = test_data_all[test_data_all['矿物类型'] == 0]B_test = test_data_all[test_data_all['矿物类型'] == 1]C_test = test_data_all[test_data_all['矿物类型'] == 2]D_test = test_data_all[test_data_all['矿物类型'] == 3]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 = pd.concat([A,B,C,D])df = df.reset_index(drop=True)return df.drop('矿物类型',axis=1),df.矿物类型def median_train_method(data):zwz = data.median()return data.fillna(zwz)
def median_train_fill(train_data,train_label):data = pd.concat([train_data,train_label],axis=1)A = data[data['矿物类型'] == 0]B = data[data['矿物类型'] == 1]C = data[data['矿物类型'] == 2]D = data[data['矿物类型'] == 3]A = median_train_method(A)B = median_train_method(B)C = median_train_method(C)D = median_train_method(D)df = pd.concat([A,B,C,D])df = df.reset_index(drop=True)return df.drop('矿物类型',axis=1),df.矿物类型def median_test_method(train_data,test_data):zwz = train_data.median()return test_data.fillna(zwz)
def median_test_fill(train_data,train_label,test_data,test_label):train_data_all = pd.concat([train_data, train_label], axis=1)test_data_all = pd.concat([test_data, test_label], axis=1)A_train = train_data_all[train_data_all['矿物类型'] == 0]B_train = train_data_all[train_data_all['矿物类型'] == 1]C_train = train_data_all[train_data_all['矿物类型'] == 2]D_train = train_data_all[train_data_all['矿物类型'] == 3]A_test = test_data_all[test_data_all['矿物类型'] == 0]B_test = test_data_all[test_data_all['矿物类型'] == 1]C_test = test_data_all[test_data_all['矿物类型'] == 2]D_test = test_data_all[test_data_all['矿物类型'] == 3]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 = pd.concat([A,B,C,D])df = df.reset_index(drop=True)return df.drop('矿物类型',axis=1),df.矿物类型def mode_train_method(data):zs = data.apply(lambda x: x.mode().iloc[0] if len(x.mode())>0 else None)return data.fillna(zs)
def mode_train_fill(train_data,train_label):data = pd.concat([train_data,train_label],axis=1)A = data[data['矿物类型'] == 0]B = data[data['矿物类型'] == 1]C = data[data['矿物类型'] == 2]D = data[data['矿物类型'] == 3]A = mode_train_method(A)B = mode_train_method(B)C = mode_train_method(C)D = mode_train_method(D)df = pd.concat([A, B, C, D])df = df.reset_index(drop=True)return df.drop('矿物类型', axis=1), df.矿物类型
def mode_test_method(train_data,test_data):zs = train_data.apply(lambda x: x.mode().iloc[0] if len(x.mode())>0 else None)return test_data.fillna(zs)
def mode_test_fill(train_data,train_label,test_data,test_label):train_data_all = pd.concat([train_data, train_label], axis=1)test_data_all = pd.concat([test_data, test_label], axis=1)A_train = train_data_all[train_data_all['矿物类型'] == 0]B_train = train_data_all[train_data_all['矿物类型'] == 1]C_train = train_data_all[train_data_all['矿物类型'] == 2]D_train = train_data_all[train_data_all['矿物类型'] == 3]A_test = test_data_all[test_data_all['矿物类型'] == 0]B_test = test_data_all[test_data_all['矿物类型'] == 1]C_test = test_data_all[test_data_all['矿物类型'] == 2]D_test = test_data_all[test_data_all['矿物类型'] == 3]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 = pd.concat([A,B,C,D])df = df.reset_index(drop=True)return df.drop('矿物类型',axis=1),df.矿物类型

这段代码是一个矿物分类任务的数据预处理 pipeline,主要实现了从原始数据读取、清洗、标准化到缺失值处理、类别平衡,最终生成训练集和测试集的完整流程。以下是代码解析:

1. 库导入与数据读取
import pandas as pd
import fill_data  # 自定义缺失值填充工具模块
# 导入数据
data = pd.read_excel('矿物数据.xls')

导入 pandas 用于数据处理,fill_data 是自定义模块(包含多种缺失值填充方法)。

读取原始矿物数据表格(矿物数据.xls),存储在 data 变量中(包含特征和标签)。

2. 数据清洗:过滤无效类别
# 删除结果为E的行
data = data[data['矿物类型']!='E']
  • 过滤掉标签为 'E' 的样本(可能是无效类别、异常值或不需要的类别),仅保留需要分类的 A/B/C/D 四类样本,减少噪声干扰。
3. 特征与标签分离
# 提取X和y值
X_whole = data.drop('序号',axis=1).drop('矿物类型',axis=1)  # 特征数据
y_whole = data['矿物类型']  # 标签数据

特征(X):删除无关的 '序号' 列(仅为编号,无实际意义)和标签列 '矿物类型',剩余列作为模型输入的特征(如矿物的化学成分、物理属性等)。

标签(y):提取 '矿物类型' 列作为分类目标(即需要预测的矿物类别)。

4. 标签编码:文字转数字
# 将结果中的中文字符改为英文字符(实际是文字标签转数字编码)
label_dict = {'A':0,'B':1,'C':2,'D':3}
xg_label = [label_dict[label] for label in y_whole]
y_whole = pd.Series(xg_label,name="矿物类型")

机器学习模型通常需要数值型标签,因此通过字典映射将原始文字标签('A'/'B'/'C'/'D')转换为数字(0/1/2/3)。

转换后标签存储为 pd.Series,保持数据结构一致性,方便后续处理。

5. 特征清洗:处理无效数值
# 处理特征中不合法的数值,并改成nan
for column_name in X_whole.columns:X_whole[column_name] = pd.to_numeric(X_whole[column_name], errors='coerce')

遍历所有特征列,使用 pd.to_numeric(..., errors='coerce') 将非数值型数据(如字符串、特殊符号等)强制转换为 NaN(缺失值)。

确保所有特征均为数值类型,避免后续模型训练因数据类型错误报错。

6. 特征标准化:Z 标准化
# (z标准化)
from sklearn.preprocessing import StandardScaler
sds = StandardScaler()
X_whole_z = sds.fit_transform(X_whole)
X_whole = pd.DataFrame(X_whole_z,columns=X_whole.columns)

Z 标准化:将特征转换为均值为 0、标准差为 1 的分布(公式:(x - 均值) / 标准差)。

作用:消除不同特征的量纲差异(如有的特征单位是百分比,有的是浓度值),使模型更易收敛(对 SVM、KNN 等基于距离的模型尤为重要)。

转换后的数据重新包装为 DataFrame,保留原始列名,便于追溯特征含义。

7. 数据集划分:训练集与测试集
# 切分测试集和训练集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(X_whole,y_whole,test_size=0.3,random_state=2000)

使用 train_test_split 将数据按 7:3 划分为训练集(70%)和测试集(30%)。

参数说明:test_size=0.3:测试集占比 30%;

random_state=2000:固定随机种子,确保每次运行划分结果一致(可复现性)。

划分后变量:x_train/x_test(训练 / 测试特征)、y_train/y_test(训练 / 测试标签)。

8. 缺失值填充:多种方法可选(当前未启用)
'''4种填充方法'''
# 1、 删除空值行
# x_train_fill,y_train_fill = fill_data.cca_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.cca_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 2、 平均值填充
# x_train_fill,y_train_fill = fill_data.mean_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.mean_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 3、 中位数填充
# x_train_fill,y_train_fill = fill_data.median_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.median_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 4、 众数填充
# x_train_fill,y_train_fill = fill_data.mode_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = fill_data.mode_test_fill(x_train_fill,y_train_fill,x_test,y_test)

代码提供了 64种缺失值填充方法(如删除空值行、平均值填充、中位数填充等),但当前均被注释(未启用)。

核心逻辑:先填充训练集(用训练集自身信息),再用训练集的填充规则填充测试集(避免数据泄露,即测试集不能使用自身信息填充)。

注意:由于此处未启用任何填充方法,后续代码可能因存在 NaN 报错,实际使用时需取消对应方法的注释。

4种填充方法函数解析:

这段代码是一个自定义缺失值填充工具模块fill_data),专为矿物分类数据设计了 4 类缺失值处理方法(删除空值法、平均值填充、中位数填充、众数填充),每种方法都包含训练集填充和测试集填充两个函数,严格遵循 “用训练集信息填充测试集” 的原则(避免数据泄露)。以下是详细解析:

*1. 删除空值法(cca_ 函数)**

直接删除包含缺失值的样本,是最简单的缺失值处理方式。

# 训练集删除空值
def cca_train_fill(train_data,train_label):# 合并特征和标签,重置索引data = pd.concat([train_data,train_label],axis =1).reset_index(drop=True)# 删除所有含缺失值的行df = data.dropna()# 返回填充后的特征和标签(分离)return df.drop('矿物类型', axis=1), df.矿物类型# 测试集删除空值
def cca_test_fill(train_data,train_label,test_data,test_label):# 合并测试集特征和标签,重置索引data = pd.concat([test_data,test_label], axis=1).reset_index(drop=True)# 删除所有含缺失值的行df = data.dropna()# 返回填充后的特征和标签(分离)return df.drop('矿物类型', axis=1), df.矿物类型

适用场景:缺失值比例极低(如 < 5%),且样本量充足的情况。

优缺点:简单直接,但会丢失数据(尤其缺失值多时,可能导致样本量不足)。

*2. 平均值填充(mean_ 函数)**

按矿物类别计算特征的平均值,用该平均值填充同类别样本的缺失值(训练集用自身均值,测试集用训练集同类别均值)。

# 训练集填充逻辑:计算同类别平均值并填充
def mean_train_method(data):pjz = data.mean()  # 计算当前数据中各特征的平均值return data.fillna(pjz)  # 用平均值填充缺失值def mean_train_fill(train_data,train_label):# 合并训练集特征和标签data = pd.concat([train_data,train_label], axis=1).reset_index(drop=True)# 按矿物类型(0-3)分组(A=0, B=1, C=2, D=3)A = data[data['矿物类型'] == 0]B = data[data['矿物类型'] == 1]C = data[data['矿物类型'] == 2]D = data[data['矿物类型'] == 3]# 每组内用自身平均值填充缺失值A = mean_train_method(A)B = mean_train_method(B)C = mean_train_method(C)D = mean_train_method(D)# 合并所有组,重置索引df = pd.concat([A,B,C,D]).reset_index(drop=True)# 返回填充后的特征和标签return df.drop('矿物类型',axis=1), df.矿物类型# 测试集填充逻辑:用训练集同类别平均值填充
def mean_test_method(train_data,test_data):pjz = train_data.mean()  # 用训练集的平均值作为填充参数return test_data.fillna(pjz)  # 填充测试集的缺失值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)# 按矿物类型分组(训练集和测试集各分4组)A_train = train_data_all[train_data_all['矿物类型'] == 0]B_train = train_data_all[train_data_all['矿物类型'] == 1]C_train = train_data_all[train_data_all['矿物类型'] == 2]D_train = train_data_all[train_data_all['矿物类型'] == 3]A_test = test_data_all[test_data_all['矿物类型'] == 0]B_test = test_data_all[test_data_all['矿物类型'] == 1]C_test = test_data_all[test_data_all['矿物类型'] == 2]D_test = test_data_all[test_data_all['矿物类型'] == 3]# 测试集每组用训练集同组的平均值填充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 = pd.concat([A,B,C,D]).reset_index(drop=True)# 返回填充后的特征和标签return df.drop('矿物类型',axis=1), df.矿物类型

核心逻辑:同一类矿物的特征分布更相似,用同类别均值填充比全局均值更精准。

适用场景:特征为连续值,且分布近似正态(均值能代表集中趋势)。

*3. 中位数填充(median_ 函数)**

逻辑与平均值填充完全一致,仅将 “平均值” 替换为 “中位数”,更抗极端值干扰。

# 训练集用同类别中位数填充
def median_train_method(data):zwz = data.median()  # 计算中位数return data.fillna(zwz)def median_train_fill(train_data,train_label):# 逻辑同mean_train_fill,仅用median_train_method替换mean_train_method...# 测试集用训练集同类别中位数填充
def median_test_method(train_data,test_data):zwz = train_data.median()  # 用训练集中位数return test_data.fillna(zwz)def median_test_fill(...):# 逻辑同mean_test_fill,仅用median_test_method替换mean_test_method...

核心优势:中位数对异常值(如矿物特征中的极端测量值)更稳健,适合特征分布有偏态的场景。

*4. 众数填充(mode_ 函数)**

用特征中出现次数最多的值(众数)填充缺失值,适合离散特征(如分类变量)。

# 训练集用同类别众数填充
def mode_train_method(data):# 计算众数:若存在众数则取第一个,否则为Nonezs = data.apply(lambda x: x.mode().iloc[0] if len(x.mode())>0 else None)return data.fillna(zs)def mode_train_fill(train_data,train_label):# 逻辑同mean_train_fill,仅用mode_train_method替换mean_train_method...# 测试集用训练集同类别众数填充
def mode_test_method(train_data,test_data):zs = train_data.apply(lambda x: x.mode().iloc[0] if len(x.mode())>0 else None)return test_data.fillna(zs)def mode_test_fill(...):# 逻辑同mean_test_fill,仅用mode_test_method替换mean_test_method...

核心逻辑:众数是最频繁出现的值,适合离散特征(如矿物的某分类属性:“有 / 无光泽”)。

注意x.mode().iloc[0] 处理了多众数的情况(取第一个众数)。

9. 类别平衡处理:SMOTE 过采样
# smote拟合数据
from imblearn.over_sampling import SMOTE
oversampler = SMOTE(k_neighbors=1,random_state=42)
os_x_train, os_y_train = oversampler.fit_resample(x_train_fill,y_train_fill)

问题背景:矿物数据可能存在类别不平衡(如某些矿物样本极少),导致模型偏向多数类,少数类识别效果差。

SMOTE 过采样:通过生成少数类的合成样本(基于近邻样本插值),平衡各分类的样本数量。

参数说明:k_neighbors=1:生成合成样本时参考 1 个近邻样本;

random_state=42:固定随机种子,确保过采样结果可复现。

处理后变量:os_x_train(平衡后的训练特征)、os_y_train(平衡后的训练标签)。

10. 数据保存:输出预处理后数据集
# 将数据存入excel
data_train = pd.concat([os_y_train,os_x_train],axis=1).sample(frac=1,random_state=4)  # 拼接并打乱训练集
data_test = pd.concat([y_test_fill,x_test_fill],axis=1)  # 拼接测试集data_train.to_excel(r'.//temp_data//训练数据集[随机森林填充].xlsx',index=False)
data_test.to_excel(r'.//temp_data//测试数据集[随机森林填充].xlsx',index=False)

数据拼接:将标签列与特征列按列拼接(axis=1),形成完整的训练集和测试集。

打乱训练集sample(frac=1) 将训练集样本顺序打乱,避免模型受样本顺序影响。

保存文件:将预处理后的数据集保存到 temp_data 文件夹,文件名注明 “随机森林填充”(尽管当前未启用该方法,可能是历史遗留命名),index=False 表示不保存行索引。

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

相关文章:

  • redis的过期键有哪些删除策略
  • Product Hunt 每日热榜 | 2025-08-18
  • 【跨国数仓迁移最佳实践6】MaxCompute SQL语法及函数功能增强,10万条SQL转写顺利迁移
  • 论往返之迴响:时间之织锦与信息之曼舞
  • [激光原理与应用-294]:理论 - 波动光学 - 衍射光学元件(DOE)
  • 如何生成和安全保存私钥?
  • oracle dg duplicate限速
  • 区块链技术原理(16)-以太坊节点与客户端
  • SpringBoot--JWT
  • WPF 打印报告图片大小的自适应(含完整示例与详解)
  • 初识CNN04——经典网络认识
  • 驱动开发系列64 - glCompileShader实现-GLSL 精度优化pass
  • 3.1 结构化输出(大模型的封闭与开放)
  • Windows系统上使用GIT
  • CMake指令:查找文件(find_file)、查找目录(find_path)、查找库文件(find_library)
  • Life:Internship in OnSea Day 57
  • 【Kubernetes】在 K8s 上部署 Prometheus
  • 1-Flask相关知识点
  • 恒创科技:日本服务器 ping 不通?从排查到解决的实用指南
  • 朝阳区24小时图书馆“焕新计划”启幕 文化讲座点亮夜间阅读之光
  • ST05跟踪MRP的运行(MD01)过程
  • 使用chmod 命令修改文件权限
  • 【完整源码+数据集+部署教程】空中目标检测系统源码和数据集:改进yolo11-UniRepLKNetBlock
  • mac 电脑安装类似 nvm 的工具,node 版本管理工具
  • 【机器人-基础知识】ROS2常用命令
  • Vue3 全新特性 defineModel 深度解析
  • CentOS Linux 7 (Core)上部署Oracle 11g、19C RAC详细图文教程
  • 【MySQL】超详细入门学习
  • vue3 + antd modal弹窗拖拽全局封装 使用useDraggable
  • LeetCode100 -- Day1