【B题解题思路】2025APMCM亚太杯中文赛B题解题思路+可运行代码参考(无偿分享)
注:该内容由“数模加油站”原创,无偿分享,可以领取参考但不要利用该内容倒卖,谢谢!
B 题 疾病的预测与大数据分析
问题1思路框架:
在解决问题 1 时,我们首先需要对三个疾病数据集(stroke.csv、heart.csv 和 cirrhosis.csv)进行深入的数据预处理。数据预处理的目标是将原始数据转化为适合模型分析的格式,消除噪声,处理缺失值,并对数据进行标准化,确保数据的质量和一致性。
数据预处理的主要步骤包括:
数据清理与填补缺失值:
检查数据集中的缺失值,针对不同类型的缺失值采用不同的填补方式,如均值填补、中位数填补或众数填补。对于分类变量,采用众数填补;对于数值型变量,使用均值或中位数填补。
数据类型转换:
确保每个特征的数据类型正确。例如,性别、是否吸烟等类别变量需要转换为二元变量(0或1),或者使用One-Hot编码转化为多个二元特征;数值型特征需要确保其数值范围和单位一致。
异常值检测与处理:
使用箱线图、Z-Score等方法检测数据中的异常值,并根据实际情况选择是否删除或修正这些异常值。
标准化与归一化:
对数值型数据进行标准化处理,使得所有特征的均值为 0,标准差为 1,避免由于不同量纲造成的模型偏差。标准化公式如下:
其中,x 为特征的原始值, 为特征的均值,\sigma 为特征的标准差
数据可视化与基础统计分析:
使用图表(如直方图、箱线图等)对各个特征进行可视化,观察数据的分布情况,尤其是对异常值和数据分布的不对称性进行检查。
计算每个特征的基本统计量(均值、方差、标准差、最大值、最小值等),并进行相关性分析。使用皮尔逊相关系数来评估不同特征之间的相关性:
其中, 为特征 X 和 Y 的协方差,
和
为特征 X 和 Y 的标准差。根据相关性分析的结果,我们可以选出对疾病发生有较大影响的关键特征。
数学模型构建:
- 相关性分析模型:
利用皮尔逊相关系数()或Spearman等级相关系数来评估特征之间的线性或非线性相关性。此步骤有助于我们识别出可能影响疾病发生的特征。
对于中风(stroke)预测,我们可能发现年龄(Age)、高血压(Hypertension)、吸烟状态(SmokingStatus)等特征与疾病发生高度相关。我们用以下公式来表达相关性:
标准化处理模型:
通过标准化公式对所有数值型特征进行归一化处理,确保数据的一致性。对于每个特征,我们将其变换为均值为 0,标准差为 1 的分布:
这种标准化不仅有助于消除不同量纲的影响,还能加快后续机器学习算法的收敛速度,提升算法的性能。
缺失值填补模型:
对于缺失值的处理,我们使用均值填补、中位数填补或者众数填补,具体方法依据数据的类型(数值型或类别型)进行选择。如果数据缺失率过高,则可能需要对相关特征进行删除。
模型算法求解:
相关性分析:
使用皮尔逊相关系数、Spearman相关系数等方法对数据集中的特征进行分析,计算出特征之间的相关性。假设我们需要计算年龄(Age)和中风发生(Stroke)之间的相关性:
该结果能帮助我们识别年龄是否为中风的一个重要预测因子。
标准化算法:
对所有的数值型特征进行标准化。设 为特征 X 的原始数据,标准化后我们得到新特征 z_1, z_2, \dots, z_n,计算公式如下:
其中, 是所有数据点的均值,
是标准差。这一过程能够消除不同特征之间的量纲差异,使其在后续的机器学习模型中具有相同的重要性。
可视化与数据分析:
使用箱线图(Boxplot)和直方图等方法对数据进行可视化,进一步检查特征的分布、异常值和偏态。如果某个特征的分布极度偏斜,可以考虑进行对数转换或其他数学转换来优化数据的分布。
计算每个特征的均值、标准差、最大值、最小值等基本统计量,用来进一步分析数据的分布情况:
通过这些统计量,我们可以了解每个特征的基本分布,从而决定是否进行转换或调整。
Python代码:
# 导入所需的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer# 读取数据集
stroke_data = pd.read_csv("stroke.csv")
heart_data = pd.read_csv("heart.csv")
cirrhosis_data = pd.read_csv("cirrhosis.csv")# 1. 数据预处理: 缺失值处理
# 使用SimpleImputer进行缺失值填补,数值型特征填补均值,类别型特征填补众数
imputer_num = SimpleImputer(strategy="mean") # 数值型数据填补均值
imputer_cat = SimpleImputer(strategy="most_frequent") # 类别型数据填补众数# 选择每个数据集中的数值型特征
stroke_num_cols = ['age', 'hypertension', 'avg_glucose_level', 'bmi'] # 根据stroke数据集的列选择数值型特征
heart_num_cols = ['Age', 'RestingBP', 'Cholesterol', 'MaxHR', 'Oldpeak'] # 根据heart数据集的列选择数值型特征
cirrhosis_num_cols = ['Age', 'Bilirubin', 'Cholesterol', 'Albumin', 'Copper', 'Alk_Phos', 'SGOT', 'Tryglicerides','Platelets', 'Prothrombin'] # 根据cirrhosis数据集的列选择数值型特征# 填补数值型数据
stroke_data[stroke_num_cols] = imputer_num.fit_transform(stroke_data[stroke_num_cols])
heart_data[heart_num_cols] = imputer_num.fit_transform(heart_data[heart_num_cols])
cirrhosis_data[cirrhosis_num_cols] = imputer_num.fit_transform(cirrhosis_data[cirrhosis_num_cols])# 填补类别型数据
stroke_cat_cols = ['gender', 'ever_married', 'work_type', 'Residence_type', 'smoking_status'] # 根据stroke数据集的列选择类别型特征
heart_cat_cols = ['Sex', 'ChestPainType', 'FastingBS', 'RestingECG', 'ExerciseAngina','ST_Slope'] # 根据heart数据集的列选择类别型特征
cirrhosis_cat_cols = ['ID', 'Status', 'Drug', 'Sex', 'Ascites', 'Hepatomegaly', 'Spiders', 'Edema','Stage'] # 根据cirrhosis数据集的列选择类别型特征stroke_data[stroke_cat_cols] = imputer_cat.fit_transform(stroke_data[stroke_cat_cols])
heart_data[heart_cat_cols] = imputer_cat.fit_transform(heart_data[heart_cat_cols])
cirrhosis_data[cirrhosis_cat_cols] = imputer_cat.fit_transform(cirrhosis_data[cirrhosis_cat_cols])# 2. 数据标准化
scaler = StandardScaler()# 对数值型特征进行标准化
stroke_data[stroke_num_cols] = scaler.fit_transform(stroke_data[stroke_num_cols])
heart_data[heart_num_cols] = scaler.fit_transform(heart_data[heart_num_cols])
cirrhosis_data[cirrhosis_num_cols] = scaler.fit_transform(cirrhosis_data[cirrhosis_num_cols])# 3. 数据可视化: 直方图与箱线图
# 直方图:查看数值型特征的分布
def save_histogram(data, columns, title="Feature Distribution", filename="histogram.png"):plt.figure(figsize=(12, 6))for i, col in enumerate(columns):plt.subplot(2, 4, i + 1) # 设置2行4列的子图sns.histplot(data[col], kde=True, color='skyblue', bins=20)plt.title(f"{title}: {col}")plt.tight_layout()plt.savefig(filename)plt.close()# 选择中风数据集的数值型特征并保存图像
save_histogram(stroke_data, stroke_num_cols, filename="stroke_histogram.png")# 箱线图:查看异常值
def save_boxplot(data, columns, title="Boxplot for Features", filename="boxplot.png"):plt.figure(figsize=(12, 6))for i, col in enumerate(columns):plt.subplot(2, 4, i + 1) # 设置2行4列的子图sns.boxplot(x=data[col], color='lightgreen')plt.title(f"{title}: {col}")plt.tight_layout()plt.savefig(filename)plt.close()# 选择中风数据集的数值型特征并保存图像
save_boxplot(stroke_data, stroke_num_cols, filename="stroke_boxplot.png")# 4. 相关性分析:计算皮尔逊相关系数并可视化
def save_correlation_heatmap(data, title="Correlation Heatmap", filename="correlation_heatmap.png"):# 选择数值型特征进行相关性计算num_data = data.select_dtypes(include=[np.number])corr = num_data.corr() # 计算相关系数矩阵plt.figure(figsize=(10, 8))sns.heatmap(corr, annot=True, cmap="coolwarm", fmt=".2f", linewidths=0.5)plt.title(f"{title}")plt.savefig(filename)plt.close()# 计算并保存中风数据集的相关性热图
save_correlation_heatmap(stroke_data, filename="stroke_correlation_heatmap.png")# 5. 计算描述性统计量
def display_summary_statistics(data):return data.describe()# 显示中风数据集的描述性统计量
stroke_summary = display_summary_statistics(stroke_data)
print("Summary Statistics for Stroke Data:")
print(stroke_summary)# 6. 查看不同疾病数据的基础信息
def display_data_info(data, dataset_name="Dataset"):print(f"{dataset_name} Info:")print(data.info())print("\n")# 查看各个数据集的基础信息
display_data_info(stroke_data, "Stroke Data")
display_data_info(heart_data, "Heart Data")
display_data_info(cirrhosis_data, "Cirrhosis Data")
后续都在“数模加油站”......