矿物数据.xls
矿物种类:A,B,C,D,E(其中E数据只有一条,无法用于训练,直接剔除)
特征:序号 氯 钠 镁 硫 钙 钾 碳 溴 锶 pH 硼 氟 硒 矿物类型
此数据有:缺失值、异常值、噪声数据、类别不均衡等等。
案例共有两部分代码:
一、数据清洗.py
代码解析:(完整代码在解析下方)
1.读取与初筛
-
读取 Excel:用 pandas 的
read_excel
把"数据/矿物数据.xls"读成 DataFrame。 -
去掉无用索引列:用
drop('序号', axis=1)
删除名为"序号"的列(axis=1 表示按列删除)。 -
过滤类别:用布尔筛选
data[data["矿物类型"] != 'E']
去掉矿物类型为 E 的行,只保留 A/B/C/D。 -
(注释掉的检查缺失)
isnull()
会生成布尔表,sum()
会按列统计缺失个数,便于了解缺失分布,但此处未执行。
2.构造特征矩阵 X 与标签 y
-
拆分特征与标签:用
drop('矿物类型', axis=1)
得到全部特征列 X_whole;用"点取列"的写法data.矿物类型
得到标签 y_whole。 -
这样得到的 X_whole 为数值+可能的异常字符串混合,y_whole 仍是字母类别。
3.标签数值化与索引重排
-
类别映射:用
Series.replace({'A':0,'B':1,'C':2,'D':3})
把 A/B/C/D 映射为 0/1/2/3,得到数值标签,便于后续建模和上采样。 -
重排索引:
reset_index(drop=True)
把 y 的行索引重置为 0..n-1(丢弃旧索引)。这样做是为了避免后面各种转换(尤其是把 X 标准化后重新构成 DataFrame)导致 X 与 y 的索引错位。
4.异常值与非数值转缺失
-
逐列数值化:对 X_whole 的每一列调用
pd.to_numeric(..., errors='coerce')
。 -
作用:把能转成数字的转成数字;不能转的(例如非法字符串、∞、溢出)统统变成
NaN
。这一步相当于"异常数据 → 缺失",便于统一用填充/删除策略处理,同时也让后续标准化器能正确识别为数值类型。
5.Z-Score 标准化
-
标准化器:从
sklearn.preprocessing
引入StandardScaler()
,先fit_transform(X_whole)
。 -
机制:对每列做
(x - 列均值) / 列标准差
,得到均值约为 0、方差约为 1 的特征。 -
结果包装:把输出的二维数组再用
pd.DataFrame(..., columns=原列名)
还原为带列名的 DataFrame,便于后续对列名的引用。 -
提醒:严格的机器学习流程应只在训练集上
fit
、再对测试集transform
,本代码是在全量数据上做了fit_transform
,会有信息泄露风险;不过后面仍会在训练/测试阶段额外做缺失处理与采样。
6.训练/测试集切分
-
切分函数:
train_test_split(X_whole, y_whole, test_size=0.3, random_state=42)
。 -
作用:按 7:3 比例把数据随机划分为训练集和测试集,并通过固定
random_state
保证可复现实验结果。返回四个对象:x_train_w, x_test_w, y_train_w, y_test_w
。
7.引入缺失值处理模块fill_data.py(自定义)
-
import fill_data
:加载你自己写的缺失值处理工具模块。 -
核心思想:所有
*_train_fill
负责"基于训练集拟合并填充训练集";与之配套的*_test_fill
负责"用训练阶段学到的统计量/模型去填充测试集"。这样可以避免把测试集信息泄露到训练阶段。
1.方案一:仅保留完整样本(CCA,列表删除)
-
训练集处理:
fill_data.cca_train_fill(x_train_w, y_train_w)
。典型实现是删除训练集中任一特征为NaN
的行(complete-case analysis / listwise deletion),同步删掉标签中的对应行,返回x_train_fill, y_train_fill
。 -
测试集处理:
fill_data.cca_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
。常见做法有两种:1)与训练集一致,只保留测试集中无缺失的行;
2)或者对测试集按训练集所保留的"有效特征子集/列集合"进行一致性处理并删除含缺失的行。
-
结果:得到完全无缺失的训练/测试集,最简单也最保守,但可能损失样本量。
2.备选缺失处理方案(按需启用其一)
这些在代码中被注释掉了,切换方案时把对应两行解注释,并注释掉 CCA 两行即可。每种方案都有一对
*_train_fill
/*_test_fill
:
-
均值填充:
mean_train_fill
/mean_test_fill
。-
训练时:通常用
SimpleImputer(strategy='mean')
在训练集按列fit
均值,再transform
训练集。 -
测试时:用训练集学到的均值
transform
测试集,保证训练-测试的一致性。适合数值型特征、分布较对称时。
-
-
中位数填充:
median_train_fill
/median_test_fill
。-
训练时:
SimpleImputer(strategy='median')
拟合中位数,鲁棒于偏态与离群值。 -
测试时:用训练阶段的中位数进行
transform
。
-
-
众数填充:
mode_train_fill
/mode_test_fill
。-
训练时:
SimpleImputer(strategy='most_frequent')
学习每列的众数; -
测试时:用训练阶段的众数填充。适合分类型或取值离散的数值特征。
-
-
线性回归填充:
lr_train_fill
/lr_test_fill
。-
训练时:对每个存在缺失的数值特征 f,取"f 非缺失的行"作为训练样本,其他特征为自变量 X,f 为目标 y,用
LinearRegression
拟合;再用该回归器预测"f 缺失的行"的取值,实现按列迭代填充。 -
测试时:用训练阶段为每个目标列学到的回归器,对测试集中该列的缺失位置做预测填充。能利用特征间线性关系,但对非线性关系/异常值较敏感。
-
-
随机森林填充:
rf_train_fill
/rf_test_fill
。-
训练时:与线回归思路相同,但用
RandomForestRegressor
(或若为离散列,用RandomForestClassifier
)逐列建模预测缺失,更能捕捉非线性与特征交互。 -
测试时:用训练阶段保存的森林模型对测试集缺失进行填补。性能更强,但计算更重。
-
8.过采样处理类别不平衡(仅对训练集)
-
上采样器:从
imblearn.over_sampling
引入SMOTE
,用SMOTE(k_neighbors=2, random_state=42)
初始化。 -
机制:
fit_resample(x_train_fill, y_train_fill)
会对每个少数类样本,寻找同类的 k 个近邻(此处 k=2),在样本与其近邻连线上随机插值,合成新的少数类样本,直到各类数量平衡或达到设定比率。 -
结果:得到
os_x_train, os_y_train
,这是类别更均衡的训练集,利于分类器学习不被多数类主导。注意 SMOTE 仅对训练集做,避免把"合成信息"泄露到测试评估。
9.数据合并后存入excel
-
合并与洗牌(训练集):用
pd.concat([os_y_train, os_x_train], axis=1)
把标签列放到最前面,再用sample(frac=1, random_state=4)
打乱行次序(frac=1
表示全量采样,等价完全洗牌),保证导出文件行序无偏。 -
合并(测试集):用
pd.concat([y_test_fill, x_test_fill], axis=1)
将标签与特征拼在一起(测试集不做洗牌也无妨)。 -
写出 Excel:
to_excel(path, index=False)
把训练/测试表分别写入指定路径,不保留行索引。当前启用的是"[删除空数据行]"版本(即 CCA 方案),其余几组to_excel
路径对应"平均值填充 / 中位数填充 / 众数填充 / 线性回归填充 / 随机森林填充"的导出文件,按需要启用相应两行即可保持命名与方案一致。
流程小结与一致性约束
数据进入流程后,先删列、滤类,再把异常值规范为缺失,做标准化,然后切分训练/测试。
任何"*_train_fill / *_test_fill"必须成对使用:训练端学来的统计量或模型只能用来处理测试集,不能反过来;这样才能避免信息泄露,保证评估公正。
SMOTE 只对训练集做
fit_resample
,随后导出平衡后的训练集与对应原始分布的测试集。导出阶段将 y 放在最前列,便于下游直接读取"标签 + 特征"的格式开展建模。
按照以上说明,你可以在"第 8~9 步"之间自由切换一种缺失处理策略;其余步骤保持不变即可完成从原始 Excel → 清洗/标准化 → 缺失处理 → 训练集重采样 → 可用训练/测试 Excel 的全流程。
完整代码:
import pandas as pd
# 1、读取excel文件 # 2、删除E类别的数据
data = pd.read_excel("数据/矿物数据.xls").drop('序号', axis=1)
data = data[data["矿物类型"] != 'E']
# null_num = data.isnull() # 查看空值数
# null_total = null_num.sum()
# 3、提取X和Y数据
X_whole = data.drop('矿物类型', axis=1)
y_whole = data.矿物类型
# 4、把标签转换为数值
y_whole = y_whole.replace({'A': 0, 'B': 1, 'C': 2, 'D': 3}).reset_index(drop=True) # 重排索引(因为X_whole标准化时也进行了重组)
# 5、异常数据转换为nan
for column_name in X_whole.columns:
X_whole[column_name] = pd.to_numeric(X_whole[column_name], errors='coerce')
# 6、对数据进行Z标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_whole_Z = scaler.fit_transform(X_whole)
X_whole = pd.DataFrame(X_whole_Z, columns=X_whole.columns)
# 7、切分数据集
from sklearn.model_selection import train_test_split
x_train_w, x_test_w, y_train_w, y_test_w = train_test_split(X_whole, y_whole, test_size = 0.3, random_state = 42)
# 8、创建一个fill_data.py文件
import fill_data
# # 1、只保留完整数据集
x_train_fill,y_train_fill = fill_data.cca_train_fill(x_train_w,y_train_w) # 调用自己写的implement_data.py
x_test_fill,y_test_fill = fill_data.cca_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
# # 2、使用平均值的方法对数据进行填充
# x_train_fill,y_train_fill = fill_data.mean_train_fill(x_train_w,y_train_w)
# x_test_fill,y_test_fill = fill_data.mean_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
# # 3、使用中位数的方法对数据进行填充
# x_train_fill,y_train_fill = fill_data.median_train_fill(x_train_w,y_train_w)
# x_test_fill,y_test_fill = fill_data.median_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
# # 4、使用众数的方法对数据进行填充
# x_train_fill,y_train_fill = fill_data.mode_train_fill(x_train_w,y_train_w)
# x_test_fill,y_test_fill = fill_data.mode_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
# # 5、线性回归算法实现训练数据集、测试数据集的填充
# x_train_fill,y_train_fill = fill_data.lr_train_fill(x_train_w,y_train_w)
# x_test_fill,y_test_fill = fill_data.lr_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
# # 6、随机森林算法实现训练数据集、测试数据集的填充
# x_train_fill,y_train_fill = fill_data.rf_train_fill(x_train_w,y_train_w)
# x_test_fill,y_test_fill = fill_data.rf_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
# 9、smote拟合数据
from imblearn.over_sampling import SMOTE
oversampler = SMOTE(k_neighbors=2, random_state=42)
os_x_train, os_y_train = oversampler.fit_resample(x_train_fill, y_train_fill)
# 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'./数据//训练数据集[删除空数据行].xlsx', index=False)
data_test.to_excel(r'./数据//测试数据集[删除空数据行].xlsx', index=False)
# data_train.to_excel(r'./数据//训练数据集[平均值填充].xlsx', index=False)
# data_test.to_excel(r'./数据//测试数据集[平均值填充].xlsx', index=False)
# data_train.to_excel(r'./数据//训练数据集[中位数填充].xlsx', index=False)
# data_test.to_excel(r'./数据//测试数据集[中位数填充].xlsx', index=False)
# data_train.to_excel(r'./数据//训练数据集[众数填充].xlsx', index=False)
# data_test.to_excel(r'./数据//测试数据集[众数填充].xlsx', index=False)
# data_train.to_excel(r'./数据//训练数据集[线性回归填充].xlsx', index=False)
# data_test.to_excel(r'./数据//测试数据集[线性回归填充].xlsx', index=False)
# data_train.to_excel(r'./数据//训练数据集[随机森林填充].xlsx', index=False)
# data_test.to_excel(r'./数据//测试数据集[随机森林填充].xlsx', index=False)
二、fill_data.py
(代码很长是因为每一种方案都完整写了出来,有很多重复的行为,如果只是需要一种方案,可以直接截取相关函数即可)
整体作用
这个文件就是实现多种 缺失值填充策略,包括:
-
CCA(Complete Case Analysis):只保留完整数据行。
-
均值填充。
-
中位数填充。
-
众数填充。
-
机器学习方法填充(线性回归 / 随机森林)。
每个方法都有 train_fill 和 test_fill 两个版本:
-
train_fill:在训练数据上学到填充规则,并对训练数据应用。
-
test_fill:在测试数据上,沿用训练数据的规则,保证一致性。
1. CCA(Complete Case Analysis 完整案例分析)
训练集函数 cca_train_fill
-
把特征和标签拼接(
pd.concat
),保证同步操作。 -
dropna()
删除任何含有 NaN 的行。 -
返回:删除了"矿物类型"这一列的特征矩阵,以及对应的标签。
👉 效果:只保留完全无缺失的样本。
测试集函数 cca_test_fill
-
和训练集思路一样:拼接后
dropna()
。 -
返回填充后的测试集特征和标签。
👉 效果:测试集也只保留完整数据行。
2. 均值填充
mean_train_method
-
用
data.mean()
算出每一列的平均值。 -
用
fillna()
把缺失值替换为该平均值。
mean_train_fill
-
拼接 train 特征和标签。
-
按类别(矿物类型 = 0/1/2/3)分组。
-
对每组分别执行
mean_train_method
(按组的均值填充)。 -
再合并所有组,保证类别平衡。
👉 效果:训练集中,每个类别的缺失值用该类别对应的均值来补。
mean_test_method
-
根据训练集算平均值,再填充测试集。
👉 关键:测试集不能用自己的统计量,要沿用训练集的均值,避免信息泄露。
mean_test_fill
-
拼接 train / test 数据。
-
按类别分组(保证 A/B/C/D 独立)。
-
每组 test 用对应 train 的均值填充。
👉 效果:训练和测试的数据分布保持一致。
3. 中位数填充
逻辑和均值完全类似,只是 mean()
换成了 median()
。
-
median_train_method
:算中位数填充。 -
median_train_fill
:按类别拆开,组内中位数填充训练集。 -
median_test_method
:用训练集的中位数填充测试集。 -
median_test_fill
:分组,train 提供中位数,test 填充。👉 适合分布偏态或有异常值的数据,比均值鲁棒。
4. 众数填充
mode_train_method
-
用
apply(lambda x: x.mode().iloc[0])
求每列的众数(出现次数最多的值)。 -
再
fillna
用众数补齐。
mode_train_fill
- 和均值/中位数一样:拼接、分组、对每组用众数补齐、再合并。
mode_test_method
- 用训练集每列的众数来填充测试集。
mode_test_fill
-
分组(四个类别),再用对应组的训练集众数填充测试集。
👉 适合离散变量(如分类型特征),但对连续数值可能不太合适。
5. 机器学习方法填充
(1)线性回归填充
lr_train_fill
(训练集)
-
拼接 train 数据(特征+标签)。
-
找出每列缺失值的数量(
isnull().sum()
),按从少到多排序。 -
遍历列:
-
如果某列有缺失:
-
构造输入特征 X(用之前填充过的列 + 其他可用特征),目标是当前列。
-
非缺失部分 → 训练集;缺失部分 → 预测集。
-
用
LinearRegression().fit(X_train, y_train)
训练。 -
predict
得到预测值,填回缺失位置。
-
-
-
循环完成后,返回填充好的特征和标签。
👉 思路:利用特征间的线性关系预测缺失值。
lr_test_fill
(测试集)
-
类似逻辑,但用 训练集的数据训练模型,对测试集缺失的列做预测填充。
-
确保测试集不参与模型训练。
(2)随机森林填充
rf_train_fill
-
步骤和线性回归类似,但模型换成
RandomForestRegressor(n_estimators=100)
。 -
好处:能捕捉非线性关系,比线性回归更灵活。
-
同样:非缺失部分训练,缺失部分预测。
rf_test_fill
- 和
lr_test_fill
一样,用训练集建模,测试集缺失值用预测补齐。
总结
这个文件里,每个缺失处理方法都有两套函数:
-
train_fill:基于训练集"学规则 + 填训练集"。
-
test_fill:沿用训练集规则,填充测试集。
方法层次:
-
简单剔除:CCA(删除有缺失的行)。
-
统计填充:均值 / 中位数 / 众数。
-
机器学习预测填充:线性回归(线性假设) / 随机森林(非线性、鲁棒)。
这样设计的好处:
-
不同方法可以随时替换,实验对比。
-
保证训练集和测试集的处理一致,避免信息泄露。
import pandas as pd
'''此文档用不同的算法实现缺失数据的填充,算法使用到
1、CCA(Complete Case Analysis)只考虑包含完整数据的行
2、平均值
3、中位数
4、众数
5、机器学习算法
'''#------------------------------考虑包含完整行的数据------------------------------#
def cca_train_fill(train_data, train_label):
'''CCA(Complete Case Analysis)只考虑包含完整数据的行'''
data = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)
df_filled = data.dropna()
return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型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_filled = data.dropna()
return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型#------------------------------使用平均值的方法对数据进行填充------------------------------#
def mean_train_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).reset_index(drop=True)
groups = [data[data['矿物类型'] == i] for i in range(4)]
groups = [mean_train_method(g) for g in groups]
df_filled = pd.concat(groups).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_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)
test_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)train_groups = [train_all[train_all['矿物类型'] == i] for i in range(4)] test_groups = [test_all[test_all['矿物类型'] == i] for i in range(4)] filled = [mean_test_method(tg, sg) for tg, sg in zip(train_groups, test_groups)] df_filled = pd.concat(filled).reset_index(drop=True) return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
#------------------------------使用中位数的方法对数据进行填充------------------------------#
def median_train_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)
groups = [data[data['矿物类型'] == i] for i in range(4)]
groups = [median_train_method(g) for g in groups]
df_filled = pd.concat(groups).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, train_label, test_data, test_label):
'''使用中位数的方法对测试集填充'''
train_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)
test_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)train_groups = [train_all[train_all['矿物类型'] == i] for i in range(4)] test_groups = [test_all[test_all['矿物类型'] == i] for i in range(4)] filled = [median_test_method(tg, sg) for tg, sg in zip(train_groups, test_groups)] df_filled = pd.concat(filled).reset_index(drop=True) return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
#------------------------------使用众数的方法对数据进行填充------------------------------#
def mode_train_method(data):
'''数据集中的空值使用每列的众数替代'''
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)
groups = [data[data['矿物类型'] == i] for i in range(4)]
groups = [mode_train_method(g) for g in groups]
df_filled = pd.concat(groups).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_all = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)
test_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)train_groups = [train_all[train_all['矿物类型'] == i] for i in range(4)] test_groups = [test_all[test_all['矿物类型'] == i] for i in range(4)] filled = [mode_test_method(tg, sg) for tg, sg in zip(train_groups, test_groups)] df_filled = pd.concat(filled).reset_index(drop=True) return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
#------------------------------使用机器学习算法对数据进行填充------------------------------#
线性回归
from sklearn.linear_model import LinearRegression
def lr_train_fill(train_data,train_label):
'''使用线性回归填充训练数据集的缺失值,主要是基于这样一个思想:特征和目标变量之间存在一定的关系,因此可以利用这种关系对缺失的特征进行预测。
以下是使用线性回归填充缺失值的一般步骤:
1、首先,确定哪些特征包含缺失值。
2、对于包含缺失值的特征,将其作为目标变量,而其他特征(可以包括原始的目标变量)作为输入特征。注意,如果多个特征都有缺失值,
通常建议按照缺失值的数量从小到大进行处理。因为缺失值较少的特征对预测的要求较低,准确性可能更高。
3、在处理某个特征的缺失值时,将该特征中的已知值(即非缺失值)作为训练集,而缺失值作为需要预测的目标。此时,其他特征的相应值作为输入特征。
4、使用线性回归模型进行训练,并对缺失值进行预测。
5、将预测得到的值填充到原始数据中的相应位置。
6、重复上述步骤,直到处理完所有包含缺失值的特征。
需要注意的是,使用线性回归填充缺失值时,可能会受到模型选择和过拟合等因素的影响。因此,在实际应用中,建议对数据进行适当的预处理,
如特征选择、异常值处理等,以提高填充的准确性和稳定性。同时,也可以使用交叉验证等方法来评估填充的效果。
'''
train_data_all = pd.concat([train_data, train_label], axis=1)
train_data_all = train_data_all.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_pred # pandas.loc[3,4] print('完成训练集中"{}"的填充'.format(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)
test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)train_data_X = train_data_all.drop('矿物类型', axis=1) test_data_X = test_data_all.drop('矿物类型', axis=1) null_num = test_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 = train_data_X[filling_feature].drop(i, axis=1) y_train = train_data_X[i] X_test = test_data_X[filling_feature].drop(i, axis=1) row_numbers_mg_null = test_data_X[test_data_X[i].isnull()].index.tolist() X_test = X_test.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_pred print('完成测试集中{}的填充'.format(i)) return test_data_X, test_data_all.矿物类型
随机森林
from sklearn.ensemble import RandomForestRegressor
def rf_train_fill(train_data,train_label):
train_data_all = pd.concat([train_data, train_label], axis=1)
train_data_all = train_data_all.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 = RandomForestRegressor(n_estimators=100, random_state=42) regr.fit(X_train, y_train) # 训练模型 y_pred = regr.predict(X_test) train_data_X.loc[row_numbers_mg_null, i] = y_pred # pandas.loc[3,4] print('完成训练集中"{}"的填充'.format(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)
test_data_all = pd.concat([test_data, test_label], axis=1).reset_index(drop=True)train_data_X = train_data_all.drop('矿物类型', axis=1) test_data_X = test_data_all.drop('矿物类型', axis=1) null_num = test_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 = train_data_X[filling_feature].drop(i, axis=1) y_train = train_data_X[i] X_test = test_data_X[filling_feature].drop(i, axis=1) row_numbers_mg_null = test_data_X[test_data_X[i].isnull()].index.tolist() X_test = X_test.iloc[row_numbers_mg_null] regr = RandomForestRegressor(n_estimators=100, random_state=42) regr.fit(X_train, y_train) y_pred = regr.predict(X_test) test_data_X.loc[row_numbers_mg_null, i] = y_pred print('完成测试集中{}的填充'.format(i)) return test_data_X, test_data_all.矿物类型