心脏病数据挖掘过程
一、加载数据源
# 如果没有安装数据源所依赖的库,则先安装数据源所在的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