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

如何用Matplotlib/Pandas绘制非堆叠非并列的重叠水平条形图?

实现重叠水平条形图(小条形在上,大条形在下)

我完全懂你的需求——要让所有水平条形重叠在一起,小条形能显示在大条形上方,既不堆叠数值,也不会被完全遮挡,还不想用透明度导致颜色混得乱七八糟。你之前的问题出在绘图逻辑上:按列循环绘制时,同一类别的所有条形会批量画出来,不管数值大小,后面的类别会直接覆盖前面的,结果就是小条形经常被大的完全挡住。

咱们换个思路来解决:针对每个星期几(每个y轴位置),先画数值大的条形(底层),再画数值小的条形(上层),这样小条形就不会被大的完全遮盖了。下面是修改后的代码:

import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv("flow_actions.csv", index_col="weekday")

def pyplot_overlapped_chart(df, **kwargs):
    # 给每个星期几分配y轴的数值位置,确保所有条形对齐在同一水平线
    y_positions = range(len(df.index))
    # 遍历每个星期几和对应的y轴位置
    for y, weekday in zip(y_positions, df.index):
        # 获取当天所有类别的数据
        daily_values = df.loc[weekday]
        # 按数值从大到小排序,先画大的(底层),后画小的(上层)
        sorted_daily = daily_values.sort_values(ascending=False)
        # 逐个绘制当天的条形,只在第一个星期几添加图例标签(避免图例重复)
        for category, value in sorted_daily.items():
            plt.barh(y=y, width=value, 
                     label=category if y == 0 else "", 
                     height=0.8, **kwargs)
    # 设置y轴显示星期几的文字标签
    plt.yticks(y_positions, df.index)
    # 清理重复的图例项,只保留一份各类别的标签
    handles, labels = plt.gca().get_legend_handles_labels()
    unique_legend = dict(zip(labels, handles))
    plt.legend(unique_legend.values(), unique_legend.keys())
    plt.grid(axis="x")
    plt.show()

# 调用函数测试效果
pyplot_overlapped_chart(df)

关键逻辑说明:

  • 按天排序绘制:不再按类别批量绘制,而是针对每个星期几单独处理数据,把数值大的类别先画(在底层),小的后画(在上层),确保小条形能露在大条形上方。
  • 图例去重:如果每个星期几绘制时都添加图例标签,图例会重复显示多次,所以只在第一个星期几绘制时添加标签,最后通过字典去重得到干净的图例。
  • y轴位置对齐:用y_positions固定每个星期几的y轴数值位置,确保同一星期几的所有条形都对齐在同一水平线,不会出现偏移。

这样出来的效果正好符合你的预期:所有条形重叠,小条形在大条形上方,数值独立不堆叠,也不会有完全被遮挡的情况,颜色也不会因为透明度变得模糊。

内容的提问来源于stack exchange,提问作者Felipe Muniz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:15:04