ToB企服应用市场:ToB评测及商务社交产业平台

标题: 数据分析每周挑衅——心衰患者特征数据集 [打印本页]

作者: 花瓣小跑    时间: 2024-6-22 13:04
标题: 数据分析每周挑衅——心衰患者特征数据集

这是一篇关于医学数据的数据分析,但是这个数据集数据不是很多。
配景描述

本数据集包含了多个与心力衰竭相关的特征,用于分析和预测患者心力衰竭发作的风险。数据集涵盖了从40岁到95岁不等年龄的患者群体,提供了广泛的生理和生活方式指标,以资助研究职员和医疗专业职员更好地明白心衰的潜伏风险因素。
每条患者记载包含以下关键信息:
数据说明

字段表明测量单元区间Age患者的年龄年(Years)[40,…, 95]Anaemia是否贫血(红细胞或血红蛋白淘汰)布尔值(Boolean)0, 1High blood pressure患者是否患有高血压布尔值(Boolean)0, 1Creatinine phosphokinase, CPK血液中的 CPK (肌酸激酶)水平微克/升(mcg/L)[23,…, 7861]Diabetes患者是否患有糖尿病布尔值(Boolean)0, 1Ejection fraction每次心脏紧缩时离开心脏的血液百分比百分比(Percentage)[14,…, 80]Sex性别,女性0或男性1二进制(Binary)0, 1Platelets血液中的血小板数量千血小板/毫升(kiloplatelets/mL)[25.01,…, 850.00]Serum creatinine血液中的肌酐水平毫克/分升(mg/dL)[0.50,…, 9.40]Serum sodium血液中的钠水平毫摩尔/升(mEq/L)[114,…, 148]Smoking患者是否吸烟布尔值(Boolean)0, 1Time随访期天(Days)[4,…,285]DEATH_EVENT患者在随访期间是否死亡布尔值(Boolean)0, 1
  1. !pip install lifelines -i https://pypi.tuna.tsinghua.edu.cn/simple/
  2. !pip install imblearn -i https://pypi.tuna.tsinghua.edu.cn/simple/
复制代码
 这是我们这次用到的一些第三方库,大家假如没有安装,可以在jupyter notebook中直接下载。
一:导入第三方库
  1. import pandas as pd
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import seaborn as sns
  5. from lifelines import KaplanMeierFitter,CoxPHFitter
  6. import scipy.stats as stats
  7. from sklearn.model_selection import train_test_split
  8. from imblearn.over_sampling import RandomOverSampler
  9. from sklearn.metrics import classification_report,confusion_matrix,roc_curve,auc
  10. from sklearn.ensemble import RandomForestClassifier
  11. from pylab import mpl
  12. plt.rcParams['font.family'] = ['sans-serif']
  13. plt.rcParams['font.sans-serif'] = ['SimHei']
  14. plt.rcParams['axes.unicode_minus'] = False
复制代码
 二:读取数据
  1. data = pd.read_csv("D:/每周挑战/heart_failure_clinical_records_dataset.csv")
  2. data.head()
复制代码
三:对数据进行预处置惩罚
  1. data = data.rename(columns={'age':'年龄','anaemia':'是否贫血','creatinine_phosphokinase':'血液中的CPK水平','diabetes':'患者是否患有糖尿病',
  2.                           'ejection_fraction':'每次心脏收缩时离开心脏的血液百分比','high_blood_pressure':'患者是否患有高血压','platelets':'血液中的血小板数量','serum_creatinine':'血液中的肌酐水平',
  3.                           'serum_sodium':'血液中的钠水平','sex':'性别(0为男)','smoking':'是否吸烟','time':'随访期(day)','DEATH_EVENT':'是否死亡'})
  4. data.head()
  5. # 将标签修改为中文更好看
复制代码
 上面这一段可以不写,假如你喜欢英语可以不加,假如你喜欢汉字,那你可以更改一下。
  1. data.info()  # 从这里可以观察出应该是没有缺失值
  2. data.isnull().sum()  # 没有缺失值
  3. data_ = data.copy()        # 方便我们后期对数据进行建模
