当前位置: 首页 > news >正文

红酒数据集预处理实战:缺失值处理的 5 种打开方式,从入门到进阶一步到位

在数据分析与建模流程中,缺失值处理是数据预处理阶段的关键步骤,直接影响后续模型的准确性与稳定性。本文以红酒数据集为研究对象,详细介绍如何通过基础统计方法(均值、中位数、众数)、完整案例分析(CCA)及机器学习算法(线性回归、随机森林)实现缺失值填充,并提供完整代码实现与结果保存方案,帮助读者系统化掌握缺失值处理逻辑。

一、项目背景与数据概览

1.1 数据集介绍

本项目使用的 “红酒.csv” 数据集包含红酒的多项理化指标(如酒精含量、酸度、糖分等)、矿物类型标签及最终质量评分,目标是通过预处理后的数据构建后续质量预测模型。数据中存在部分缺失值,需先进行填充处理。

1.2 核心需求

  • 查看数据基本结构(前 10 行、后 10 行),了解数据分布;
  • 采用 5 种不同方法处理缺失值,确保数据完整性;
  • 拆分训练集与测试集,按 “训练集规则填充测试集”(避免数据泄露);
  • 保存处理后的数据集,为后续建模提供输入。

二、项目环境与依赖库

首先需安装并导入以下 Python 库,核心用于数据读取、缺失值处理与模型构建:

import pandas as pd  # 数据处理核心库
from sklearn.model_selection import train_test_split  # 数据集拆分
from sklearn.linear_model import LinearRegression  # 线性回归模型
from sklearn.ensemble import RandomForestRegressor  # 随机森林回归模型

三、数据预处理核心流程

3.1 数据读取与初步探索

第一步读取数据并查看基本结构,同时统计缺失值总量,明确后续处理目标:

# 读取红酒数据(根据编码选择gbk或utf-8)
data = pd.read_csv('红酒.csv', encoding='gbk')# 查看数据前10行与后10行,了解数据结构
print("===== 数据前10行 =====")
print(data.head(10))
print("\n===== 数据后10行 =====")
print(data.tail(10))# 统计每列缺失值数量
null_total = data.isnull().sum()
print("\n===== 各列缺失值数量 =====")
print(null_total)# 拆分特征与标签(质量评分为目标变量,矿物类型为类别特征)
x_whole = data.drop(['质量评分'], axis=1)  # 所有特征(含矿物类型)
y_whole = data['质量评分']  # 目标变量:质量评分# 拆分训练集(75%)与测试集(25%),固定随机种子确保结果可复现
x_train, x_test, y_train, y_test = train_test_split(x_whole, y_whole, test_size=0.25, random_state=42
)

3.2 缺失值处理方法详解

为适配不同数据分布场景,本文实现 5 种缺失值处理方法,核心逻辑是 **“按矿物类型分组填充”**(同类红酒理化指标更相似,填充更精准),且严格遵循 “用训练集规则填充测试集” 原则,避免数据泄露。

所有方法封装在fill_data.py文件中,下文分模块解析核心逻辑。

方法 1:完整案例分析(CCA)—— 直接删除缺失值行

适用于缺失值占比极低的场景,直接保留无缺失值的完整样本,优点是简单无偏差,缺点是会损失数据量。

def cca_train_fill(train_data, train_label):"""训练集CCA填充:删除含缺失值的行"""# 合并特征与标签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):"""测试集CCA填充:逻辑与训练集一致,仅处理测试集"""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['矿物类型']
方法 2-4:基础统计填充(均值 / 中位数 / 众数)
  • 均值填充:适用于数据近似正态分布、无极端值的场景;
  • 中位数填充:适用于数据含极端值(如异常高的酒精含量)的场景,抗干扰性更强;
  • 众数填充:适用于类别型或离散型特征(如某类矿物类型的红酒酸度集中在某个值)。

