糖尿病数据分析:血压与年龄关系可视化

一、查看数据信息

python 复制代码
import matplotlib.pyplot as plt				
import pandas as pd
import matplotlib.font_manager as fm
from sklearn.feature_selection import SelectKBest,chi2
plt.rcParams['font.sans-serif']=['SimHei']
#数据探索
data = pd.read_excel(r"D:\Python\健康医学数据分析\第9章 医学实践综合案例源代码\案例4:糖尿病致病因素数据分析与可视化\diabetes.xlsx")		# 读取文件
data.info()									# 查看数据信息
data.describe()

代码解析:

  1. 导入库

    • matplotlib.pyplot:用于数据可视化
    • pandas:用于数据处理和分析
    • matplotlib.font_manager:用于管理字体
    • sklearn.feature_selection:用于特征选择(虽然导入但未使用)
  2. 字体设置

    • plt.rcParams['font.sans-serif']=['SimHei']:设置matplotlib使用黑体(SimHei)显示中文,避免中文乱码
  3. 数据加载

    • 使用pd.read_excel()从指定路径读取Excel文件
    • 文件路径指向一个糖尿病数据集(diabetes.xlsx)
  4. 数据探索

    • data.info():显示数据的基本信息,包括:
      • 列名和数据类型
      • 非空值数量
      • 内存使用情况
    • data.describe():显示数据的统计摘要,包括:
      • 计数(count)
      • 均值(mean)
      • 标准差(std)
      • 最小值(min)
      • 四分位数(25%, 50%, 75%)
      • 最大值(max)

运行结果:

二、 绘制箱线图查看异常值

