【数据挖掘】通过心脏病数据案例熟悉数据挖掘的完整过程

发布于:2025-03-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

心脏病数据挖掘过程

一、加载数据源

# 如果没有安装数据源所依赖的库,则先安装数据源所在的python库: pip install ucimlrepo
# 引入pandas和ucimlrepo
import pandas as pd
from ucimlrepo import fetch_ucirepo

# fetch dataset Heart Disease dataset的Id为45
heart_disease = fetch_ucirepo(id=45) 

二、筛选数据

# data (as pandas dataframes) 
X = heart_disease.data.features  # 特征
y = heart_disease.data.targets   # 标签
  
# 可先查看下metadata 
# print(heart_disease.metadata) 
  
# 再看下变量信息 variable information 
# print(heart_disease.variables)

# 查看X是什么样子的数据
# X
# 查看y是什么样子的数据

三、数据预处理

3.1 将特征数据和标签数据整合
# 为使得数据集符合逻辑回归算法训练时需要的训练数据集的形式,即特征+标签,也就是有标签的数据集,需要将X和y进行合并
X['target'] = y
# 取出前几行查看下X
# X.head(5)
3.2 判断数据集中是否有缺失值
# 使用 isnull() 函数找出所有缺失值,并统计每列的缺失数量
missing_values = X.isnull().sum()
# print(missing_values)
3.3 将缺失值进行处理
# 对于缺失值可选择的处理方法如下:
# 1. 均值填充: 适用于正态分布的数据。
# 2. 中位数填充: 适用于非正态分布或存在异常值的数据。
# 3. 删除样本: 当缺失值较多时,可能导致数据量大幅减少,需谨慎使用。
# 计算每列的均值,并用这些均值填充缺失值 准确度 54%
mean_values = X.mean()
df_fill_mean = X.fillna(mean_values)

# 计算每列的中位数,并用这些中位数填充缺失值 准确度54%
# median_values = X.median()
# df_fill_median = X.fillna(median_values)

# 删除所有包含缺失值的行   准确度为 54%
# df_fill_median = X.dropna()
3.4 检查缺失值处理后的数据情况
# 检查填充后的数据
print(df_fill_mean.isnull().sum())
age         0
sex         0
cp          0
trestbps    0
chol        0
fbs         0
restecg     0
thalach     0
exang       0
oldpeak     0
slope       0
ca          0
thal        0
target      0
dtype: int64
3.5 数据分析

分析每个特征与目标变量的关系

import matplotlib.pyplot as plt

# 为方便,重新用变量来表达数据集
df = df_fill_mean

# 绘制目标变量分布图
df['target'].value_counts().plot(kind='bar')
plt.title('Heart Disease Distribution')
plt.show()

# 选择age年龄特征来进行分析,查看年龄分布情况(按是否有心脏病分组)
# df.groupby('target') :这部分的意思是根据“target”列对数据框进行分组。例如,在Heart Disease数据集中,“target”表示是否患有心脏病(0或1)。所以这一步会将数据分成两个组:一个是有心脏病的患者,另一个是没有心脏病的患者。 
# ['age'] :接下来,我们指定只使用“age”这一列的数据。也就是说,我们要分析每个分组中年龄的分布情况。 
# .hist() :调用hist方法,这是pandas的一个函数,用于绘制直方图。直方图可以展示数据的分布情况,比如年龄的分布。 
# bins=15 :这个参数指定将数据分成15个桶(bin)。每个桶代表一个年龄段,这样可以让图表更清晰地显示不同年龄段的分布情况。 
# figsize=(10,6) :设置图的大小,宽为10英寸,高为6英寸。这一步是为了让图表在展示时看起来更舒服,不会太小或太大。 
df.groupby('target')['age'].hist(bins=15, figsize=(10,6))

# 绘制直方图
# 运行这行代码后,会生成一个包含两个直方图的图表:
# 第一个是 'target' 为 0 的组(没有心脏病患者)的年龄分布。
# 第二个是 'target' 为 1 的组(有心脏病患者)的年龄分布。
# 这两个直方图将帮助你直观地比较两种不同类别中的年龄分布情况,例如:
# 是否有心脏病患者中存在明显的年龄段差异?
# 年龄较大的人是否更容易患心脏病?
plt.title('Age Distribution by Heart Disease Status')
plt.xlabel('Age')
plt.ylabel('Count')
plt.show()

在这里插入图片描述
在这里插入图片描述

3.6 分析结论

特征会影响目标的取值,目标变量target取值为[0,4],其中0表示没有心脏病,1-4表示有心脏病,只是程度不一样。由此,看出挖掘这部分数据可选用分类算法来完成,而且是选择二分类算法,比如逻辑回归算法、SVM算法等。这里我们选择逻辑回归,它是一种用于分类任务的统计方法,适用于二元分类问题。它通过拟合一个逻辑函数(sigmoid 函数)来预测目标变量的概率

四、模型构建(数据挖掘-算法选择)

4.1 划分训练数据集和测试数据
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# 分割数据集为训练集和测试集
X = df.drop('target', axis=1)
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
4.2 数据标准化处理
# 标准化(因为逻辑回归对特征尺度敏感)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
4.3 模型训练
# 训练逻辑回归模型
log_reg = LogisticRegression(max_iter=1000, random_state=42)
log_reg.fit(X_train, y_train)

五、模型预测

# 预测
y_pred_log = log_reg.predict(X_test)
y_pred_log
array([2, 1, 2, 0, 0, 3, 2, 2, 0, 0, 0, 0, 1, 2, 2, 0, 0, 3, 3, 0, 1, 0,
       3, 0, 3, 0, 0, 1, 3, 0, 0, 1, 0, 0, 0, 1, 3, 0, 3, 0, 2, 0, 1, 0,
       0, 2, 0, 0, 3, 1, 0, 0, 0, 0, 3, 0, 0, 3, 3, 2, 0], dtype=int64)

六、模型评估

from sklearn.metrics import roc_auc_score, confusion_matrix
import seaborn as sns

# 真实值
y_true = y_test

# 预测值
y_pred = y_pred_log

# 计算准确率
accuracy = accuracy_score(y_true, y_pred)

# 计算精确率、召回率和F1分数
precision = precision_score(y_true, y_pred,average='weighted')
recall = recall_score(y_true, y_pred,average='macro')
f1 = f1_score(y_true, y_pred,average='macro')

# 计算ROC AUC值(适用于二分类)
if len(set(y_true)) == 2:
    auc = roc_auc_score(y_true, y_pred_proba)
else:
    auc = None

# 可视化混淆矩阵
conf_matrix = confusion_matrix(y_true, y_pred)
plt.figure(figsize=(10, 7))
sns.heatmap(conf_matrix, annot=True, fmt='d')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()

print(f"Accuracy: {accuracy}")
print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"F1 Score: {f1}")

if auc is not None:
    print(f"AUC: {auc}")

执行结果如下:

D:\Program Files\Python312\Lib\site-packages\sklearn\metrics\_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
      _warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))

可视化混淆矩阵:
在这里插入图片描述
准确度、精确率、召回率和F1分数:
Accuracy: 0.5409836065573771
Precision: 0.5119535519125683
Recall: 0.3308976464148878
F1 Score: 0.3170415108810277