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

Matplotlib绘制叠加柱状图对比新旧时序数据 按差值正负区分颜色

问题原因

直接绘制完整新值柱的逻辑是从y轴0点开始画全高度柱,必然会覆盖下层的旧值蓝色柱。正确的做法是不要绘制完整新值柱,仅单独绘制差值段,通过bottom参数控制差值段的起始位置,就能保留完整的旧值蓝色基底。

实现步骤
  • 首先绘制全量旧值的蓝色柱,作为所有月份的基准层
  • 差值为正(新值>旧值)时:差值段的起始高度为旧值,柱高等于正差值,填充绿色,叠加在蓝色柱上方展示增长幅度
  • 差值为负(新值<旧值)时:差值段的起始高度为新值,柱高等于差值的绝对值,填充红色,叠加在蓝色柱的上部区间展示下降幅度
完整实现代码
import matplotlib.pyplot as plt
import pandas as pd

# 替换为你自己的数据集加载逻辑即可
data = pd.DataFrame({
    "DATE": ["08/22", "09/22", "10/22", "11/22"],
    "OLD VALUE": [10000, 5000, 8000, 20000],
    "NEW VALUE": [9500, 5500, 9000, 18000],
    "DELTA": [-500, 500, 1000, -2000]
})

# 绘制旧值蓝色基底
plt.bar(data["DATE"], data["OLD VALUE"], color="#1f77b4", label="旧值")

# 绘制增长段(绿色)
gain_data = data[data["DELTA"] >= 0]
plt.bar(
    gain_data["DATE"],
    gain_data["DELTA"],
    bottom=gain_data["OLD VALUE"],
    color="green",
    label="增长值"
)

# 绘制下降段(红色)
loss_data = data[data["DELTA"] < 0]
plt.bar(
    loss_data["DATE"],
    -loss_data["DELTA"],
    bottom=loss_data["NEW VALUE"],
    color="red",
    label="减少值"
)

# 可选优化:添加图例和差值标签
plt.legend()
for _, row in data.iterrows():
    label_y = row["NEW VALUE"] if row["DELTA"] < 0 else row["OLD VALUE"] + row["DELTA"]
    va_align = "top" if row["DELTA"] < 0 else "bottom"
    plt.text(
        row["DATE"],
        label_y,
        f'{int(row["DELTA"]):+}',
        ha="center",
        va=va_align
    )

plt.show()
最终效果
  • 所有月份从0到旧值的柱段始终为蓝色,不会被覆盖
  • 增长月份:蓝色柱上方延伸出对应长度的绿色柱,柱顶为新值
  • 下降月份:蓝色柱上部覆盖对应长度的红色柱,红色柱顶为新值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:33:25