复制代码
区分连续数据和分类数据。 
  1. for i in data.columns:
  2.     if set(data[i].unique()) == {0,1}:
  3.         print(i)
  4. print('-'*50)
  5. for i in data.columns:
  6.     if set(data[i].unique()) != {0,1}:
  7.         print(i)   
复制代码
 四:数据分析绘图
  1. classify = ['anaemia','high_blood_pressure','diabetes','sex','smoking','DEATH_EVENT']  #  DEATH_EVENT 这个是研究的主要结果指标
  2. numerical = ['age','creatinine_phosphokinase','ejection_fraction','platelets','serum_creatinine','serum_sodium','time']
  3. plt.figure(figsize=((16,20)))
  4. for i,col in enumerate(numerical):
  5.     plt.subplot(4,2,i+1)
  6.     sns.boxplot(y = data[col])
  7.     plt.title(f'{col}的箱线图', fontsize=14)
  8.     plt.ylabel('数值', fontsize=12)
  9.     plt.grid(axis='y', linestyle='--', alpha=0.7)
  10.    
  11. plt.tight_layout()
  12. plt.show()
复制代码

 从箱型图来看,有些数据有部分异常值,但是,由于缺乏医学知识,所以这里我们不能对异常值进行处置惩罚。
  1. colors = ['#63FF9D', '#C191FF']
  2. plt.figure(figsize=(10,12))
  3. for i,col in enumerate(classify):
  4.     statistics = data[col].value_counts().reset_index()
  5.     plt.subplot(3,2,i+1)
  6.     sns.barplot(x=statistics['index'],y=statistics[col],palette=colors)
  7.     plt.title(f'{col}的条形图', fontsize=14)
  8.    
  9. plt.tight_layout()
  10. plt.show()
复制代码

接下里,我们看时间对于生存率的影响,这里我们就用到了前面安装的KaplanMeierFitter。
  1. kmf = KaplanMeierFitter()
  2. kmf.fit(durations=data['time'],event_observed=data['DEATH_EVENT'])
  3. plt.figure(figsize=(10,8))
  4. kmf.plot_survival_function()
  5. plt.title('Kaplan-Meier 生存曲线', fontsize=14)
  6. plt.xlabel('时间(天)', fontsize=12)
  7. plt.ylabel('生存概率', fontsize=12)
  8. plt.show()
复制代码

随着时间的推移,生存概率逐渐降落。 在随访竣事时,生存概率大约为60%。 接下来,我们对特征相关性进行分析。 
  1. corr = data.corr(method="spearman")
  2. plt.figure(figsize=(10,8))
  3. sns.heatmap(corr,annot=True,cmap='coolwarm',fmt='.2g')
  4. plt.title("斯皮尔曼相关性矩阵")
  5. plt.show()
复制代码

显著相关性:
年龄、射血分数、血清肌酐 血清钠 和 随访期 与死亡事件之间的相关性较强。 射血分数和血清肌酐与死亡事件的相关性尤为显著,这表明这些变量对死亡事件的预测大概具有紧张意义。 弱相关性或无相关性:
贫血、高血压 与死亡事件有轻微相关性,但不显著。
肌酸激酶、糖尿病、血小板、性别 和 吸烟 与死亡事件几乎没有相关性。
  1. def t_test(fea):
  2.     group1 = data[data['DEATH_EVENT'] == 0][fea]
  3.     group2 = data[data['DEATH_EVENT'] == 1][fea]
  4.     t,p = stats.ttest_ind(group1,group2)
  5.     return t,p
  6. # 对数值变量进行t检验
  7. t_test_results = {feature: t_test(feature) for feature in numerical}
  8. t_test_df = pd.DataFrame.from_dict(t_test_results,orient='index',columns=['T-Statistic','P-Value'])
  9. t_test_df
