如何为堆叠条形图添加堆叠式X轴标签
实现Matplotlib堆叠式多层X轴标签的修改方案
要实现类似参考示例的多层堆叠X轴效果,核心是给DataFrame设置多层索引,并调整标签生成函数的位置参数,具体修改如下:
关键修改步骤
1. 构建多层索引
当前代码仅使用单层索引,无法支撑多层标签生成。我们需要添加大组分类,并将其与现有部署目标设为双层索引:
# 在创建DataFrame后添加大组标签,区分不同的分组 df['Group'] = ['DV only'] + ['场景1']*3 + ['场景2']*3 + ['场景3']*3 # 设置双层索引:外层为大组,内层为部署目标 df.set_index(['Group', 'Deployment target'], inplace=True)
2. 调整标签生成函数的位置参数
原函数的标签位置会导致多层标签重叠,需要修改初始Y轴位置和层级间距:
def label_group_bar_table(ax, df): ypos = -.15 # 下调初始标签位置,避免重叠 scale = 1./df.index.size # 从外层到内层遍历索引层级 for level in range(df.index.nlevels)[::-1]: pos = 0 for label, rpos in label_len(df.index,level): lxpos = (pos + .5 * rpos)*scale ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes) add_line(ax, pos*scale, ypos) pos += rpos add_line(ax, pos*scale , ypos) ypos -= .12 # 增大层级间的垂直间距
3. 优化图表布局
调整图表尺寸和底部间距,适配多层标签:
fig = plt.figure(figsize=(10,6)) # 增大图表宽度,避免标签拥挤 # ... 其他代码 ... # 调整底部间距,预留足够空间放多层标签 fig.subplots_adjust(bottom=.25*df.index.nlevels, left=0.1)
完整修改后的代码
import numpy as np from matplotlib import pyplot as plt from itertools import groupby import pandas as pd percent_EVs = [0, 8, 21, 26, 37, 39, 41, 75, 95, 97] percent_DVs = [100, 92, 79, 74, 63, 61, 59, 25, 5, 3] num_buses = [1423, 1489, 1613, 1606, 1710, 1684, 1694, 2153, 2202, 2195] veh_range = ['DV only', 60, 120, 150, 60, 120, 150, 60, 120, 150] deployment = ['DV only', 'Low', 'Medium', 'High', 'Low', 'Medium', 'High', 'Low', 'Medium', 'High'] df = pd.DataFrame({"Percent EVs": percent_EVs, "Percent DVs": percent_DVs, "# Buses": num_buses, "Range (mi)":veh_range, "Deployment target": deployment}) # 添加大组标签并设置双层索引 df['Group'] = ['DV only'] + ['场景1']*3 + ['场景2']*3 + ['场景3']*3 df.set_index(['Group', 'Deployment target'], inplace=True) def add_line(ax, xpos, ypos): line = plt.Line2D([xpos, xpos], [ypos + .1, ypos], transform=ax.transAxes, color='black') line.set_clip_on(False) ax.add_line(line) def label_len(my_index,level): labels = my_index.get_level_values(level) return [(k, sum(1 for i in g)) for k,g in groupby(labels)] def label_group_bar_table(ax, df): ypos = -.15 scale = 1./df.index.size for level in range(df.index.nlevels)[::-1]: pos = 0 for label, rpos in label_len(df.index,level): lxpos = (pos + .5 * rpos)*scale ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes) add_line(ax, pos*scale, ypos) pos += rpos add_line(ax, pos*scale , ypos) ypos -= .12 fig = plt.figure(figsize=(10,6)) ax = fig.add_subplot(111) # 绘制堆叠柱状图 df.plot.bar(stacked=True, rot=0, alpha=0.5, legend=False, ax=ax) # 隐藏默认X轴标签 labels = ['' for item in ax.get_xticklabels()] ax.set_xticklabels(labels) ax.set_xlabel('') # 添加多层X轴标签 label_group_bar_table(ax, df) # 调整布局并显示图例 fig.subplots_adjust(bottom=.25*df.index.nlevels, left=0.1) plt.legend(loc='upper right') plt.show()
修改后会生成两层X轴:上层为大组标签(DV only、场景1/2/3),下层为每个柱子的部署目标(DV only、Low/Medium/High),并用分隔线清晰区分不同分组。
内容的提问来源于stack exchange,提问作者tcokyasar
相关产品推荐
相关产品推荐

