用Python构建居民健康画像:从问卷数据到SVM分类实战
当健康管理遇上机器学习,数据科学正在重新定义我们对个体健康的理解方式。想象一下,通过一份简单的问卷数据,就能预测一个人的慢性病风险,并为其量身定制健康建议——这正是数学建模竞赛中深圳杯A题试图解决的问题,也是医疗健康领域数据应用的典型场景。本文将带你用Python完整复现这一过程,从原始问卷清洗到SVM模型构建,最终生成可解释的健康分类报告。
1. 健康数据分析的基础准备
1.1 环境配置与数据加载
健康数据分析的第一步是搭建合适的Python环境。推荐使用Anaconda创建独立环境,避免包版本冲突:
conda create -n health_analysis python=3.8 conda activate health_analysis pip install pandas scikit-learn matplotlib seaborn加载数据时,需要特别注意医疗数据的特殊性。原始问卷通常包含大量分类变量和缺失值:
import pandas as pd # 加载原始问卷数据 raw_data = pd.read_excel('health_survey.xlsx', sheet_name='A2') # 显示数据结构概览 print(f"数据集维度:{raw_data.shape}") print("前5行样本:\n", raw_data.head())典型健康问卷数据包含以下字段类型:
- 人口统计学特征:年龄、性别、职业等
- 生活习惯指标:吸烟频率、饮酒量、运动时长
- 饮食记录:各类食物摄入频率
- 健康结局:慢性病诊断结果
1.2 数据清洗与特征工程
医疗数据清洗需要遵循特殊原则。例如,对于"每周饮酒次数"这样的敏感问题,缺失值可能意味着被调查者不愿透露而非数据收集错误:
# 处理缺失值的策略示例 def clean_medical_data(df): # 连续变量用中位数填充 num_cols = ['age', 'exercise_hours'] df[num_cols] = df[num_cols].fillna(df[num_cols].median()) # 分类变量新增'unknown'类别 cat_cols = ['smoking_status', 'drinking_freq'] df[cat_cols] = df[cat_cols].fillna('unknown') return df cleaned_data = clean_medical_data(raw_data)特征工程阶段需要将医学知识编码到特征中。例如,根据膳食指南将原始饮食记录转化为营养评分:
# 饮食健康评分计算示例 def calculate_diet_score(row): score = 0 # 蔬菜水果摄入 if row['vegetable_freq'] >= 5: score += 2 elif row['vegetable_freq'] >= 3: score += 1 # 红肉摄入控制 if row['redmeat_freq'] <= 2: score += 1 return score cleaned_data['diet_score'] = cleaned_data.apply(calculate_diet_score, axis=1)2. 探索性分析与可视化
2.1 健康指标分布分析
使用Seaborn绘制关键健康指标的分布图,可以直观发现人群健康趋势:
import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) sns.boxplot(x='health_status', y='age', data=cleaned_data) plt.title('不同健康状况人群的年龄分布') plt.show()常见健康数据模式包括:
- 年龄相关性:慢性病患病率随年龄增长而上升
- 性别差异:男性吸烟率通常高于女性
- 职业影响:久坐职业人群运动量普遍不足
2.2 特征相关性热力图
计算Spearman相关系数(适用于有序分类变量)并可视化:
# 选择数值型特征计算相关性 numeric_cols = ['age', 'bmi', 'exercise_hours', 'diet_score'] corr_matrix = cleaned_data[numeric_cols].corr(method='spearman') plt.figure(figsize=(10, 8)) sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0) plt.title('健康特征相关性热力图') plt.show()提示:医疗数据相关性分析需谨慎解读,相关不等于因果。建议结合临床知识验证统计发现。
3. 构建SVM健康分类模型
3.1 数据预处理与划分
将分类变量转换为机器学习模型可处理的数值形式:
from sklearn.preprocessing import OrdinalEncoder from sklearn.model_selection import train_test_split # 定义分类变量编码规则 cat_cols = ['smoking_status', 'drinking_freq'] encoder = OrdinalEncoder(categories=[['never', 'occasional', 'regular', 'heavy', 'unknown']]*2) cleaned_data[cat_cols] = encoder.fit_transform(cleaned_data[cat_cols]) # 划分特征和目标变量 X = cleaned_data.drop('health_status', axis=1) y = cleaned_data['health_status'] # 数据集划分 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42)3.2 SVM模型训练与调优
使用网格搜索寻找最优核函数和正则化参数:
from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV # 定义参数网格 param_grid = { 'C': [0.1, 1, 10], 'kernel': ['linear', 'rbf'], 'gamma': ['scale', 'auto'] } # 创建并训练模型 svm_model = GridSearchCV(SVC(probability=True), param_grid, cv=5) svm_model.fit(X_train, y_train) # 输出最佳参数 print(f"最佳参数组合:{svm_model.best_params_}") print(f"交叉验证准确率:{svm_model.best_score_:.3f}")3.3 模型评估与解释
医疗模型评估需特别关注对少数类(如患病群体)的识别能力:
from sklearn.metrics import classification_report, confusion_matrix # 测试集预测 y_pred = svm_model.predict(X_test) # 输出分类报告 print(classification_report(y_test, y_pred)) # 绘制混淆矩阵 cm = confusion_matrix(y_test, y_pred) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel('预测标签') plt.ylabel('真实标签') plt.show()关键评估指标解读:
- 召回率(Recall):正确识别出的实际患者比例
- 精确率(Precision):预测为患者中真正患病的比例
- F1分数:召回率和精确率的调和平均
4. 健康画像生成与应用
4.1 居民健康分类策略
基于SVM预测概率进行精细化分类:
# 获取预测概率 probs = svm_model.predict_proba(X_test)[:, 1] # 定义风险等级阈值 low_risk = probs < 0.3 medium_risk = (probs >= 0.3) & (probs < 0.7) high_risk = probs >= 0.7 # 统计各风险人群比例 print(f"低风险人群占比:{low_risk.mean():.1%}") print(f"中风险人群占比:{medium_risk.mean():.1%}") print(f"高风险人群占比:{high_risk.mean():.1%}")4.2 个性化健康建议生成
为不同风险群体生成针对性的健康建议模板:
def generate_health_recommendation(row): if row['risk_level'] == 'high': return f"""尊敬的{row['age']}岁{row['gender']}性: 根据分析,您患慢性病的风险较高。建议: 1. 立即戒烟限酒 2. 每周至少150分钟中等强度运动 3. 增加蔬菜水果摄入至每日500g""" elif row['risk_level'] == 'medium': return "..." else: return "..." # 应用建议生成函数 health_report = test_data.apply(generate_health_recommendation, axis=1)4.3 模型部署与持续学习
将训练好的模型封装为可复用管道:
from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler # 创建完整管道 health_pipe = Pipeline([ ('scaler', StandardScaler()), ('svm', SVC(C=1, kernel='rbf', gamma='scale', probability=True)) ]) # 保存模型到文件 import joblib joblib.dump(health_pipe, 'health_risk_predictor.pkl')在实际应用中,模型需要定期用新数据重新训练以保持预测准确性。建议设置自动化retraining流程,当数据分布变化超过阈值时触发模型更新。