复制代码
T-StatisticP-Valueage-4.5219838.862975e-06creatinine_phosphokinase-1.0831712.796112e-01ejection_fraction4.8056282.452897e-06platelets0.8478683.971942e-01serum_creatinine-5.3064582.190198e-07serum_sodium3.4300636.889112e-04time10.6855639.122223e-23  
t查验是一种统计方法,用于比较两组数据是否存在显著差异。该方法基于以下步骤和原理:
建立假设:首先建立零假设(H0),通常表示两个比较群体间没有差异,以及备择假设(H1),即存在差异。
盘算t值:盘算得到一个t值,这个值反映了样本均值与假定总体均值之间的差距巨细。
确定P值:通过t分布理论,盘算出在零假设为真的条件下,观察到当前t值或更极端情况的概率,即P值。
做出结论:假如P值小于事先设定的显著性水平(通常为0.05),则拒绝零假设,认为样原来自的两个总体之间存在显著差异;否则,不拒绝零假设。
对于连续数据的特征我们接纳t查验进行分析,而对于离散数据,我们接纳卡方查验进行分析
  1. # 卡方检验
  2. def chi_square_test(fea1, fea2):
  3.     contingency_table = pd.crosstab(data[fea1], data[fea2])
  4.     chi2, p, dof, expected = stats.chi2_contingency(contingency_table)
  5.     return chi2, p
  6. chi_square_results = {}
  7. chi_square_results = {feature: chi_square_test(feature, 'DEATH_EVENT') for feature in classify}
  8. chi_square_df = pd.DataFrame.from_dict(chi_square_results,orient='index',columns=['Chi-Square','P-Value'])
  9. chi_square_df
复制代码
Chi-SquareP-Valueanaemia1.0421753.073161e-01high_blood_pressure1.5434612.141034e-01diabetes0.0000001.000000e+00sex0.0000001.000000e+00smoking0.0073319.317653e-01DEATH_EVENT294.4301065.386429e-66 全部分类变量(贫血、糖尿病、高血压、性别、吸烟)的p值均大于0.05,表明它们与死亡事件无显著相关性。
最后我们对数据进行建模,这里我们使用随机森林,由于数据量较少,因此我们接纳随机采样的方法进行过采样。
  1. x = data.drop('DEATH_EVENT',axis=1)
  2. y = data['DEATH_EVENT']
  3. x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3,random_state=15) #37分
  4. # 实例化随机过采样器
  5. oversampler = RandomOverSampler()
  6. # 在训练集上进行随机过采样
  7. x_train, y_train = oversampler.fit_resample(x_train, y_train)
  8. rf_clf = RandomForestClassifier(random_state=15)
  9. rf_clf.fit(x_train, y_train)
  10. y_pred_rf = rf_clf.predict(x_test)
  11. class_report_rf = classification_report(y_test, y_pred_rf)
  12. print(class_report_rf)
复制代码
  1.           precision    recall  f1-score   support
  2.            0       0.84      0.85      0.84        60
  3.            1       0.69      0.67      0.68        30
  4.     accuracy                           0.79        90
  5.    macro avg       0.76      0.76      0.76        90
  6. weighted avg       0.79      0.79      0.79        90
复制代码
  1. cm = confusion_matrix(y_test,y_pred_rf)
  2. plt.figure(figsize=(8, 6))
  3. sns.heatmap(cm, annot=True, fmt='g', cmap='Blues',
  4.             xticklabels=['预测值 0', '预测值 1'],
  5.             yticklabels=['真实值 0', '真实值 1'])
  6. plt.title('混淆矩阵')
  7. plt.show()
复制代码

  1. feature_importance = rf_clf.feature_importances_
  2. feature = x.columns
  3. sort_importance = feature_importance.argsort()
  4. plt.figure(figsize=(10,8))
  5. plt.barh(range(len(sort_importance)), feature_importance[sort_importance],color='#B5FFCD')
  6. plt.yticks(range(len(sort_importance)), [feature[i] for i in sort_importance])
  7. plt.xlabel('特征重要性')
  8. plt.title('特征重要性分析')
  9. plt.show()
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4