礦物數據.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_predprint('完成測試集中{}的填充'.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_predprint('完成測試集中{}的填充'.format(i))return test_data_X, test_data_all.礦物類型