中风体检数据分析
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
| 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.22271.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()
| 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




