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

机器学习——数据清洗

数据科学项目中缺失值填充的全面指南

一、数据准备与原始值保留策略

1.1 创建数据副本的最佳实践

在数据清洗过程中,保持原始数据的完整性至关重要。我们建议采用以下两种复制策略:

  1. 完全独立副本:使用Python的copy模块创建深层副本,确保所有嵌套数据结构都被完全复制

    import copy
    original_data = copy.deepcopy(data)  # 完全独立的原始数据副本
    
  2. 工作副本:使用pandas的copy()方法创建工作副本

    working_data = data.copy(deep=True)  # 深度复制,确保不影响原始数据
    

应用场景:在金融数据分析项目中,原始交易记录必须保持不可变,而清洗操作在工作副本上进行。

1.2 详细的缺失值标记方法

为每个存在缺失值的列创建标记列,记录原始缺失情况:

for col in working_data.columns:if working_data[col].isnull().any():  # 检查列是否有缺失值working_data[f'{col}_missing'] = working_data[col].isnull().astype(int)# 存储缺失位置信息,1表示缺失,0表示存在

实际应用:在医疗数据集中,标记哪些血压值是估算的,哪些是实际测量的,这对后续分析至关重要。

二、基础统计填充方法的深入解析

2.1 众数填充的完整实现(适合分类变量)

from scipy.stats import modedef fill_with_mode(df, column):# 计算众数(忽略缺失值)mode_result = mode(df[column].dropna())mode_value = mode_result.mode[0] if len(mode_result.mode) > 0 else None# 创建填充列并保留原始值filled_col = f'{column}_filled_mode'df[filled_col] = df[column].fillna(mode_value)return df# 示例:填充产品类别中的缺失值
data = fill_with_mode(data, 'product_category')

注意事项:当所有值都相同时众数可能不存在,需添加异常处理。

2.2 平均数填充的增强版(适合正态分布数值变量)

def fill_with_mean(df, column, groupby_col=None):if groupby_col:# 分组计算均值(如按地区计算平均收入)group_means = df.groupby(groupby_col)[column].transform('mean')df[f'{column}_filled_mean'] = df[column].fillna(group_means)else:# 整体均值填充global_mean = df[column].mean()df[f'{column}_filled_mean'] = df[column].fillna(global_mean)return df# 示例1:整体均值填充年龄
data = fill_with_mean(data, 'age')# 示例2:按部门填充工资均值
data = fill_with_mean(data, 'salary', 'department')

优化建议:对于偏态分布数据,考虑使用对数转换后的均值。

2.3 中位数填充的稳健实现(适合偏态分布数据)

def fill_with_median(df, column, clip_outliers=True):if clip_outliers:# 移除极端值后计算中位数q1 = df[column].quantile(0.25)q3 = df[column].quantile(0.75)iqr = q3 - q1filtered = df[column][(df[column] >= q1-1.5*iqr) & (df[column] <= q3+1.5*iqr)]median_value = filtered.median()else:median_value = df[column].median()df[f'{column}_filled_median'] = df[column].fillna(median_value)return df# 示例:填充房屋价格(考虑去除异常值)
data = fill_with_median(data, 'house_price', clip_outliers=True)

适用场景:在收入、房价等通常右偏的数据中,中位数比平均数更能代表典型值。

三、机器学习填充方法的实现

3.1 数据预处理的完整流程

from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.impute import SimpleImputer# 分类变量编码
def encode_categorical(df, cat_cols):le_dict = {}for col in cat_cols:le = LabelEncoder()df[col+'_encoded'] = le.fit_transform(df[col].fillna('Missing'))le_dict[col] = le  # 保存编码器供后续使用return df, le_dict# 数值变量标准化
def scale_numeric(df, num_cols):scaler = StandardScaler()df[num_cols] = scaler.fit_transform(df[num_cols])return df, scaler# 示例预处理流程
data, encoders = encode_categorical(data, ['department', 'job_title'])
data, scaler = scale_numeric(data, ['age', 'salary'])

关键点:始终保存预处理对象,以便对新数据应用相同转换。

3.2 线性回归填充的完整实现

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_splitdef fill_with_regression(df, target_col, feature_cols):# 分离完整数据和缺失数据complete = df[df[target_col].notnull()]missing = df[df[target_col].isnull()]if len(complete) < 10:  # 样本量不足时退回均值填充return fill_with_mean(df, target_col)# 划分训练测试集X = complete[feature_cols]y = complete[target_col]X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)# 训练模型model = LinearRegression()model.fit(X_train, y_train)# 预测缺失值if not missing.empty:X_missing = missing[feature_cols]predictions = model.predict(X_missing)df.loc[df[target_col].isnull(), f'{target_col}_filled_lr'] = predictionsreturn df, model# 示例:用学历和工作年限预测收入
data, lr_model = fill_with_regression(data, target_col='income',feature_cols=['education_years', 'work_experience']
)

