心血管疾病数据预处理实战:7万条Kaggle数据清洗与特征工程3步法
心血管疾病数据预处理实战7万条Kaggle数据清洗与特征工程3步法心血管疾病是全球范围内导致死亡的主要原因之一准确预测心血管疾病风险对于早期干预和治疗至关重要。在机器学习项目中数据预处理环节往往决定了模型的成败。本文将带您深入实战从Kaggle获取的7万条心血管疾病数据出发通过三个核心步骤完成数据清洗与特征工程的全流程。1. 数据质量诊断与异常值处理数据清洗是机器学习项目中最耗时但至关重要的环节。在开始建模之前我们需要对数据进行全面体检识别并处理可能影响模型性能的问题点。1.1 数据概览与缺失值分析首先加载数据集并进行初步检查import pandas as pd import numpy as np # 加载数据 df pd.read_csv(cardio_data.csv) # 查看数据基本信息 print(f数据集形状: {df.shape}) print(\n前5行数据:) print(df.head()) print(\n数据统计描述:) print(df.describe()) print(\n缺失值统计:) print(df.isnull().sum())对于心血管疾病数据集常见的字段包括年龄、性别、血压、胆固醇水平等。检查缺失值时我们发现这个数据集比较完整没有明显的缺失值。但在实际项目中如果遇到缺失数据处理策略包括删除缺失率高的特征60%缺失对连续变量使用均值/中位数填补对分类变量使用众数填补使用预测模型估算缺失值1.2 异常值检测与处理异常值会严重影响模型的性能我们需要系统性地识别和处理它们# 血压异常值处理 - 舒张压不应高于收缩压 df df[df[ap_lo] df[ap_hi]] # 生理指标异常值 - 使用IQR方法 def remove_outliers(df, column): Q1 df[column].quantile(0.25) Q3 df[column].quantile(0.75) IQR Q3 - Q1 lower_bound Q1 - 1.5 * IQR upper_bound Q3 1.5 * IQR return df[(df[column] lower_bound) (df[column] upper_bound)] columns_to_check [height, weight, ap_hi, ap_lo] for col in columns_to_check: df remove_outliers(df, col) # 年龄转换为年数原始数据为天数 df[age] (df[age] / 365).round().astype(int)处理后的数据更加干净但要注意过度清洗可能导致信息丢失。建议保留清洗前后的数据版本便于后续对比分析。1.3 数据一致性检查确保数据逻辑一致性是预处理的关键一步# 检查血压值是否在合理范围内 df df[(df[ap_hi] 90) (df[ap_hi] 250)] df df[(df[ap_lo] 60) (df[ap_lo] 150)] # 检查BMI是否合理 df[bmi] df[weight] / (df[height]/100)**2 df df[(df[bmi] 15) (df[bmi] 50)]通过以上步骤我们得到了一个干净、一致的数据集为后续特征工程打下了坚实基础。2. 特征工程从原始数据到模型输入特征工程是将原始数据转化为模型可理解形式的过程好的特征可以显著提升模型性能。2.1 基础特征构建基于领域知识创建有意义的特征# 计算BMI分类 df[bmi_category] pd.cut(df[bmi], bins[0, 18.5, 25, 30, 100], labels[underweight, normal, overweight, obese]) # 血压分类 def categorize_bp(row): if row[ap_hi] 120 and row[ap_lo] 80: return normal elif 120 row[ap_hi] 130 and row[ap_lo] 80: return elevated elif (130 row[ap_hi] 140) or (80 row[ap_lo] 90): return hypertension_stage1 elif (row[ap_hi] 140) or (row[ap_lo] 90): return hypertension_stage2 else: return other df[bp_category] df.apply(categorize_bp, axis1) # 年龄分组 df[age_group] pd.cut(df[age], bins[30, 40, 50, 60, 70, 80], labels[30-39, 40-49, 50-59, 60-69, 70-79])2.2 交互特征与多项式特征特征间的交互作用可能包含重要信息# 交互特征 df[chol_bp_interaction] df[cholesterol] * df[ap_hi] df[bmi_age_interaction] df[bmi] * df[age] # 多项式特征 df[age_squared] df[age] ** 2 df[bmi_squared] df[bmi] ** 22.3 特征编码与标准化将分类变量转换为数值形式并对连续变量进行标准化from sklearn.preprocessing import StandardScaler, OneHotEncoder # 分类变量编码 cat_cols [gender, cholesterol, gluc, smoke, alco, active, bmi_category, bp_category, age_group] encoder OneHotEncoder(dropfirst, sparseFalse) encoded_features encoder.fit_transform(df[cat_cols]) encoded_df pd.DataFrame(encoded_features, columnsencoder.get_feature_names_out(cat_cols)) # 连续变量标准化 cont_cols [age, height, weight, ap_hi, ap_lo, bmi] scaler StandardScaler() scaled_features scaler.fit_transform(df[cont_cols]) scaled_df pd.DataFrame(scaled_features, columnscont_cols) # 合并处理后的特征 final_df pd.concat([df[cardio], scaled_df, encoded_df], axis1)2.4 特征选择使用统计方法和模型评估特征重要性from sklearn.ensemble import RandomForestClassifier from sklearn.feature_selection import SelectKBest, f_classif # 分离特征和目标变量 X final_df.drop(cardio, axis1) y final_df[cardio] # 使用随机森林评估特征重要性 rf RandomForestClassifier(n_estimators100, random_state42) rf.fit(X, y) # 可视化特征重要性 import matplotlib.pyplot as plt plt.figure(figsize(12, 8)) feat_importances pd.Series(rf.feature_importances_, indexX.columns) feat_importances.nlargest(15).plot(kindbarh) plt.title(Top 15 Important Features) plt.show() # 选择最佳特征 selector SelectKBest(score_funcf_classif, k20) X_selected selector.fit_transform(X, y) selected_features X.columns[selector.get_support()]通过特征选择我们保留了最具预测力的特征减少了模型复杂度提高了泛化能力。3. 数据分割与验证策略正确的数据分割和验证策略对于评估模型真实性能至关重要。3.1 分层抽样与数据分割确保训练集和测试集中各类别比例一致from sklearn.model_selection import train_test_split # 分层抽样保持类别比例 X_train, X_test, y_train, y_test train_test_split( X_selected, y, test_size0.2, stratifyy, random_state42 ) print(f训练集形状: {X_train.shape}) print(f测试集形状: {X_test.shape}) print(\n训练集类别分布:) print(y_train.value_counts(normalizeTrue)) print(\n测试集类别分布:) print(y_test.value_counts(normalizeTrue))3.2 交叉验证策略使用交叉验证更可靠地评估模型性能from sklearn.model_selection import StratifiedKFold # 定义分层K折交叉验证 cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) # 交叉验证示例 from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score model LogisticRegression(max_iter1000) scores cross_val_score(model, X_train, y_train, cvcv, scoringroc_auc) print(f交叉验证AUC得分: {scores.mean():.3f} ± {scores.std():.3f})3.3 处理类别不平衡心血管疾病数据通常存在类别不平衡问题from imblearn.over_sampling import SMOTE # 使用SMOTE处理类别不平衡 smote SMOTE(random_state42) X_train_res, y_train_res smote.fit_resample(X_train, y_train) print(\n重采样后类别分布:) print(pd.Series(y_train_res).value_counts())3.4 特征重要性可视化理解模型决策依据对医疗应用至关重要# 训练最终模型并可视化特征重要性 final_model RandomForestClassifier(n_estimators200, random_state42) final_model.fit(X_train_res, y_train_res) # 获取特征重要性 importances final_model.feature_importances_ indices np.argsort(importances)[::-1] # 绘制特征重要性 plt.figure(figsize(12, 8)) plt.title(Feature Importances) plt.barh(range(len(indices[:15])), importances[indices[:15]][::-1], colorb, aligncenter) plt.yticks(range(len(indices[:15])), [selected_features[i] for i in indices[:15]][::-1]) plt.xlabel(Relative Importance) plt.show()通过以上三个核心步骤我们完成了从原始数据到模型就绪数据的完整预处理流程。这套方法不仅适用于心血管疾病预测也可迁移到其他医疗预测任务中。