以均值填充为例,核心代码逻辑如下(中位数、众数仅需替换mean()median()/mode()):

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)# 按矿物类型(0-3)分组groups = [data[data['矿物类型'] == i] for i in range(4)]# 每组单独用均值填充filled_groups = [mean_train_method(group) for group in groups]# 合并分组数据df_filled = pd.concat(filled_groups).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled['矿物类型']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)# 按矿物类型分组,用训练集分组均值填充测试集filled_test_groups = []for mineral_type in range(4):# 训练集该类别的均值train_group = train_all[train_all['矿物类型'] == mineral_type]# 测试集该类别数据test_group = test_all[test_all['矿物类型'] == mineral_type]# 用训练集均值填充测试集filled_test = test_group.fillna(train_group.mean())filled_test_groups.append(filled_test)df_filled = pd.concat(filled_test_groups).reset_index(drop=True)return df_filled.drop('矿物类型', axis=1), df_filled['矿物类型']
方法 5:机器学习填充(线性回归 / 随机森林)

适用于特征间存在明显相关性的场景,通过构建预测模型,用其他特征预测缺失值,填充精度更高。核心逻辑是 **“按缺失值数量从小到大处理”**(先填充缺失少的特征,用已填充的特征预测缺失多的特征)。

以随机森林填充为例,核心代码如下:

def rf_train_fill(train_data, train_label):"""训练集随机森林填充:用其他特征预测缺失值"""# 合并特征与标签data = pd.concat([train_data, train_label], axis=1).reset_index(drop=True)train_X = data.drop('矿物类型', axis=1)# 按缺失值数量从小到大排序,确定填充顺序null_num = train_X.isnull().sum()null_sorted = null_num.sort_values(ascending=True)filling_features = []  # 存储已处理的特征(用于构建模型输入)for feat in null_sorted.index:filling_features.append(feat)# 仅处理含缺失值的特征if null_sorted[feat] == 0:continue# 构建模型:以当前特征为目标变量,其他已处理特征为输入X = train_X[filling_features].drop(feat, axis=1)  # 输入特征y = train_X[feat]  # 目标变量(待填充的特征)# 筛选非缺失值样本作为训练集,缺失值样本作为测试集null_rows = train_X[train_X[feat].isnull()].index.tolist()X_train = X.drop(null_rows)y_train = y.drop(null_rows)X_test = X.iloc[null_rows]# 训练随机森林模型rf = RandomForestRegressor(n_estimators=100, random_state=42)rf.fit(X_train, y_train)# 预测缺失值并填充y_pred = rf.predict(X_test)train_X.loc[null_rows, feat] = y_predprint(f'完成训练集「{feat}」列填充')return train_X, data['矿物类型']def rf_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_X = train_all.drop('矿物类型', axis=1)test_X = test_all.drop('矿物类型', axis=1)# 按测试集缺失值数量排序,用训练集规则填充null_num = test_X.isnull().sum()null_sorted = null_num.sort_values(ascending=True)filling_features = []for feat in null_sorted.index:filling_features.append(feat)if null_sorted[feat] == 0:continue# 用训练集的特征构建模型X_train = train_X[filling_features].drop(feat, axis=1)y_train = train_X[feat]X_test = test_X[filling_features].drop(feat, axis=1)# 筛选测试集缺失值行null_rows = test_X[test_X[feat].isnull()].index.tolist()X_test = X_test.iloc[null_rows]# 训练模型并预测填充rf = RandomForestRegressor(n_estimators=100, random_state=42)rf.fit(X_train, y_train)y_pred = rf.predict(X_test)test_X.loc[null_rows, feat] = y_predprint(f'完成测试集「{feat}」列填充')return test_X, test_all['矿物类型']

3.3 数据保存与后续使用

填充完成后,需将训练集与测试集合并为完整 DataFrame,并保存为 Excel 文件,方便后续建模使用。同时对训练集进行随机打乱,避免顺序对模型训练的影响:

