概述:
在处理数据之前,需要进行数据质量分析,了解数据的功能和作用,检查原始数据中是否存在脏数据。脏数据一般是指不符合要求以及不能直接进行相应分析的数据。
脏数据往往存在如下问题:没有列头,一个列有多个参数,列数据的单位不统一,存在缺失值、空行、重复数据和非ASCII字符,有些列头应该是数据而不应该是列名参数等等。可将这些问题大致归类为缺失值、异常值和重复值等噪声数据问题。
数据清洗步骤:
-
数据加载和初步处理
- 加载数据:从Excel文件中加载数据。
- 数据筛选:去除“矿物类型”为'E'的行。
data = pd.read_excel("矿物数据.xls") #从数据中筛选出“矿物类型”不是'E'的行。 data=data[data['矿物类型']!='E']
- 空值处理:计算每列的空值数量,但未进行填充或删除。
#找出数据中的空值。 null_num=data.isnull() # 计算每列空值的总数。 null_total=null_num.sum()
- 特征和标签分离:将“矿物类型”作为标签,其余作为特征。
# 从数据中删除'矿物类型'和'序号'这两列,准备作为特征数据。 x_whole=data.drop('矿物类型',axis=1).drop('序号',axis=1) # 将'矿物类型'列作为标签数据。 y_whole=data.矿物类型
- 标签编码:将标签从文本转换为数字。
# 创建一个字典,用于将标签文本转换为数字。 label_dict={"A":0,"B":1,"C":2,"D":3} # 使用列表推导式将标签文本转换为数字。 encoded_label=[label_dict[label] for label in y_whole] # 将转换后的标签数据转换为pandas Series,并命名为“矿物类型”。 y_whole=pd.Series(encoded_label,name="矿物类型")
- 缺失值处理:代码中计算了空值数量,但没有进一步处理这些空值。可以考虑填充或删除这些空值。
# 尝试将每一列的数据转换为数值类型,如果转换失败则用NaN代替。 for column_name in x_whole.columns: x_whole[column_name]=pd.to_numeric(x_whole[column_name],errors='coerce')
- 数据标准化:使用
StandardScaler
对特征进行标准化处理。from sklearn.preprocessing import StandardScaler scaler=StandardScaler() # 使用StandardScaler对特征数据进行标准化。 x_whole_z=scaler.fit_transform(x_whole) # 将标准化后的数据转换回DataFrame。 x_whole=pd.DataFrame(x_whole_z,columns=x_whole.columns)
- 训练集和测试集分割:使用
train_test_split
将数据分为训练集和测试集,测试集占30%。# 从sklearn库中导入train_test_split,用于数据集的分割。 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=5000)
-
缺失值填充:中位数填充:使用自定义的
fill_data.median_train_fill
和fill_data.median_test_fill
方法填充训练集和测试集的缺失值。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)
函数
median_method
这个函数用于填充数据中的缺失值,使用每列的中位数。- 计算中位数:计算数据中每列的中位数。
- 填充缺失值:使用计算得到的中位数填充数据中的缺失值。
def median_method(data): fill_values=data.median() return data.fillna(fill_values)
函数
median_train_fill
这个函数用于填充训练集中的缺失值,按标签分类处理。 - 合并数据:将特征和标签合并到一个DataFrame中。
- 重置索引:重置数据的索引。
- 按标签分类:将数据按标签分类到不同的子集。
- 分类填充:对每个子集使用
median_method
函数填充缺失值。 - 合并填充后的数据:将填充后的子集重新合并为一个完整的DataFrame。
- 重置索引:再次重置索引以确保连续性。
- 数据可视化:在绘制条形图时,添加了标签数量的文本显示,这有助于直观地看到每个类别的数量。
def median_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=median_method(A) B=median_method(B) C=median_method(C) D=median_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.矿物类型
函数
median_test_method
这个函数用于使用训练集中位数填充测试集中的缺失值。 - 计算训练集中位数:计算训练数据中每列的中位数。
- 填充测试数据:使用训练数据的中位数填充测试数据中的缺失值。
def median_test_method(train_data,test_data): fill_values=train_data.median() return test_data.fillna(fill_values)
函数
median_test_fill
这个函数用于填充测试集中的缺失值,按标签分类处理。 - 合并数据:将训练和测试数据分别与标签合并。
- 重置索引:重置数据的索引。
- 按标签分类:将训练和测试数据按标签分类到不同的子集。
- 分类填充:对每个测试数据子集使用
median_test_method
函数填充缺失值。 - 合并填充后的数据:将填充后的子集重新合并为一个完整的DataFrame。
- 重置索引:再次重置索引以确保连续性。
def median_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=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]) df_filled = df_filled.reset_index(drop=True) return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型
- 过采样:使用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)
- 合并标签:将过采样后的训练集标签和测试集标签合并,用于可视化。
labels_count = pd.Series(y_whole).value_counts() fig,ax=plt.subplots() bars=ax.bar(labels_count.index,labels_count.values) for bar in bars: yval=bar.get_height() ax.text(bar.get_x()+bar.get_width()/2,yval,round(yval,2),va='bottom',ha='center',fontsize=10,color='black') plt.xlabel('labels') plt.ylabel('numbers') plt.title('data_fillna_median') plt.show()
-
合并训练数据与测试数据并保存到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)
数据清洗结果
完整代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import fill_data
data = pd.read_excel("矿物数据.xls")
#从数据中筛选出“矿物类型”不是'E'的行。
data=data[data['矿物类型']!='E']
#找出数据中的空值。
null_num=data.isnull()
# 计算每列空值的总数。
null_total=null_num.sum()
# 从数据中删除'矿物类型'和'序号'这两列,准备作为特征数据。
x_whole=data.drop('矿物类型',axis=1).drop('序号',axis=1)
# 将'矿物类型'列作为标签数据。
y_whole=data.矿物类型
# 创建一个字典,用于将标签文本转换为数字。
label_dict={"A":0,"B":1,"C":2,"D":3}
# 使用列表推导式将标签文本转换为数字。
encoded_label=[label_dict[label] for label in y_whole]
# 将转换后的标签数据转换为pandas Series,并命名为“矿物类型”。
y_whole=pd.Series(encoded_label,name="矿物类型")
# 尝试将每一列的数据转换为数值类型,如果转换失败则用NaN代替。
for column_name in x_whole.columns:
x_whole[column_name]=pd.to_numeric(x_whole[column_name],errors='coerce')
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
# 使用StandardScaler对特征数据进行标准化。
x_whole_z=scaler.fit_transform(x_whole)
# 将标准化后的数据转换回DataFrame。
x_whole=pd.DataFrame(x_whole_z,columns=x_whole.columns)
# 从sklearn库中导入train_test_split,用于数据集的分割。
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=5000)
# 二:中位数填充
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)
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)
y_whole=pd.concat([os_y_train,y_test_fill])
labels_count = pd.Series(y_whole).value_counts()
fig,ax=plt.subplots()
bars=ax.bar(labels_count.index,labels_count.values)
for bar in bars:
yval=bar.get_height()
ax.text(bar.get_x()+bar.get_width()/2,yval,round(yval,2),va='bottom',ha='center',fontsize=10,color='black')
plt.xlabel('labels')
plt.ylabel('numbers')
plt.title('data_fillna_median')
plt.show()
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)
fill_data文件
import pandas as pd
import numpy as np
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)
data = data.reset_index(drop=True)
A=data[data['矿物类型']==0]
B=data[data['矿物类型']==1]
C=data[data['矿物类型']==2]
D=data[data['矿物类型']==3]
A=median_method(A)
B=median_method(B)
C=median_method(C)
D=median_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 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_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=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])
df_filled = df_filled.reset_index(drop=True)
return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型