最近在做项目,需要左侧展示百分比,右侧展示相应的数目,类似于金字塔图,尝试了seaborn等包,但是绘制出来的效果不理想,而且与自己项目需要的效果存在差异,特别是受到右侧数目的大小影响,在设置横坐标轴范围的时候,导致左侧比例显示非常的小,于是就想着使用subplots绘制子图,并通过设置子图之间的距离为0,进行图形拼接,具体实现过程如下:

数据准备

这里我采用csv格式准备相应数据,并通过pandas包的read_csv函数进行读取,具体内容如下:

name,applyUse,applyUseRatio
交通运输工程学院, 123, 88.43
计算机学院, 103, 76.76
智能科学学院, 203, 78.55
资源与环境学院, 125, 89.34
经济与管理学院, 201, 89.43
土木学院, 203, 89.55
机械工程学院, 145, 77.88
汽车自动化学院, 176, 74.28
航空航天学院, 198, 85.76
历史文化学院, 102, 83.58
新闻与传播学院, 122, 82.16

代码实现

下面直接贴出全部代码,在代码注释部分给出相应说明,具体代码如下:

import numpy as np   #引入相应包
import pandas as pd
from matplotlib import pyplot as plt, rcParams

# 设置图片信息,这里包括中文显示问题,图片大小,分辨率,负数符号显示等
config = {
    'font.family': 'serif',
    'font.size': 12,
    'mathtext.fontset': 'stix',  # 用于设置Latex字体
    'font.serif': ['SimHei'],  # simsun字体中文版就是宋体
    'figure.dpi': 480,
    'figure.figsize': [15, 6],
    'axes.linewidth': 1.5,
    'axes.spines.top': False,
    'axes.spines.right': False,
    'axes.unicode_minus': False,
}
rcParams.update(config)
# 读取CSV数据文件
stackBarDf = pd.read_csv('people.csv')
print(stackBarDf)
fig, ax = plt.subplots(nrows=1, ncols=2)   # 设置子图数量
ax[0] = plt.subplot(121)  # 绘制第一幅子图
plt.barh(stackBarDf["name"], -stackBarDf["applyUseRatio"])   # 读取名称和经费使用率,将使用率设置为负数,便于向左侧显示
ax[0].yaxis.set_ticks_position('left')  # 将y轴设置在左侧
ax[0].set_xlim(-(max(stackBarDf["applyUseRatio"] + 3)), 0)  # 设置x轴标签
labels = np.linspace(-(max(stackBarDf["applyUseRatio"] + 10.45)), 0, 6)  # 通过线性差值,修改x周标签
xlabels = []
for i in range(len(labels) - 1):
    xlabels.append(str(round(-1 * labels[i], 2)) + '%')
xlabels.append('')
ax[0].set_xticks(labels)
ax[0].set_xticklabels(xlabels)  # 设置x刻度标签
for i in ax[0].patches:  # 给条形图添加数据标签
    plt.text(i.get_width() - 9, i.get_y() + 0.25,
             str(round((i.get_width()), 2) * -1) + '%', )
plt.xlabel("经费使用占比")  # 增加x轴标题
ax = plt.subplot(122) # 绘制第2个子图
plt.barh(stackBarDf["name"], stackBarDf["applyUse"], color='darkorange')
ax.set_yticks([])
ax.spines['left'].set_color('white') # 使得中间的Y轴变为白色,即将图片用白色切分为左右两边
for i in ax.patches:
    plt.text(i.get_width() + 0.2, i.get_y() + 0.25,
             str(round((i.get_width()), 2)), )
plt.xlabel("学院总人数")
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0, hspace=0) # 设置子图的位置关系
plt.savefig("diagram_used_pyramid.png")
# 清空缓存用于下一幅图的绘制
plt.figure().clear()
plt.cla()
plt.clf()
plt.close("all")  # 记得关闭图形

代码运行结果展示

通过运行上述代码,可以得到如下图所示效果,如果有需要可以直接拿走。
diagram_used_pyramid.png