一、分析数据表格
1.我们这里用的是矿物分类的数据表格最后一列为矿物类型共5类A,B,C,D,E作为数据标签,前面的矿物元素构成含量作为数据特征。
2.我们需要观察表格里的数据进行处理确保数据能够正常进行训练
第一种:表格中的数据存在空白值,我们需要对空白值进行填充
第二种:E种类的矿物数据太少只有几条无法进行训练需要排除出去
第三种:数据在人工输入的时候会存在一些错误,比如多打了一个小数点或其他符号导致数据错误。
二、导入和处理数据
1.导入数据
import pandas as pd
data=pd.read_excel(r'.\矿物数据.xls')
导入pandas库读取矿物数据的表格
2.处理数据
1.将矿物类别为E的数据清除
python
data=data[data['矿物类型']!='E']
2.得到数据特征与数据标签
python
x_whole=data.drop('矿物类型',axis=1).drop('序号',axis=1)
y_whole=data.矿物类型
3.将矿物类别的A,B,C,D转化成数字0,1,2,3好做数据分类
python
label_c={'A':0,'B':1,'C':2,'D':3}
en_labels=[label_c[label] for label in y_whole]
y_whole=pd.Series(en_labels,name="矿物类型")
4.遍历 DataFrame x_whole 的每一列,将每一列的所有值强制转换为数值类型(int/float);如果某个值无法转换(比如字符串 "abc"、空字符串 "" 等),则将其替换为 NaN(缺失值)。
python
for column_name in x_whole.columns:
x_whole[column_name]=pd.to_numeric(x_whole[column_name],errors='coerce')
5.对 DataFrame x_whole 的所有特征列做标准化处理,并将处理后的结果重新转换为 DataFrame(保留原列名)
python
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)
6.数据切分通过train_test_split将你的特征数据和标签数据按 7:3 的比例随机拆分
python
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=0)
x_whole:为数据特征
y_whole:为数据标签
test_size:划分训练集和测试集的比例
random_state:随机种子确保每次随机是一样的
三、数据填充
1.删除空白行进行填充
定义cca_train_fill()和cca_test_fill()方法进行删除空白行
python
x_train_fill,y_train_fill= fill_data.cca_train_fill(x_train_w, y_train_w)
x_test_fill,y_test_fill= fill_data.cca_test_fill(x_test_w, y_test_w)
定义函数代码
python
def cca_train_fill(x_data,y_data):
my_data=pd.concat([x_data,y_data],axis=1)
my_data=my_data.reset_index(drop=True)
new_data=my_data.dropna()
return new_data.drop("矿物类型",axis=1),new_data.矿物类型
def cca_test_fill(x_data,y_data):
my_data=pd.concat([x_data,y_data],axis=1)
my_data=my_data.reset_index(drop=True)
new_data=my_data.dropna()
return new_data.drop("矿物类型",axis=1),new_data.矿物类型
1.通过concat()方法将特征和标签组合起来使删除空白行时标签会跟着特征一起删除。
2.用reset_index(drop=True)将数据重新排序
3.通过dropna()删除 DataFrame/Series 中包含缺失值(NaN)的行
python
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)#人工拟合的只是训练集。
对训练集的少数类样本进行 "人工合成",让训练集中各类别的样本数量达到平衡
2.取平均值填充
函数定义:
python
def mean_train_fill(x_data,y_data):
my_data=pd.concat([x_data,y_data],axis=1)
my_data = my_data.reset_index(drop=True)
A=my_data[my_data['矿物类型']==0]
B = my_data[my_data['矿物类型'] == 1]
C= my_data[my_data['矿物类型'] == 2]
D= my_data[my_data['矿物类型'] == 3]
A=mean_train_method(A)
B=mean_train_method(B)
C=mean_train_method(C)
D=mean_train_method(D)
df_filled=pd.concat([A,B,C,D])
new_data = df_filled.reset_index(drop=True)
return new_data.drop("矿物类型",axis=1),new_data.矿物类型
def mean_test_fill(x_data_train,y_data_train,x_data,y_data):
my_data_train=pd.concat([x_data_train,y_data_train],axis=1)
my_data_test=pd.concat([x_data,y_data],axis=1)
my_data_train = my_data_train.reset_index(drop=True)
my_data_test = my_data_test.reset_index(drop=True)
A_train=my_data_train[my_data_train['矿物类型']==0]
B_train = my_data_train[my_data_train['矿物类型'] == 1]
C_train= my_data_train[my_data_train['矿物类型'] == 2]
D_train= my_data_train[my_data_train['矿物类型'] == 3]
A_test=my_data_test[my_data_test['矿物类型']==0]
B_test = my_data_test[my_data_test['矿物类型'] == 1]
C_test = my_data_test[my_data_test['矿物类型'] == 2]
D_test = my_data_test[my_data_test['矿物类型'] == 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_filled=pd.concat([A,B,C,D])
new_data = df_filled.reset_index(drop=True)
return new_data.drop("矿物类型",axis=1),new_data.矿物类型
def mean_train_method(data):
fill_values=data.mean()
return data.fillna(fill_values)
def mean_test_method(train_v,test_v):
fill_values=train_v.mean()
return test_v.fillna(fill_values)
相要通过平均值填充需要对矿物类型进行分类求同一类型的平均值进行填充
通过data.mean()计算每一列的平均值在用fillna()进行缺失值的填充
注意:此时测试集的数据需要通过训练集的平均值进行填充
3.取中位数填充
python
def media_train_method(data):
fill_values=data.median()
return data.fillna(fill_values)
def media_test_method(train_v,test_v):
fill_values=train_v.median()
return test_v.fillna(fill_values)
中位数填充与平均值填充步骤差不多取中位数用median()方法
4.取众数填充
python
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_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)#使用众数填充缺失值
众数填充步骤也差不多,mode()方法取众数可能一列会有很多个众数,我们可以取第一个众数
data.apply(lambda x: x.mode().iloc[0] if len(x.mode()) > 0 else None)
-
计算该列的众数(出现次数最多的值);
-
如果众数存在(列非全 NaN),取第一个众数(处理多众数情况);
-
如果众数不存在(列全为 NaN),返回
None;最终返回一个包含每列众数的 Series,常用于分类特征的缺失值填充。
5.线性回归填充
代码:
python
def lr_train_fill(x_data,y_data):
my_data=pd.concat([x_data,y_data],axis=1)
my_data=my_data.reset_index(drop=True)
my_data_x=my_data.drop('矿物类型',axis=1)
null_sum=my_data_x.isnull().sum()
null_sum_sort=null_sum.sort_values(ascending=True)
my_feature=[]
for i in null_sum_sort.index:
my_feature.append(i)
if null_sum_sort[i]!=0:
x=my_data_x[my_feature].drop(i,axis=1)
y=my_data_x[i]
number_null=my_data_x[my_data_x[i].isnull()].index.tolist()
x_train=x.drop(number_null)
x_test=x.iloc[number_null]
y_train=y.drop(number_null)
regr=LinearRegression()
regr.fit(x_train,y_train)
y_pred=regr.predict(x_test)
my_data_x.loc[number_null,i]=y_pred
return my_data_x,my_data.矿物类型
def lr_test_fill(x_data_train, y_data_train, x_data, y_data):
my_data_tr = pd.concat([x_data_train, y_data_train], axis=1)
my_data_tr = my_data_tr.reset_index(drop=True)
my_data_te = pd.concat([x_data, y_data], axis=1)
my_data_te = my_data_te.reset_index(drop=True)
my_data_train = my_data_tr.drop('矿物类型', axis=1)
my_data_test = my_data_te.drop('矿物类型', axis=1)
null_sum = my_data_test.isnull().sum()
null_sum_sort = null_sum.sort_values(ascending=True)
my_feature = []
for i in null_sum_sort.index:
my_feature.append(i)
if null_sum_sort[i] != 0:
x = my_data_train[my_feature].drop(i, axis=1)
y = my_data_train[i]
x_te=my_data_test[my_feature].drop(i, axis=1)
number_null = my_data_test[my_data_test[i].isnull()].index.tolist()
x_test=x_te.iloc[number_null]
regr = LinearRegression()
regr.fit(x, y)
y_pred = regr.predict(x_test)
my_data_test.loc[number_null, i] = y_pred
return my_data_test, my_data_te.矿物类型
1.计算 DataFrame 中每列的缺失值数量,再按缺失值数量升序排列
null_sum=my_data_x.isnull().sum()
null_sum_sort=null_sum.sort_values(ascending=True)
2.筛选出my_data_x中第i列值为NaN的所有行,提取这些行的索引(行号),并转换为列表number_null
number_null=my_data_x[my_data_x[i].isnull()].index.tolist()
3.将有空缺值的行去除用来做训练集,用线性回归进行训练
python
x_train=x.drop(number_null)
x_test=x.iloc[number_null]
y_train=y.drop(number_null)
regr=LinearRegression()
regr.fit(x_train,y_train)
6.随机森林填充
随机森林填充与线性回归的填充一模一样只有训练模型不一样用随机森林模型
python
regr=RandomForestRegressor(n_estimators=100,random_state=0)
regr.fit(x_train,y_train)