评估指标:建议检查模型在测试集上的R²值,确保预测质量。

3.3 随机森林填充的高级实现

from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_errordef fill_with_rf(df, target_col, feature_cols, n_estimators=100):complete = df[df[target_col].notnull()]missing = df[df[target_col].isnull()]if len(complete) < 30:  # 随机森林需要更多样本return fill_with_median(df, target_col)X = complete[feature_cols]y = complete[target_col]X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)# 使用交叉验证选择最佳参数model = RandomForestRegressor(n_estimators=n_estimators,random_state=42,n_jobs=-1  # 使用所有CPU核心)model.fit(X_train, y_train)# 评估模型y_pred = model.predict(X_test)mse = mean_squared_error(y_test, y_pred)print(f'Test MSE: {mse:.2f}')# 填充缺失值if not missing.empty:X_missing = missing[feature_cols]predictions = model.predict(X_missing)df.loc[df[target_col].isnull(), f'{target_col}_filled_rf'] = predictionsreturn df, model# 示例:用多种特征预测客户生命周期价值
data, rf_model = fill_with_rf(data,target_col='customer_lifetime_value',feature_cols=['age', 'income', 'purchase_frequency', 'region']
)

优化建议:使用GridSearchCV进行超参数调优,考虑特征重要性分析。

四、填充结果比较与分析

4.1 可视化

import matplotlib.pyplot as plt
import seaborn as snsdef compare_distributions(df, original_col, filled_cols):plt.figure(figsize=(12, 6))# 绘制原始分布(仅非缺失值)sns.kdeplot(df[original_col].dropna(), label='Original', linewidth=3)# 绘制各填充方法分布for method in filled_cols:sns.kdeplot(df[method], label=method.replace('_filled_', ' '))plt.title('Distribution Comparison')plt.xlabel(original_col)plt.ylabel('Density')plt.legend()plt.show()# 示例:比较年龄的不同填充结果
compare_distributions(data,original_col='age',filled_cols=['age_filled_mean', 'age_filled_median', 'age_filled_rf']
)

扩展功能:添加Q-Q图比较分位数分布,或箱线图比较统计量。

4.2 统计比较

def comprehensive_stats_compare(df, original_col, filled_cols):stats = pd.DataFrame()# 原始数据统计(仅非缺失值)stats['Original'] = df[original_col].describe()# 各填充方法统计for col in filled_cols:stats[col.replace('_filled_', ' ')] = df[col].describe()# 添加额外指标additional_stats = pd.DataFrame({'Skewness': [df[original_col].skew()] + [df[col].skew() for col in filled_cols],'Kurtosis': [df[original_col].kurtosis()] + [df[col].kurtosis() for col in filled_cols],'Missing %': [df[original_col].isnull().mean()*100] + [0]*len(filled_cols)}, index=['Original'] + [col.replace('_filled_', ' ') for col in filled_cols])return stats.T.join(additional_stats)# 示例:生成详细的统计比较报告
stats_report = comprehensive_stats_compare(data,original_col='income',filled_cols=['income_filled_mean', 'income_filled_median', 'income_filled_lr']
)print(stats_report.round(2))

http://www.xdnf.cn/news/18282.html

相关文章:

  • 【论文阅读】Multi-metrics adaptively identifies backdoors in Federated Learning
  • Linux 文本处理与 Shell 编程笔记:正则表达式、sed、awk 与变量脚本
  • 本地文件上传到gitee仓库的详细步骤
  • Excel表格复制到word中格式错乱
  • Nginx 的完整配置文件结构、配置语法以及模块详解
  • 【学习笔记】大话设计模式——一些心得及各设计模式思想记录
  • Vue3全局配置Loading的完整指南:从基础到实战
  • PyTorch API 4
  • Mac 4步 安装 Jenv 管理多版本JDK
  • Linux Capability 解析
  • strncpy 函数使用及其模拟实现
  • 为什么我的UI界面会突然卡顿,失去响应
  • 安装使用Conda
  • pyqt 的自动滚动区QScrollArea
  • Rust 入门 包 (二十一)
  • Ubuntu 虚拟显示器自动控制服务设置(有无显示器的切换)
  • 华为数通认证学习
  • 微算法科技(NASDAQ: MLGO)引入高级区块链DSR算法:重塑区块链网络安全新范式
  • K8S-Configmap资源
  • C++中的 Eigen库使用
  • 数据库DML语言(增、删、改)
  • oracle服务器导入dmp文件
  • Causal-Copilot: An Autonomous Causal Analysis Agent 论文解读
  • 栈的概念(韦东山学习笔记)
  • C#APP.Config配置文件解析
  • Java内功修炼(2)——线程安全三剑客:synchronized、volatile与wait/notify
  • 5.4 4pnpm 使用介绍
  • kotlin 协程笔记
  • AI 创业公司分析报告:RealRoots
  • 0基础安卓逆向原理与实践:第2章:编程基础与工具链