# 选择一种填充方法(以CCA为例,其他方法只需替换函数名)
x_train_fill, y_train_fill = fill_data.cca_train_fill(x_train, y_train)
x_test_fill, y_test_fill = fill_data.cca_test_fill(x_train, y_train, x_test, y_test)# 合并特征与标签,训练集随机打乱
data_train = pd.concat([x_train_fill, y_train_fill], axis=1).sample(frac=1, random_state=4)
data_test = pd.concat([x_test_fill, y_test_fill], axis=1)# 保存到本地(需提前创建“数据”文件夹)
data_train.to_excel('./数据/训练空值删除填充.xlsx', index=False)
data_test.to_excel('./数据/测试空值删除填充.xlsx', index=False)
print("数据保存完成!")

四、各方法对比与适用场景

不同缺失值处理方法各有优劣,需根据数据特点选择,下表为核心对比:

处理方法优点缺点适用场景
CCA(删除行)简单无偏差,不引入额外信息损失数据量,样本代表性下降缺失值占比 < 5%,数据量充足
均值填充计算简单,保留数据量受极端值影响大数据近似正态分布,无极端值
中位数填充抗极端值,稳定性强未利用特征相关性数据含极端值(如酒精含量异常值)
众数填充适用于离散型 / 类别型特征不适用于连续型特征离散特征(如某类矿物类型的酸度)
随机森林填充利用特征相关性,填充精度高计算复杂,需调参特征间相关性强,数据量中等

五、总结与后续优化方向

5.1 项目总结

本项目以红酒数据集为载体,完整实现了从 “数据探索→缺失值处理→结果保存” 的预处理流程,核心亮点:

  1. 严格遵循 “训练集规则填充测试集”,避免数据泄露;
  2. 按 “矿物类型分组填充”,贴合红酒数据的业务逻辑;
  3. 覆盖基础到进阶的 5 种方法,适配不同数据场景。

5.2 后续优化方向

  1. 填充效果评估:可通过 “插入人工缺失值” 的方式,对比不同方法的填充误差(如 MAE、RMSE);
  2. 特征标准化:在机器学习填充前对特征进行标准化(如StandardScaler),提升模型预测精度;
  3. 分类任务适配:若目标是 “红酒质量分级”(如好 / 中 / 差),可将随机森林回归改为分类器(RandomForestClassifier)。

通过本文的方法,可快速完成红酒数据集的缺失值处理,为后续的质量预测模型(如线性回归、随机森林、SVM)提供高质量的输入数据。

http://www.dtcms.com/a/345031.html

相关文章:

  • vue-admin-template权限管理
  • 信创认证是什么?怎么报考?
  • 特级资质信息化迎检核心流程经验分享
  • Pod控制器详解
  • STM32之ADC详解
  • [系统架构设计师]大数据架构设计理论与实践(十九)
  • ​维基框架 (Wiki Framework) 1.1.0 版本发布​ 提供多模型AI辅助开发
  • TNS(ORACLE)协议分析
  • [硬件电路-162]:PID参数受哪些因素影响?
  • 【Redis】缓存和分布式锁
  • MySQL - 视图,事务和索引
  • AAA 服务器与 RADIUS 协议笔记
  • C语言初学笔记【联合与枚举】
  • Unreal Engine USceneComponent
  • 如何实现二维CAD与3D建模工程图关联一体化出图 | 中望3D 2026新亮点
  • android sdk 虚拟机是否可以通过命令行打开?
  • 数字逻辑与数字系统设计之电梯控制器设计
  • 防爆连接器在防爆箱上的作用
  • shell脚本第二阶段-----选择结构
  • Unreal Engine IWYU Include What You Use
  • DLT645仪表通信,串口助手调试读写地址
  • 【C#】观察者模式 + UI 线程调度、委托讲解
  • vuex如何在js文件中使用
  • NVIDIA GB200 架构详解及与 B200/H200/H100 的区别
  • 【芯芯相印】芯片设计生产全流程核心技术术语与实践指南:从架构定义到量产交付的完整图谱
  • NLP学习之Transformer(2)
  • 数据预处理学习笔记
  • Thunderbird 将推出在德国托管的加密电子邮件服务
  • Android Jetpack | Hilt
  • 快速了解深度学习