欢迎光临
我们一直在努力

项目实战:中风数据分析

中风体检数据分析

1.数据导入

首先将所需要的包进行引用

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#设置中文显示
plt.rcParams['font.sans-serif']=['SimHei']
#设置负号显示
plt.rcParams['axes.unicode_minus']=False

然后导入数据

pip install xlrd openpyxl

Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: xlrd in c:\\users\\wld\\appdata\\roaming\\python\\python313\\site-packages (2.0.2)
Requirement already satisfied: openpyxl in f:\\wld666\\lib\\site-packages (3.1.5)
Requirement already satisfied: et-xmlfile in f:\\wld666\\lib\\site-packages (from openpyxl) (1.1.0)
Note: you may need to restart the kernel to use updated packages.

age_abs=pd.read_excel(r'D:\\wld20256030609(python数据分析)\\healthcare-dataset-age_abs.xlsx')
print(age_abs.head())

stroke=pd.read_excel(r'D:\\wld20256030609(python数据分析)\\healthcare-dataset-stroke.xlsx')
print(stroke.head())

编号 年龄 平均血糖
0 9046 67.0 228.69
1 51676 61.0 202.21
2 31112 80.0 105.92
3 60182 49.0 171.23
4 1665 79.0 174.12
编号 性别 高血压 是否结婚 工作类型 居住类型 体重指数 吸烟史 中风
0 9046 男 否 是 私人 城市 36.6 以前吸烟 是
1 51676 女 否 是 私营企业 农村 NaN 从不吸烟 是
2 31112 男 否 是 私人 农村 32.5 从不吸烟 是
3 60182 女 否 是 私人 城市 34.4 抽烟 是
4 1665 女 是 是 私营企业 农村 24.0 从不吸烟 是

healthcare-dataset-age_abs.xlsx表格为患者的年龄和血糖信息,表格healthcare-dataset-stroke.xlsx为患者的基本信息(性别、年龄、体重、身高、血压、心率、是否患有中风等)。

2.查看数据信息(分布)

age_abs[['年龄','平均血糖']].describe().T

countmeanstdmin25%50%75%max年龄

平均血糖

1767.0 45.858766 22.785222 0.08 28.000 49.00 64.000 82.00
1767.0 109.355444 47.983848 55.22 77.925 93.55 118.565 271.74

可见年龄的分布范围为[082],年龄分布较为平均,平均年龄为42岁,标准差为12岁。\\
平均血糖的分布范围为[55.22
271.74],平均血糖为109.35544

age_abs.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1767 entries, 0 to 1766
Data columns (total 3 columns):
# Column Non-Null Count Dtype
— —— ————– —–
0 编号 1767 non-null int64
1 年龄 1767 non-null float64
2 平均血糖 1767 non-null float64
dtypes: float64(2), int64(1)
memory usage: 41.5 KB

可见age_abs表格中没有缺失值,所有数据均为数值型数据。

#查看中风数据的空缺情况
stroke.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1767 entries, 0 to 1766
Data columns (total 9 columns):
# Column Non-Null Count Dtype
— —— ————– —–
0 编号 1767 non-null int64
1 性别 1767 non-null object
2 高血压 1767 non-null object
3 是否结婚 1767 non-null object
4 工作类型 1767 non-null object
5 居住类型 1767 non-null object
6 体重指数 1672 non-null float64
7 吸烟史 1767 non-null object
8 中风 1767 non-null object
dtypes: float64(1), int64(1), object(7)
memory usage: 124.4+ KB

3.数据预处理

# 处理空缺值
stroke=stroke.dropna()

#合并表格
data=pd.merge(age_abs,stroke,on='编号',how='inner')
data.head()

编号年龄平均血糖性别高血压是否结婚工作类型居住类型体重指数吸烟史中风0

1

2

3

4

9046 67.0 228.69 男 否 是 私人 城市 36.6 以前吸烟 是
31112 80.0 105.92 男 否 是 私人 农村 32.5 从不吸烟 是
60182 49.0 171.23 女 否 是 私人 城市 34.4 抽烟 是
1665 79.0 174.12 女 是 是 私营企业 农村 24.0 从不吸烟 是
56669 81.0 186.21 男 否 是 私人 城市 29.0 以前吸烟 是

data['中风'].value_counts()

中风
否 1463
是 209
Name: count, dtype: int64

data=data.loc[data['中风']=='是'].reset_index(drop=True) #只需要中风数据

data表格将进行后续的分析,分析出因素和中风的相关性。

4.数据分析与可视化

4.1 查看年龄和中风的相关性

#首先将连续年龄离散化
labels=['青少年','青年','中年','壮年','老年']
data['年龄级别']=pd.cut(data['年龄'],bins=[0,20,40,60,80,100],
labels=labels)

#按照年龄级别进行分组,统计每个组别的中风数量
df_age=data.groupby('年龄级别')['中风'].count()
#df_age

#可视化
df_age.plot.pie(autopct='%1.1f%%',labels=labels,startangle=90)
plt.title("不同年龄级别中中风数量占比")
plt.show()

