python 心脏病可视化和分类预测
一、 问题分析的背景和意义
背景:心脏病是人类健康的头号杀手,全世界1/3的人口死亡是心脏病引起的。而我国,每年有几十万人死于心脏病。如果可以通过提取人体相关的体测指标,通过数据挖掘方式来分析不同特征对于心脏病的影响,将对预防心脏病起到至关重要的作用。
意义:此数据集可以用于分析患者患有心脏病是否与本身患有的其他疾病有关系,为预测心脏病提供决策支持。例如,通过分析心脏病分类预测数据集,我们可以得出结论,年龄越大、不运动的患者得心脏病的可能性越高,或者患者本身患有的某些疾病与心脏病之间存在显著的相关性等。
二、 数据来源
数据文件heart.csv已经放入网盘里,需要可自行下载
链接:https://pan.baidu.com/s/1xjMOCrEzLLHkARP90q2iAw
提取码:2323
数据集说明:心脏病分类预测数据集是指针对心脏病患者分类的相关数据集。这类数据集通常包含了关于患者的基本信息,包括年龄、性别、静息血压、胆固醇等,以及患者是否患有其他疾病的相关信息,包括心绞痛、糖尿病、地中海贫血等。
三、 数据预处理
1.加载第三方库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')
import warnings
warnings.filterwarnings('ignore')
import matplotlib
from sklearn import metrics
from scipy.stats import pearsonr
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
print('第三方库加载成功')
2.读取数据文件,展示数据信息
heart = pd.read_csv('heart.csv')
heart.head()
3.将数据集复制一份,查看数据类型,数据大小,描述性统计
data = heart.copy()
data.dtypes
data.shape
data.describe()
4.查看重复值和缺失值
data.drop_duplicates()
data.isnull().sum()
删除数据中的重复值后,数据大小与先前的一样,说明没有重复值。
查询的各列缺失值的数目都为0,没有数据缺失。
5.查看年龄列的异常值判定
X = 'age'
print(X+':')
mean1 = data[X].quantile(q = 0.25) # 下四分位差
mean2 = data[X].quantile(q = 0.75) # 上四分位差
mean3 = mean2 - mean1 # 中位差
topnum2 = mean2 + 1.5*mean3
bottomnum2 = mean2 - 1.5*mean3
print("正常值的范围:", topnum2, bottomnum2)
print("是否存在超出正常范围的值:", any(data[X]>topnum2))
print("是否存在小于正常范围的值:", any(data[X]<bottomnum2))
使用上四中位数和下四中位数进行异常值判定,得出正常值的范围在40-81岁之间,由于这一属性列是年龄,只能说明大部分的值在40-81岁之间,但是也有在这些年龄以外的情况,所以超过了这个区间的年龄不算异常值。
6.特征编码
# 特征编码
size_mapping = {'male': 1,'female': 0}
data['sex'] = data['sex'].map(size_mapping)
size_mapping1 = {'normal': 1,'fixed defect': 2,'reversable defect':3}
data['thal'] = data['thal'].map(size_mapping1)
data
对数据集进行特征编码,将数据集里的文本型数据转换为数值型数据。
四、数据可视化分析(使用pyecharts库)
1.是否患病情况数量 – 饼图
data['target'].value_counts()from pyecharts import Pie
attr = ['正常','患病']
data = [138,165]
pie = Pie("是否患病情况数量")
# 是否直接显示label信息
pie.add("", attr, data, is_label_show=True)
pie.render("issick.html")from IPython.display import IFrame
IFrame(src='./issick.html', width=800, height=450)
没有患心脏病人数是:138,没有患心脏病的比例是: 45.54%;患有心脏病的人数是:165, 患有心脏病的比例是:54.46%。数据集里两类人数相差不是很大。
2.不同年龄段的人患心脏病的情况 – 条形图
# 由于年龄过于分散,将年龄拆分成不同段
age_distDf = pd.DataFrame()# 用pd.cut() 将年龄进行分割
age_distDf['age_range'] = pd.cut(x = data['age'],bins = [0,18,40,60,100],include_lowest = True,right=False,labels = ['儿童','青年','中年','老年'])# 将原数据集的target合并到age_distDf中
age_distDf = pd.concat([age_distDf['age_range'],data['target']],axis=1)
age_distDf.head()at = age_distDf.groupby(["age_range","target"]).agg({'target':'count'})
at.rename(columns={'target':'amount'},inplace=True)
at = at.reset_index()
print(at)from pyecharts import Bar
columns = ['儿童','青年','中年','老年']
data1 = [0, 4, 82, 52]
data2 = [0, 12, 115, 38]
bar = Bar("不同年龄段的人患心脏病的情况")
bar.add("未得心脏病的人数", columns, data1)
bar.add("患心脏病的人数", columns, data2)
bar.render("agesick.html")from IPython.display import IFrame
IFrame(src='./agesick.html', width=800, height=450)
患心脏的人群里,儿童为0人,青年为12人,中年为115人,老年为38人;不患心脏病的人群里,儿童为0人,青年为4人,中年为82人,老年为52人。患心脏病的人群里,中年人和老年人都比较多。
3.不同年龄段人群患病情况 – 3d柱状图
from pyecharts import Bar3Dbar3d = Bar3D("3D 柱状图示例", width=1200, height=600)
x_axis = ['儿童', '青年','中年', '老年']
y_axis = ['健康', '患病']
data = [[0, 0, 0], [1, 0, 0],[0, 1, 4], [1, 1, 12],[0, 2, 82], [1, 2, 115],[0, 3, 52], [1, 3, 38]]
range_color = ['#313695', '#4575b4']
bar3d.add("",x_axis,y_axis,[[d[1], d[0], d[2]] for d in data],is_visualmap=True,visual_range=[0, 20],visual_range_color=range_color,grid3d_width=200,grid3d_depth=80,
)
bar3d.render("bar3d.html")from IPython.display import IFrame
IFrame(src='./bar3d.html', width=1000, height=600)
青年人的患病率高于老年人的患病率,很大程度上和现代青年人压力大,熬夜,缺乏运动等不健康的生活方式有关。
4.不同性别人群患病情况 – 漏斗图
atyy = data.groupby(["sex","target"]).agg({'target':'count'})
atyy.rename(columns={'target':'amount'},inplace=True)
atyy = atyy.reset_index()
print(atyy)from pyecharts import Funnelx_movies_name = ["女性正常", "女性患心脏病", "男性患心脏病病", "男性正常"]
y_16 = [24, 72, 93, 114]
funnel = Funnel("不同性别人群患病情况")
funnel.add("不同性别人群患病情况", x_movies_name, y_16)
funnel.render("funnel.html")from IPython.display import IFrame
IFrame(src='./funnel.html', width=900, height=450)
从上图可以看出,女性正常的人数有24人,女性患心脏病的人数有72人;男性正常的人数有114人,男性患心脏病的人数有93人。总的来说,女性患心脏病的比例高于男性。
5.不同胸痛类型的患病情况 – 折线图
atcp = data.groupby(["cp","target"]).agg({'target':'count'})
atcp.rename(columns={'target':'amount'},inplace=True)
atcp = atcp.reset_index()
print(atcp)from pyecharts import Page
from pyecharts import Line
page = Page()
attr = ['典型心绞痛', '非典型心绞痛', '非心绞痛', '没有症状']
line1 = Line("不同胸痛类型与患病的关系")
line1.add("正常人群",attr,[104,9,18,7],mark_point=["max", "min"],mark_line=["average"],mark_point_symbol="arrow",mark_point_textcolor="#40ff27",mark_point_symbolsize=25,
)
line1.add("患心脏病人群",attr,[39,41,69,16],mark_point=["max", "min"],mark_line=["average"],yaxis_formatter="",mark_point_symbol="diamond",mark_point_symbolsize=25,
)
page.add(line1)
page.render("line.html")from IPython.display import IFrame
IFrame(src='./line.html', width=800, height=450)
典型性心绞痛患者得心脏病的概率比较低,只是单纯的心绞痛,并非心脏病,而其他类心绞痛患者得心脏病的几率比价高,说明心脏病和心绞痛类型存在一定的关系。
6.心率与静息血压的关系 – 散点图
tandt = data[['trestbps','thalach']]
print(tandt)
from pyecharts import Scatter #散点图
v1 =tandt.trestbps
v2 =tandt.thalach
scatter =Scatter("心率与静息血压的关系", title_pos='center', background_color='white', title_top='90%')
scatter.add("静息血压", v1, v2)
scatter.add("心率", v1[::-1], v2)
scatter.show_config()
scatter.render("scatter.html")from IPython.display import IFrame
IFrame(src='./scatter.html', width=800, height=450)
由上图可以看出,心率和静息血压之间相关性很高,数据点都比较集中,横轴代表静息血压,大部分的值都位于80-200之间,纵轴代表心率,大部分的值也是位于80-200之间。
7.运动与心脏病的关系 – 阶梯图
atex = data.groupby(["exang","target"]).agg({'target':'count'})
atex.rename(columns={'target':'amount'},inplace=True)
atex = atex.reset_index()
print(atex)from pyecharts import Linedata_x = ['不运动的正常人群', '不运动的患病人群', '运动的正常人群', '运动的患病人群']
data_y = [62,142,76,23]line = Line(title='运动与心脏病关系阶梯图')
line.add(name='Sum', x_axis=data_x, y_axis=data_y, is_step=True, is_label_show=True, yaxis_min=15, yaxis_max=160, legend_text_color='red')
line.render('step.html')from IPython.display import IFrame
IFrame(src='./step.html', width=800, height=450)
运动引起的心绞痛诊断为心脏病的概率比较低。所以只是运动是有心绞痛的现象,首先考虑可能是其他疾病,但是如果本身有心脏病,要听从医嘱静养,高强度的运动还是会引起心绞痛的。
8.地中海贫血的血液疾病与心脏病的关系 – 环形图
t = data.groupby(["thal","target"]).agg({'target':'count'})
t.rename(columns={'target':'amount'},inplace=True)
t = t.reset_index()
print(t)from pyecharts import Pie
from pyecharts import options as opts
c = Pie()
L1 = ["thal=1,正常","thal=1,患心脏病","thal=2,正常","thal=2,患心脏病","thal=3,正常","thal=3,患心脏病"]
num = [13,7,36,130,89,28]
c.add("",attr = L1,value =num,radius=["40%","75%"])
# c.set_global_opts(title_opts=opts.TitleOpts(title='Pie圆环'),
# legend_opts=opts.LegendOpts(orient='vertical',pos_top='5%',pos_left="2%"))
# c.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}"))
c.render("c.html")from IPython.display import IFrame
IFrame(src='./c.html', width=800, height=450)
当地中海贫血的类型为2,也就是固定缺陷,并且属于患心脏病的人群这一类最多,为130人,这可能说明地中海贫血与患心脏病之间有一定的联系。
9.运动高峰的心电图各类型数量情况 – 线性_闪烁图
data['slope'].value_counts()from pyecharts import Line,EffectScatter,Overlap
attr = ['上坡','平坦','下坡']
v1 = [21,140,142]
line = Line('线性_闪烁图示例')
line.add('',attr,v1,is_random = True)es = EffectScatter()
es.add('',attr,v1,effect_scale=8) #闪烁
overlop = Overlap()
overlop.add(line) #必须先添加line,在添加es
overlop.add(es)
overlop.render('./line-es01.html')from IPython.display import IFrame
IFrame(src='./line-es01.html', width=800, height=450)
当运动高峰的心电图的类型为上坡,为21人,当运动高峰的心电图的类型为平坦,为140人,当运动高峰的心电图的类型为下坡,为142人.
10.不同性别的人的空腹血糖情况 – 线性_柱状图
s = data.groupby(["sex","fbs"]).agg({'fbs':'count'})
s.rename(columns={'fbs':'amount'},inplace=True)
s = s.reset_index()
print(s)from pyecharts import Bar,Line,Overlap
attr = ['女性血糖<120mg/d','女性血糖>120mg/d','男性血糖<120mg/d','男性血糖>120mg/d']
v1 = [84,12,174,33]
v2 = [84,12,174,33]
bar = Bar('Line - Bar示例')
bar.add('bar',attr,v1)
line = Line()
line.add('line',attr,v2)overlop = Overlap()
overlop.add(bar)
overlop.add(line)
overlop.render('./line-bar01.html')from IPython.display import IFrame
IFrame(src='./line-bar01.html', width=800, height=450)
当女性血糖<120mg/d时人数为84人,当女性血糖>120mg/d时为12人,当男性血糖<120mg/d时为174人,当男性血糖>120mg/d时为33人。由此可以看出,数据集里的男性或者女性的血糖普遍都是低于120mg/d。
11.查看不同特征之间的相关关系
# 查看不同特征之间的相关关系
plt.figure(figsize=(12,10))
corr = data.corr()
sns.heatmap(data=corr,annot=True, square=True,fmt='.2f')
plt.show()
五、建模预测
1.独热处理
# 采用get_dummies()编码方式处理非连续性分类数据
cp_dummies= pd.get_dummies(data['cp'],prefix = 'cp')
restecg_dummies = pd.get_dummies(data['restecg'],prefix='restecg')
slope_dummies = pd.get_dummies(data['slope'],prefix='slope')
thal_dummies = pd.get_dummies(data['thal'],prefix='thal')# 将原数据中经过独热编码的列删除
heart_new = data.drop(['cp','restecg','slope','thal'],axis=1)
heart_new = pd.concat([heart_new,cp_dummies,restecg_dummies,slope_dummies,thal_dummies],axis=1)
heart_new.head()
2.分离出数据和标签
# 分离出数据和标签
label = heart_new['target']
data = heart_new.drop('target',axis=1)
data.shape
3.归一化处理
# 数据集合的不同特征之间数据相差有点大,对于SVM、KNN等算法,会产生权重影响,因此需要归一化处理数据
from sklearn.preprocessing import StandardScaler
standardScaler = StandardScaler()
standardScaler.fit(data)
data = standardScaler.transform(data)
4.拆分训练集,测试集
# 拆分训练集,测试集
from sklearn.model_selection import train_test_split
train_X,test_X,train_y,test_y = train_test_split(data,label,random_state=3)
train_X.shape
5.KNN近邻法
# 构建模型
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier()
#训练数据
knn.fit(train_X,train_y)
# 预测数据
knn_pred_y = knn.predict(test_X)
# 评估模型
knn.score(train_X,train_y)knn.score(test_X,test_y)accuracy_score(test_y,knn_pred_y)
模型的测试集得分和准确率为86.842%
6.使用网格搜索寻找更好的模型参数
from sklearn.model_selection import GridSearchCV
knn = KNeighborsClassifier()
param_test = [{'n_neighbors':[i for i in range(1,31)],'weights':['uniform']},{'n_neighbors':[i for i in range(1,21)],'weights':['distance'],'p':[i for i in range(1,6)]}
]
knn_gv = GridSearchCV(estimator = knn,param_grid=param_test,cv=5)
knn_gv.fit(train_X,train_y)# 最优参数
knn_gv.best_params_knn = KNeighborsClassifier(n_neighbors=16,p=3,weights='distance')#训练数据
knn.fit(train_X,train_y)# 预测数据
knn_pred_y = knn.predict(test_X)# 评估模型
knn.score(train_X,train_y)
使用模型查找出的KNN最优参数为n_neighbors=16,p=3,weights=distance.使用最优参数,得出的模型训练集得分为1。
7.查看模型准确率,召回率
# 预测数据
knn_pred_y = knn_gv.predict(test_X)# 查看主要分类指标文本报告
print(classification_report(test_y,knn_pred_y))
print(knn_gv.score(test_X,test_y))
模型的精准率,召回率,F1值分别为0.86,0.86,0.87。
8.计算评价指标
MSE = metrics.mean_squared_error(test_y,knn_pred_y)
RMSE = np.sqrt(MSE)
R = pearsonr(test_y, knn_pred_y)[0]
std = np.std(test_y-knn_pred_y)
RMSE,R,std
模型的RMSE为0.3627,R为0.7212,std为0.3627。
python 心脏病可视化和分类预测相关推荐
- R语言构建logistic回归模型并评估模型:模型预测结果抽样、可视化模型分类预测的概率分布情况、使用WVPlots包绘制ROC曲线并计算AUC值
R语言构建logistic回归模型并评估模型:模型预测结果抽样.可视化模型分类预测的概率分布情况.使用WVPlots包绘制ROC曲线并计算AUC值 目录
- 3.Python数据分析项目——工资分类预测
1.总结 流程 具体操作 基本查看 查看缺失值(可以用直接查看方式isnull.图像查看方式查看缺失值missingno).查看数值类型特征与非数值类型特征.一次性绘制所有特征的分布图像 预处理 缺失 ...
- python 逻辑回归二元分类预测Titanic生存率
项目源码请见:https://github.com/dennis0818/Titanic-survival-prediction 一 项目简介 泰坦尼克号的沉没是历史上最为著名的海难之一.1912年4 ...
- python机器学习之SVM分类预测电芯状态
最近给公司做电芯状态分类,边搞边学了下数据处理和svm分类模型训练与调用 华丽的分割线--------------------------------------------------------- ...
- python实现KNN模型分类预测并验证评估(附代码)
实现功能: python实现KNN建模,选择最佳K值,对数据样本进行分类预测,并验证评估. 实现代码: # 导入需要的库 from warnings import simplefilter simpl ...
- 数据分享|PYTHON用决策树分类预测糖尿病和可视化实例
全文下载链接:http://tecdat.cn/?p=23848 在本文中,决策树是对例子进行分类的一种简单表示.它是一种有监督的机器学习技术,数据根据某个参数被连续分割.决策树分析可以帮助解决分类和 ...
- 泰坦尼克号沉船数据分析与可视化、数据建模与分类预测【Python | 机器学习-Sklearn】
泰坦尼克号沉船数据之美--起于悲剧,止于浪漫 前言:泰坦尼克号,不只是卡梅隆导演的经典电影,它是一个真实存在的悲剧,也是电影的故事背景与题材.作为一个IT人,分析事实还得看数据,了解到泰坦尼克号沉船幸 ...
- ML之PDP:基于FIFA 2018 Statistics(2018年俄罗斯世界杯足球赛)球队比赛之星分类预测数据集利用DT决策树RF随机森林+PDP部分依赖图可视化实现模型可解释性之详细攻略
ML之PDP:基于FIFA 2018 Statistics(2018年俄罗斯世界杯足球赛)球队比赛之星分类预测数据集利用DT决策树&RF随机森林+PDP部分依赖图可视化实现模型可解释性之详细攻 ...
- 【机器学习入门】(2) 朴素贝叶斯算法:原理、实例应用(文档分类预测)附python完整代码及数据集
各位同学好,今天我向大家介绍python机器学习中的朴素贝叶斯算法.内容有:算法的基本原理:案例实战--新闻文档的分类预测. 案例简介:新闻数据有20个主题,有10万多篇文章,每篇文章对应不同的主题, ...
最新文章
- 我对软件设计原则的理解
- 你知道前端单页面路由是怎么实现的吗?
- QT教程1:ubuntu18.04安装QT5
- Amazon Elasticsearch Service 入门实践
- 【最爽的日期工具包LocalDate·超爽,超实用】(Java8版本)
- 数据结构--双链表的创建和操作
- nmon监控linux内存,使用Nmon监控Linux系统性能
- android box2d运行小例子,配置eclipse【转】
- ADC采样间隔问题+TRGO作为ADC的触发源头
- SimpleFs文件系统初步一(编译并挂载)
- 翻译:生产中的机器学习:为什么你应该关心数据和概念漂移
- itext生成pdf间距_java将html转为pdf
- 第四届福建省大学生程序设计竞赛
- MySQL数据库基础
- 3 Java学习之 IO
- 阅读--2020-7-19 CCFC2019 使用向量自回归和堆积LSTM模型进行多变量工作量预测
- PHP解密小程序加密信息
- 【寒江雪】Go实现组合模式
- 1041: 数列求和2 C语言
- 周涨粉超30w B站UP主非非宇Fay粉丝增长密码是什么?