Matplotlib中不同轴水平条形图对齐叠加并保留左侧Y轴标签的实现问题
Matplotlib中不同轴水平条形图对齐叠加并保留左侧Y轴标签的实现问题
我完全懂你碰到的麻烦——用双轴的话条形对不齐,合并到单轴又会丢Y轴名称、多出不需要的图例,还会让背景条盖在数据条上面。咱们直接调整代码,用单轴布局解决所有问题,同时保留你想要的所有样式:
修改后的完整代码
import pandas as pd import matplotlib.pyplot as plt data = { 'Name': ["A", "B", "C", "D",'E'], 'Todo': [4, 5, 6, 7, 3], 'Done': [6, 2, 6, 8, 6], 'TimeRemaining': [4, 4, 4, 4, 4] } df = pd.DataFrame(data) fig, ax = plt.subplots(figsize=(10, 8)) # 第一步:先画背景的TimeRemaining条(放在最底层) df.set_index('Name').plot( kind='barh', y=["TimeRemaining"], color='whitesmoke', alpha=0.3, ax=ax, align='center', width=0.8, edgecolor='blue', legend=False # 直接不生成这个条的图例 ) # 第二步:画堆叠的Todo和Done条(在背景条上方) selected_column_names = df.columns[1:3].to_list() # 取Todo和Done stacked_ax = df.plot( kind='barh', y=selected_column_names, stacked=True, ax=ax, width=0.8, # 和背景条宽度一致 align='center' # 对齐方式一致 ) # 保持你原来的条形标注逻辑 for c in stacked_ax.containers: labels = [v.get_width() if v.get_width() > 0 else '' for v in c] stacked_ax.bar_label(c, fmt=lambda x: f'{x:.0f}' if x > 0 else '', label_type='center') # 处理图例:只保留堆叠条的图例 handles, labels = ax.get_legend_handles_labels() ax.legend(handles[:2], labels[:2], loc='upper right') # 设置标题和布局 plt.title('Status Chart') plt.tight_layout() plt.show()
关键修改点说明
- 移除双轴布局:直接用单个
ax绘制所有条形,从根源解决对齐问题——所有条形共享同一套Y轴坐标,自然完全对齐。 - 调整绘图顺序:先画
TimeRemaining的背景条,再画堆叠的数据条,这样数据条会自动覆盖在背景条上方,不会出现背景盖数据的情况。 - 保留Y轴的Name标签:通过
set_index('Name')绘制背景条时,Matplotlib会自动把Name列设为Y轴标签,不需要额外做隐藏或清空操作。 - 统一条形样式:把所有条形的
width和align参数设为一致(都是0.8和center),确保条形完全重合。 - 精准控制图例:给背景条的绘图加上
legend=False,然后手动筛选出堆叠条的图例保留,去掉不需要的背景条图例。 - 保留原有标注逻辑:你原来的条形中心标注逻辑完全保留,只需要把目标轴换成单轴即可。
这样修改后,你就能得到对齐的条形、左侧保留Name的Y轴标签,同时数据条在背景条上方,也没有多余的图例啦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