C:\\Users\\wld\\AppData\\Local\\Temp\\ipykernel_33576\\1287358588.py:7: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
df_age=data.groupby('年龄级别')['中风'].count()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可见年龄为壮年的中风人数最多,其次是中年和老年,最后是青少年和青年。

4.2 查看其他类别数据和中风的相关性

#按照类别进行分组,统计每个组别的中风数量
df_sex=data.groupby('性别').size()
df_HBP=data.groupby('高血压').size()
df_smoke=data.groupby('吸烟史').size()
df_marrige=data.groupby('是否结婚').size()
df_livetype=data.groupby('居住类型').size()
df_worketype=data.groupby('工作类型').size()

#可视化
fig=plt.figure(figsize=(12,12),dpi=200) #创建画布,设置大小和分辨率

plt.subplot(321) #创建子图,3行2列,第1个子图
df_sex.plot.pie(autopct='%1.1f%%',startangle=90)
plt.title("不同性别中中风数量占比")

plt.subplot(322)
df_HBP.plot.pie(autopct='%1.1f%%',startangle=90)
plt.title("高血压中风数量占比")

plt.subplot(323)
df_smoke.plot.pie(autopct='%1.1f%%',startangle=90)
plt.title("是否吸烟中风数量占比")

plt.subplot(324)
df_marrige.plot.pie(autopct='%1.1f%%',startangle=90)
plt.title("是否结婚中风数量占比")

plt.subplot(325)
df_livetype.plot.pie(autopct='%1.1f%%',startangle=90)
plt.title("居住类型中风数量占比")

plt.subplot(326)
df_worketype.plot.pie(autopct='%1.1f%%',startangle=90)
plt.title("工作类型中风数量占比")

plt.tight_layout() #调整子图间距
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论分析:?

4.3 分析血糖和体重指数

plt.scatter(data['平均血糖'],data['体重指数'],s=0.8)
plt.xlabel("平均血糖")
plt.ylabel("体重指数")
plt.title("平均血糖与体重指数关系")
plt.show()

## 1. 计算血糖与BMI相关系数(量化关联)
corr = data[['平均血糖','体重指数']].corr().iloc[0,1]
print(f"血糖与BMI相关系数:{corr:.3f}")

# 2. 简单分档统计+单图展示(核心对比)
data['血糖等级'] = pd.cut(data['平均血糖'], [0,100,150,300], labels=['正常','偏高','高血糖'])
data['BMI等级'] = pd.cut(data['体重指数'], [0,18.5,24,28,60], labels=['偏瘦','正常','超重','肥胖'])

# 合并展示血糖/BMI分布
plt.figure(figsize=(10,4))
plt.subplot(121)
data['血糖等级'].value_counts().plot(kind='bar', color=['green','orange','red'])
plt.title('血糖等级分布')
plt.subplot(122)
data['BMI等级'].value_counts().plot(kind='bar', color=['blue','purple','yellow','red'])
plt.title('BMI等级分布')
plt.tight_layout()
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

血糖与BMI相关系数:0.335

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论?

4.4 全特征相关性热力图

# 类别特征编码,方便做相关性分析
from sklearn.preprocessing import LabelEncoder
df_corr = data.copy()
# 对分类字段标签编码
for col in ['性别','高血压','是否结婚','工作类型','居住类型','吸烟史']:
df_corr[col] = LabelEncoder().fit_transform(df_corr[col])

# 提取数值字段做热力图
import seaborn as sns
plt.figure(figsize=(10,7),dpi=150)
corr_all = df_corr[['年龄','平均血糖','体重指数','性别','高血压','是否结婚','吸烟史']].corr()
sns.heatmap(corr_all,annot=True,cmap='RdBu_r',fmt='.2f')
plt.title('各危险因素相关性热力图')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.5中风患病影响量化

# 构建特征与标签,预测中风患病(原全量数据,不是只取中风患者)
# 重新读取原始合并数据(如需)
# raw_data = pd.merge(age_abs,stroke,on='编号',how='inner').dropna()

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report

# 数据编码
raw_data = pd.merge(age_abs,stroke,on='编号',how='inner').dropna()
X = raw_data[['年龄','平均血糖','体重指数']].copy()
# 标签转为0/1
raw_data['中风标签'] = raw_data['中风'].map({'否':0,'是':1})
y = raw_data['中风标签']

# 划分训练测试集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=2025)
lr = LogisticRegression()
lr.fit(X_train,y_train)
y_pred = lr.predict(X_test)

print("模型分类报告:\\n",classification_report(y_test,y_pred))
print("各特征影响系数(系数越大,越容易诱发中风):")
coef_df = pd.DataFrame({
'特征':['年龄','平均血糖','体重指数'],
'回归系数':lr.coef_[0]
})
print(coef_df)

模型分类报告:
precision recall f1-score support

0 0.90 0.99 0.94 297
1 0.62 0.13 0.22 38

accuracy 0.89 335
macro avg 0.76 0.56 0.58 335
weighted avg 0.87 0.89 0.86 335

各特征影响系数(系数越大,越容易诱发中风):
特征 回归系数
0 年龄 0.073473
1 平均血糖 0.005787
2 体重指数 0.007338

赞(0)
未经允许不得转载:171主机测评 » 项目实战:中风数据分析
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址