【跟着SCI学作图】Matplotlib年龄结构图+堆积柱状图

【跟着SCI学作图】Matplotlib年龄结构图+堆积柱状图

在这里插入图片描述

01 引言

最近接到这么一个需求,需要将年龄结构图和堆积柱状图结合在一起,主要是Matplotlib简单柱状图的变形,但简单的组合后,能够非常直观地展现年龄结构和组成成分,丰富了图表内容,节约了文章版面。
请添加图片描述

02 读取数据 :

借助pandas读取数据如下图所示,可以发现就是简单的问卷调查类型的数据(样例数据仅供绘图使用,不必纠结数据的合理性),由于需要分组和绘制堆积柱状图,这里可以借助panda的cut和cumsum对数据进行处理。
请添加图片描述

# 读取数据
fn = r'D:\ForestMeteorology\FM230613\data\鼻炎问卷数据样例.xlsx'
df = pd.read_excel(fn)
df.columns = ['kind','age','gender']
print(df)# 年龄分组
bins = np.arange(10,101,10)
df['group']  = pd.cut(df.age,bins = bins)
df['level'] = df['group'].astype(str).str[1:3].astype(int)
kinddict = {'鼻炎前期': 1, '鼻炎确诊3年内': 2, '鼻炎确诊3年以上(无并发症)': 3,'鼻炎确诊3年以上(有并发症)':4}
df['kind'].replace(kinddict, inplace=True)
df['gender'].replace({'男': 1, '女': 0}, inplace=True)
df.sort_values('level',inplace=True)
print(df)

03 可视化 :

主要分性别分年龄组去绘制,需要注意的是图层的上下层关系。

fig,ax = plt.subplots(figsize=(8,4.5))
colors = ['#D1B26F', '#E7D9B6', '#B4D7D3', '#6FB2AB']
for g in [0,1]:
    for i in df['level'].unique():
        idf = df[(df['level']==i)&(df['gender']==g)]
        ires = idf.groupby('kind').count()
        ires.reset_index(inplace=True)
        ires['csum'] = ires['age'].cumsum()
        ires.sort_values('csum',inplace=True,ascending=False)
        print((i,g))
        print(ires)
        for j in range(len(ires)):
            if g==0:
                jx = ires.iloc[j,-1]
                jtype = ires.iloc[j,0]
                ax.barh(i,jx
                        ,label = list(kinddict.keys())[jtype-1]
                        ,color = colors[jtype-1]
                        ,height=10
                        )
                # 添加外框
                ax.barh(i,ires.iloc[0,-1]
                        ,label = list(kinddict.keys())[jtype-1]
                        ,facecolor = 'none'
                        ,height=10
                        ,edgecolor = 'k'
                        ,zorder = 0
                        )
            else:
                jx = ires.iloc[j,-1]*(-1)
                jtype = ires.iloc[j,0]
                ax.barh(i,jx
                        ,label = list(kinddict.keys())[jtype-1]
                        ,color = colors[jtype-1]
                        ,height=10
                        )
                # 添加外框
                ax.barh(i,ires.iloc[0,-1]*(-1)
                        ,label = list(kinddict.keys())[jtype-1]
                        ,facecolor = 'none'
                        ,height=10
                        ,edgecolor = 'k'
                        ,zorder = 0
                        )
plt.show()

请添加图片描述

04完整代码

最终添加图例、坐标轴名称等细节就完成了整幅图啦!
请添加图片描述

# -*- encoding: utf-8 -*-
'''
@File    :   gzh230616.py
@Time    :   2023/06/16 23:59:51
@Author  :   HMX
@Version :   1.0
@Contact :   kzdhb8023@163.com
'''# here put the import lib
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
​
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
​
​
# 读取数据
fn = r'D:\ForestMeteorology\FM230613\data\鼻炎问卷数据样例.xlsx'
df = pd.read_excel(fn)
df.columns = ['kind','age','gender']
print(df)# 年龄分组
bins = np.arange(10,101,10)
df['group']  = pd.cut(df.age,bins = bins)
df['level'] = df['group'].astype(str).str[1:3].astype(int)
kinddict = {'鼻炎前期': 1, '鼻炎确诊3年内': 2, '鼻炎确诊3年以上(无并发症)': 3,'鼻炎确诊3年以上(有并发症)':4}
df['kind'].replace(kinddict, inplace=True)
df['gender'].replace({'男': 1, '女': 0}, inplace=True)
df.sort_values('level',inplace=True)
print(df)
​
​
fig,ax = plt.subplots(figsize=(8,4.5))
colors = ['#D1B26F', '#E7D9B6', '#B4D7D3', '#6FB2AB']
for g in [0,1]:
    for i in df['level'].unique():
        idf = df[(df['level']==i)&(df['gender']==g)]
        ires = idf.groupby('kind').count()
        ires.reset_index(inplace=True)
        ires['csum'] = ires['age'].cumsum()
        ires.sort_values('csum',inplace=True,ascending=False)
        print((i,g))
        print(ires)
        for j in range(len(ires)):
            if g==0:
                jx = ires.iloc[j,-1]
                jtype = ires.iloc[j,0]
                ax.barh(i,jx
                        ,label = list(kinddict.keys())[jtype-1]
                        ,color = colors[jtype-1]
                        ,height=10
                        )
                # 添加外框
                ax.barh(i,ires.iloc[0,-1]
                        ,label = list(kinddict.keys())[jtype-1]
                        ,facecolor = 'none'
                        ,height=10
                        ,edgecolor = 'k'
                        ,zorder = 0
                        )
            else:
                jx = ires.iloc[j,-1]*(-1)
                jtype = ires.iloc[j,0]
                ax.barh(i,jx
                        ,label = list(kinddict.keys())[jtype-1]
                        ,color = colors[jtype-1]
                        ,height=10
                        )
                # 添加外框
                ax.barh(i,ires.iloc[0,-1]*(-1)
                        ,label = list(kinddict.keys())[jtype-1]
                        ,facecolor = 'none'
                        ,height=10
                        ,edgecolor = 'k'
                        ,zorder = 0
                        )
​
​
# 图例设置 图例去重
handles, labels = ax.get_legend_handles_labels()
unique_labels = []
unique_handles = []
for i, label in enumerate(labels):
    if label not in unique_labels:
        unique_labels.append(label)
        unique_handles.append(handles[i])
ax.legend(unique_handles, unique_labels)# 添加辅助线
ax.axvline(x = 0,c='k',ls=':',lw=1)# 设置xy轴刻度及名称
ax.set_yticks(bins[:-1])
ax.set_ylim(0,100)
ax.set_xlim(-35,35)
ax.set_xticks(np.arange(-30,31,10))
ax.set_xticklabels([abs(i) for i in np.arange(-30,31,10)])
ax.set_ylabel('年龄')
ax.set_xlabel('人数')
ax.text(30,10,'女',ha = 'center',va = 'center')
ax.text(-30,10,'男',ha = 'center',va = 'center')
plt.tight_layout()
plt.savefig(r'D:\ForestMeteorology\FM230613\data\gzh230616.png',dpi = 600)
plt.show()

以上就是本期推文的全部内容了,如果对你有帮助的话,请‘点赞’、‘收藏’,‘关注’,你们的支持是我更新的动力。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值