机器学习之数据清洗及六种缺值处理方式

数据清洗及六种缺值处理方式

目录

  • 数据清洗及六种缺值处理方式
    • [1 数据清洗](#1 数据清洗)
      • [1.1 概念](#1.1 概念)
      • [1.2 重要性](#1.2 重要性)
      • [1.3 注意事项](#1.3 注意事项)
    • [2 查转空值及数据类型转换和标准化](#2 查转空值及数据类型转换和标准化)
      • [2.1 空值为空](#2.1 空值为空)
      • [2.2 空值不为空](#2.2 空值不为空)
        • [2.2.1 结果](#2.2.1 结果)
      • [2.3 类型转换和标准化处理](#2.3 类型转换和标准化处理)
    • [3 六种缺值处理方式](#3 六种缺值处理方式)
      • [3.1 数据介绍](#3.1 数据介绍)
      • [3.2 涉及函数导入及变量](#3.2 涉及函数导入及变量)
      • [3.3 删除空行填充](#3.3 删除空行填充)
      • [3.4 平均值填充](#3.4 平均值填充)
      • [3.5 中位数填充](#3.5 中位数填充)
      • [3.6 众数填充](#3.6 众数填充)
      • [3.7 线性填充](#3.7 线性填充)
      • [3.8 随机森林填充](#3.8 随机森林填充)
    • [4 数据保存](#4 数据保存)
    • [5 代码集合测试](#5 代码集合测试)

1 数据清洗


1.1 概念

数据清洗(Data Cleaning)是指从数据集中识别并纠正或删除不准确、不完整、格式不统一或与业务规则不符的数据的过程 。这个过程是数据预处理的一个重要组成部分,其目的是提高数据的质量,确保数据的一致性和准确性,从而为数据分析、数据挖掘和机器学习等后续数据处理工作提供可靠的基础。数据清洗是一个反复迭代的过程,可能需要多次调整和优化以达到理想的效果。

1.2 重要性

数据清洗是数据处理过程中的重要环节,它涉及到将原始数据转换为可用、可靠和有意义的形式,以便进行进一步的分析和挖掘。

数据清洗是数据科学和数据分析领域的一个重要步骤,因为它直接影响到后续分析结果的准确性和可靠性。不干净的数据可能会导致错误的结论和决策。

1.3 注意事项

  • 1.完整性 :检查单条数据是否存在空值 ,统计的字段是否完善
  • 2.全面性:观察某一列的全部数值,可以通过比较最大值、最小值、平均值、数据定义等来判断数据是否全面。
  • 3.合法性 :检査数值的类型、内容、大小是否符合预设的规则。例如,人类的年龄超过1000岁这个数据就是不合法的。
  • 4.唯一性 :检查数据是否重复记录,例如一个人的数据被重复记录多次。
  • 5.类别是否可靠

2 查转空值及数据类型转换和标准化


2.1 空值为空

  • null_num = data.isnull()
    判断是否为空,为空填充为True
  • null_all = null_num.sum()
    计算空值数量

2.2 空值不为空

  • data.replace('NA', '', inplace=True)
    空值为NA填充,替换为空再计算
    null_num = data.isnull()
    null_all = null_num.sum()
2.2.1 结果

调试结果:

null_num = data.isnull()

null_all

处理后原数据

2.3 类型转换和标准化处理

  • 特征数据类型转换为数值
    pd.to_numeric(数据,errors='coerce')
  • 标准化处理
    scaler = StandardScaler()
    x_all_z = scaler.fit_transform(x_all)

调试结果:

x_all_z

3 六种缺值处理方式


3.1 数据介绍

部分数据展示,第一列为序号,最后一行为结果类别,其他为特征变量

3.2 涉及函数导入及变量

python 复制代码
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor

train_data,train_label,test_data,test_label分别为训练集变量、结果和测试集变量、结果,结果列名为质量评分

3.3 删除空行填充

python 复制代码
# 删除空行
def cca_train_fill(train_data,train_label):
    data = pd.concat([train_data, train_label], axis=1)
    #reset_index()重新排序
    data = data.reset_index(drop=True)
    #dropna()删除空行
    df_filled = data.dropna()
    #dropna()删除空行
    df_filled = df_filled.reset_index(drop=True)
    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)
    data = data.reset_index(drop=True)
    df_filled = data.dropna()
    df_filled = df_filled.reset_index(drop=True)
    return df_filled.drop('矿物类型', axis=1), df_filled.矿物类型

3.4 平均值填充

python 复制代码
# 平均数
# 填充训练集平均值
def mean_train_method(data):
	# 数据的平均值
    fill_values = data.mean()
    # fillna(平均值)填充平均值
    # 返回数据填充后结果
    return data.fillna(fill_values)

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_filled = pd.concat([A,B,C,D])
    df_filled = df_filled.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_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_filled = pd.concat([A,B,C,D])
    df_filled = df_filled.reset_index(drop=True)
    return df_filled.drop('矿物类型', axis=1),df_filled.矿物类型

3.5 中位数填充

python 复制代码
# 中位数
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)
    data = data.reset_index(drop=True)

    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_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.矿物类型

3.6 众数填充

python 复制代码
# 众数
def mode_train_method(data):
	# apply()每列应用函数
	# 执行函数如果有众数个数不为0或空,填充第一个
    fill_values = data.apply(lambda x:x.mode().iloc[0] if len(x.mode())>0 else None)
    # 每列众数
    a = data.mode()
    return data.fillna(fill_values)

def mode_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 = mode_train_method(A)
    B = mode_train_method(B)
    C = mode_train_method(C)
    D = mode_train_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 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_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 = 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_filled = pd.concat([A,B,C,D])
    df_filled = df_filled.reset_index(drop=True)
    return df_filled.drop('矿物类型', axis=1),df_filled.矿物类型

3.7 线性填充

python 复制代码
def lr_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)
        # 该列空值个数不为0
        if null_num_sorted[i] != 0:
        	# x为去除当前含空列的其他列特征数据
            x = train_data_x[filling_feature].drop(i,axis=1)
            # y为含空列所有数据
            y = train_data_x[i]
			# 空列行索引列表
            row_numbers_null_list = train_data_x[train_data_x[i].isnull()].index.tolist()
            # 训练集x为去除空行的x
            x_train = x.drop(row_numbers_null_list)
            # 训练集y为去除空行的y
            y_train = y.drop(row_numbers_null_list)
            # 测试集空行的x数据
            x_test = x.iloc[row_numbers_null_list]
            lr = LinearRegression()
            lr.fit(x_train,y_train)
            # 预测空值结果
            y_pr = lr.predict(x_test)
            train_data_x.loc[row_numbers_null_list,i] = y_pr
            print(f'完成训练数据集中的{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)
    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)

    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_null_list = test_data_x[test_data_x[i].isnull()].index.tolist()
            x_test = x_test.iloc[row_numbers_null_list]

            lr = LinearRegression()
            # 根据训练集数据进行测试集数据空值填充
            lr.fit(x_train,y_train)
            y_pr = lr.predict(x_test)
            test_data_x.loc[row_numbers_null_list,i] = y_pr
            print(f'完成测试数据集中的{i}列数据清洗')
    return test_data_x,test_data_all.矿物类型

3.8 随机森林填充

python 复制代码
# 随机森林
def Random_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_null_list = train_data_x[train_data_x[i].isnull()].index.tolist()
            x_train = x.drop(row_numbers_null_list)
            y_train = y.drop(row_numbers_null_list)
            x_test = x.iloc[row_numbers_null_list]

            lr = RandomForestRegressor(n_estimators=100,max_features=0.8,random_state=314,n_jobs=-1)
            lr.fit(x_train,y_train)
            y_pr = lr.predict(x_test)
            train_data_x.loc[row_numbers_null_list,i] = y_pr
            print(f'完成训练数据集中的{i}列数据清洗')
    return train_data_x,train_data_all.矿物类型

def Random_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)

    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_null_list = test_data_x[test_data_x[i].isnull()].index.tolist()
            x_test = x_test.iloc[row_numbers_null_list]

            lr = RandomForestRegressor(n_estimators=100,max_features=0.8,random_state=314,n_jobs=-1)
            lr.fit(x_train,y_train)
            y_pr = lr.predict(x_test)
            test_data_x.loc[row_numbers_null_list,i] = y_pr
            print(f'完成测试数据集中的{i}列数据清洗')
    return test_data_x,test_data_all.矿物类型

4 数据保存

不同处理方法得到的数据应分别保存,更改[ ]内内容即可

代码展示:

python 复制代码
data_train = pd.concat([ov_x_train,ov_y_train],axis=1).sample(frac=1,random_state=4)
data_test = pd.concat([x_test_fill,y_test_fill],axis=1).sample(frac=1,random_state=4)
data_train.to_excel(r'./data_train_test//训练数据集[随机森林回归].xlsx',index=False)
data_test.to_excel(r'./data_train_test//测试数据集[随机森林回归].xlsx',index=False)

5 代码集合测试

为便于处理,将数据填充另封装为file_data,便于应用

全部代码展示:

python 复制代码
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import file_data
from imblearn.over_sampling import SMOTE

data = pd.read_excel('矿物数据.xls')

data = data[data['矿物类型'] != 'E']
# 空值为nan
null_num = data.isnull()
# 计算空值数量
null_all = null_num.sum()

x_all = data.drop('矿物类型',axis=1).drop('序号',axis=1)
y_all = data.矿物类型
# 转换结果类别类型
label_dict = {'A':0,'B':1,'C':2,'D':3}
encod_labels = [label_dict[label] for label in y_all]
# 类别转serises
y_all = pd.Series(encod_labels,name='矿物类型')
# 特征数据类型转换为数值
for column_name in x_all.columns:
    x_all[column_name] = pd.to_numeric(x_all[column_name],errors='coerce')
# 标准化处理
scaler = StandardScaler()
x_all_z = scaler.fit_transform(x_all)
x_all = pd.DataFrame(x_all_z,columns=x_all.columns)

x_train,x_test,y_train,y_test = \
    train_test_split(x_all,y_all,test_size=0.3,random_state=50000)
### 按注释依次使用不同填充缺值数据
# cca
# x_train_fill,y_train_fill = file_data.cca_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = file_data.cca_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 平均值
# x_train_fill,y_train_fill = file_data.mean_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = file_data.mean_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 中位数
# x_train_fill,y_train_fill = file_data.median_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = file_data.median_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 众数
# x_train_fill,y_train_fill = file_data.mode_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = file_data.mode_test_fill(x_train_fill,y_train_fill,x_test,y_test)
#
# lr_train_fill线性回归
# x_train_fill,y_train_fill = file_data.lr_train_fill(x_train,y_train)
# x_test_fill,y_test_fill = file_data.lr_test_fill(x_train_fill,y_train_fill,x_test,y_test)
# 随机森林回归
x_train_fill,y_train_fill = file_data.Random_train_fill(x_train,y_train)
x_test_fill,y_test_fill = file_data.Random_test_fill(x_train_fill,y_train_fill,x_test,y_test)

#打乱顺序
oversampler = SMOTE(k_neighbors=1,random_state=42)
ov_x_train,ov_y_train = oversampler.fit_resample(x_train_fill,y_train_fill)

# 数据存储
data_train = pd.concat([ov_x_train,ov_y_train],axis=1).sample(frac=1,random_state=4)
data_test = pd.concat([x_test_fill,y_test_fill],axis=1).sample(frac=1,random_state=4)

data_train.to_excel(r'./data_train_test//训练数据集[随机森林回归].xlsx',index=False)
data_test.to_excel(r'./data_train_test//测试数据集[随机森林回归].xlsx',index=False)

依次运行结果:


相关推荐
缘来是黎2 分钟前
Python 进阶:生成器与上下文管理器
java·前端·python
yc_239 分钟前
语义分割文献阅读——SETR:使用Transformer从序列到序列的角度重新思考语义分割
人工智能·深度学习·transformer
深圳市快瞳科技有限公司12 分钟前
杜绝遛狗不牵绳,AI技术助力智慧城市宠物管理
人工智能·智慧城市·宠物
大雄野比16 分钟前
Python 实现 macOS 系统代理的设置
python·macos·策略模式
豆豆酱22 分钟前
强化学习到大模型训练理论概要(一)
人工智能·算法
山海青风23 分钟前
OpenAI 实战进阶教程 - 第十二节 : 多模态任务开发(文本、图像、音频)
图像处理·人工智能·python·ai作画·音视频·语音识别
2501_904447741 小时前
荣耀已接入DeepSeek-R1,荣耀手机系统版本MagicOS8.0及以上用户可用
人工智能·智能手机·virtualenv·scikit-learn·tornado
LaughingZhu1 小时前
PH热榜 | 2025-02-10
人工智能·经验分享·产品运营
不爱原创的Yoga1 小时前
【AI】人工智能与搜索引擎知识了解
人工智能·搜索引擎
shadowcz0071 小时前
Open-Interface:基于大语言模型 LLM 的自动化界面操作系统
运维·人工智能·语言模型·自然语言处理·自动化