You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 11:09:32