python 复制代码
# 绘制箱线图查看异常值
fig = plt.figure(figsize=(20, 15))
plt.subplot(421)
plt.boxplot(data['Pregnancies'],showmeans=True,patch_artist='bule')
plt.title('怀孕次数',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(422)
plt.boxplot(data['Glucose'],showmeans=True,patch_artist='bule')
plt.title('口服葡萄糖耐量试验中血浆葡萄糖浓度',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(423)
plt.boxplot(data['BloodPressure'],showmeans=True,patch_artist='bule')
plt.title('舒张压',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(424)
plt.boxplot(data['SkinThickness'],showmeans=True,patch_artist='bule')
plt.title('三头肌组织褶厚度',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(425)
plt.boxplot(data['Insulin'],showmeans=True,patch_artist='bule')
plt.title('2小时血清胰岛素',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(426)
plt.boxplot(data['BMI'],showmeans=True,patch_artist='bule')
plt.title('身体质量指数(BMI)',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(427)
plt.boxplot(data['DiabetesPedigreeFunction'],showmeans=True,patch_artist='bule')
plt.title('糖尿病系统功能',fontsize='x-large')
plt.ylabel('人数')

plt.subplot(428)
plt.boxplot(data['Age'],showmeans=True,patch_artist='bule')
plt.title('年龄',fontsize='x-large')
plt.ylabel('人数')
plt.show()

创建画布

python 复制代码
fig = plt.figure(figsize=(20, 15))  # 设置画布大小(宽20英寸,高15英寸)
  • 通过 figsize 调整整体图形大小,适合同时展示多个子图。

绘制子图

  • 使用 plt.subplot(421)plt.subplot(428) 将画布分为 4行2列共8个子图 ,每个子图对应一个特征:
    • Pregnancies(怀孕次数)
    • Glucose(葡萄糖浓度)
    • BloodPressure(舒张压)
    • SkinThickness(皮肤厚度)
    • Insulin(胰岛素)
    • BMI(身体质量指数)
    • DiabetesPedigreeFunction(糖尿病遗传函数)
    • Age(年龄)

箱线图参数

python 复制代码
plt.boxplot(data['列名'], showmeans=True, patch_artist='bule')
  • showmeans=True:显示均值(绿色三角标记)。
  • patch_artist='bule':试图设置箱体颜色为蓝色,但参数有误(正确应 为 patch_artist=True, boxprops={'facecolor':'blue'})。

标题和标签

每个子图添加中文标题(如 '怀孕次数')和纵轴标签('人数'),字体大小设为 x-large

显示图形

python 复制代码
plt.show()

运行结果:

三、将0值用平均值替换

python 复制代码
#将0值用平均值替换
for i in range(6):
    value = int(data.iloc[:,i].mean())
    data.iloc[:,i].replace(0,value=value,inplace=True)
data.head()

遍历前 6 列数据

python 复制代码
for i in range(6):  # 处理前6列(0到5列)
  • 假设数据集的前 6 列是数值型特征(如 Pregnancies, Glucose 等)。

计算列的平均值

python 复制代码
value = int(data.iloc[:, i].mean())  # 取整后的列均值
  • data.iloc[:, i] 选择第 i 列的所有行。
  • .mean() 计算该列的平均值,并用 int() 取整。

替换 0 值为均值

python 复制代码
data.iloc[:, i].replace(0, value=value, inplace=True)
  • 将当前列中所有 0 值替换为 value(均值)。
  • inplace=True 直接修改原数据,无需重新赋值。

查看处理后的数据

python 复制代码
data.head()  # 显示前5行,验证替换结果

运行结果:

四、查看不同年龄段血压情况,多重柱状图---血压

python 复制代码
#查看不同年龄段血压情况,多重柱状图---血压
row=0;num1=0;num2=0;num3=0;num20=0;num30=0;num40=0;num50=0;num60=0;num21=0;num31=0;num41=0;num51=0;num61=0;num22=0;num32=0;num42=0;num52=0;num62=0
for i in data.loc[:,"Outcome"]:
    if i==0:
        continue
        row+=1
    else:
        if data.loc[row,"BloodPressure"]<=60:
            num1+=1
            if 20<data.loc[row,"Age"]<=30:
                num20+=1
            elif 30<data.loc[row,"Age"]<=40:
                num30+=1
            elif 40<data.loc[row,"Age"]<=50:
                num40+=1
            elif 50<data.loc[row,"Age"]<=60:
                num50+=1
            else:
                num60+=1
        elif 60<data.loc[row,"BloodPressure"]<=90:
            num2+=1
            if 20<data.loc[row,"Age"]<=30:
                num21+=1
            elif 30<data.loc[row,"Age"]<=40:
                num31+=1
            elif 40<data.loc[row,"Age"]<=50:
                num41+=1
            elif 50<data.loc[row,"Age"]<=60:
                num51+=1
            else:
                num61+=1
        else:
            num3+=1
            if 20<data.loc[row,"Age"]<=30:
                num22+=1
            elif 30<data.loc[row,"Age"]<=40:
                num32+=1
            elif 40<data.loc[row,"Age"]<=50:
                num42+=1
            elif 50<data.loc[row,"Age"]<=60:
                num52+=1
            else:
                num62+=1
        row+=1
dataplot = pd.DataFrame({'分类': ['低血压','血压正常','高血压'],
                     '21岁-30岁':[num20,num21,num22],
                    '31岁-40岁':[num30,num31,num32],
                    '41岁-50岁':[num40,num41,num42],
                    '51岁-60岁':[num50,num51,num52],
                    '61岁-70岁':[num60,num61,num62]})
print(dataplot)
dataplot.plot(x='分类', kind='bar')
plt.xticks(rotation=360)
plt.ylabel('人数(人)', fontproperties='simhei')
plt.title("不同血压情况下的年龄分布")
plt.legend()
plt.show()
  1. 目标:统计糖尿病患者中,不同血压范围(低血压、正常血压、高血压)在各年龄段的人数。
  2. 血压分组
    • 低血压(≤60 mmHg)
    • 血压正常(60-90 mmHg)
    • 高血压(>90 mmHg)
  3. 年龄分组
    • 21-30岁
    • 31-40岁
    • 41-50岁
    • 51-60岁
    • 61-70岁
  4. 实现方式
    • 通过循环遍历每一行数据,手动统计每个血压和年龄组合的人数。
    • 使用多个变量(如 num20, num21 等)记录计数结果。
    • 最后将结果整理成表格并绘制柱状图。

优化代码:

python 复制代码
# 筛选糖尿病患者
diabetic_data = data[data['Outcome'] == 1].copy()

# 创建血压分组
bp_bins = [0, 60, 90, float('inf')]
bp_labels = ['低血压', '血压正常', '高血压']
diabetic_data['血压分组'] = pd.cut(diabetic_data['BloodPressure'], 
                                 bins=bp_bins, 
                                 labels=bp_labels)

# 创建年龄分组
age_bins = [20, 30, 40, 50, 60, 70]
age_labels = ['21-30岁', '31-40岁', '41-50岁', '51-60岁', '61-70岁']
diabetic_data['年龄分组'] = pd.cut(diabetic_data['Age'], 
                                 bins=age_bins, 
                                 labels=age_labels)

# 创建交叉表
cross_tab = pd.crosstab(diabetic_data['血压分组'], diabetic_data['年龄分组'])
print(cross_tab)

# 绘制分组柱状图
ax = cross_tab.plot(kind='bar', figsize=(12, 8), rot=0)
plt.title("糖尿病患者血压与年龄分布", fontsize=14)
plt.ylabel("人数(人)")
plt.xlabel("血压分类")
plt.legend(title="年龄段")

# 添加数据标签
for p in ax.patches:
    height = p.get_height()
    if height > 0:  # 只添加非零值的标签
        ax.annotate(f"{int(height)}", 
                    (p.get_x() + p.get_width() / 2, height), 
                    ha='center', va='bottom', xytext=(0, 3),
                    textcoords='offset points')
                    
plt.tight_layout()
plt.show()

代码分析:

  1. 简化数据处理

    • 使用 pd.cut() 函数代替手动分类,更高效且不易出错
    • 直接筛选糖尿病患者 (data[data['Outcome'] == 1])
  2. 改进分组逻辑

    • 血压分组:
      • 低血压 (≤60 mmHg)
      • 血压正常 (60-90 mmHg)
      • 高血压 (>90 mmHg)
    • 年龄分组:
      • 21-30岁
      • 31-40岁
      • 41-50岁
      • 51-60岁
      • 61-70岁
  3. 高效计数

    • 使用 pd.crosstab() 创建交叉表,替代手动计数变量
    • 自动处理分组间的计数关系
  4. 可视化优化

    • 添加数据标签,提高图表可读性
    • 优化图例标题 ("年龄段")
    • 调整图表尺寸和布局
    • 添加图表标题和轴标签
  5. 错误修复

    • 原代码中 continue 语句导致索引错误的问题已解决
    • 正确处理边界值 (如 60, 61 的处理)

运行结果:

五、找出对患糖尿病影响最大的因素

python 复制代码
# 找出对患糖尿病影响最大的因素
x = data.iloc[:,0:8]
y = data.iloc[:,8:9]
bestfeatures = SelectKBest(score_func=chi2,k = len(x.columns))
fit = bestfeatures.fit(x,y)
df_scores = pd.DataFrame(fit.scores_)
df_columns = pd.DataFrame(['怀孕次数','口服葡萄糖耐量试验中血浆葡萄糖浓度','舒张压','三头肌组织褶厚度','2小时血清胰岛素','身体质量指数(BMI)','糖尿病系统功能','年龄'])
df_feature_scores = pd.concat([df_scores,df_columns],axis = 1)
df_feature_scores.columns = ["得分","指标"]
df_sort =df_feature_scores.sort_values(by = "得分",ascending= False)
df_sort

数据准备

python 复制代码
x = data.iloc[:, 0:8]  # 选取前8列作为特征(怀孕次数、血糖等)
y = data.iloc[:, 8:9]  # 选取第9列(Outcome)作为目标变量
  • x:包含所有特征(自变量)。
  • y:包含标签(因变量,是否患糖尿病)。

卡方检验

python 复制代码
bestfeatures = SelectKBest(score_func=chi2, k=len(x.columns))
fit = bestfeatures.fit(x, y)
  • SelectKBest:选择得分最高的 k 个特征。
  • score_func=chi2:使用卡方检验计算特征重要性(适用于分类问题)。
  • k=len(x.columns):评估所有特征,不进行筛选。

整理结果

python 复制代码
df_scores = pd.DataFrame(fit.scores_)  # 卡方检验得分
df_columns = pd.DataFrame(['怀孕次数', '葡萄糖浓度', '舒张压', '皮肤厚度', 
                         '胰岛素', 'BMI', '糖尿病遗传函数', '年龄'])
df_feature_scores = pd.concat([df_scores, df_columns], axis=1)
df_feature_scores.columns = ["得分", "指标"]

排序输出

python 复制代码
df_sort = df_feature_scores.sort_values(by="得分", ascending=False)
  • 按得分从高到低排序,得分越高表示特征对糖尿病的影响越大。

卡方检验的原理

  • 用途:检验分类变量之间的独立性(此处是特征与糖尿病结果的关联性)。
  • 得分计算:卡方统计量越高,特征与目标变量的相关性越强。
  • 适用条件:特征必须是非负的(如计数、频率、二值化数据)。如果数据包含负数或连续值,需先进行分箱(离散化)。

运行结果:

相关推荐
cwn_24 分钟前
Sequential 损失函数 反向传播 优化器 模型的使用修改保存加载
人工智能·pytorch·python·深度学习·机器学习
老鱼说AI25 分钟前
Transformer Masked loss原理精讲及其PyTorch逐行实现
人工智能·pytorch·python·深度学习·transformer
lxmyzzs29 分钟前
【已解决】YOLO11模型转wts时报错:PytorchStreamReader failed reading zip archive
人工智能·python·深度学习·神经网络·目标检测·计算机视觉·bug
雄狮少年2 小时前
智能体服务封装
开发语言·windows·python
云天徽上3 小时前
【数据可视化-70】奶茶店销量数据可视化:打造炫酷黑金风格的可视化大屏
python·信息可视化·数据分析·数据可视化·pyecharts
IMER SIMPLE3 小时前
人工智能-python-OpenCV 图像基础认知与运用-图像的预处理(1)
人工智能·python·opencv
ku_code_ku3 小时前
Django关于ListView通用视图的理解(Cursor解释)
python·django·sqlite
荼蘼4 小时前
python爬虫实战-小案例:爬取苏宁易购的好评
开发语言·爬虫·python
运维小文4 小时前
初探贪心算法 -- 使用最少纸币组成指定金额
c++·python·算法·贪心算法
Eiceblue4 小时前
PDF转Markdown - Python 实现方案与代码
开发语言·vscode·python·pdf