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

如何解决Matplotlib中stacked bar plot与line plot的X轴对齐问题?

堆叠柱状图与折线图X轴对齐问题

数据情况

两个DataFrame的数据如下:

df1 的数据(df1.to_dict() 结果)

{'Peak Demand PES': {2023: 124126.91,
  2025: 154803.41,
  2030: 231494.66,
  2040: 483217.66000000003,
  2050: 1004207.86},
 'Peak Demand TES': {2023: 125724.8,
  2025: 142959.13999999998,
  2030: 186044.99000000002,
  2040: 288307.99,
  2050: 424827.79},
 'Peak Demand DES': {2023: 125263.94,
  2025: 152080.7,
  2030: 219122.6,
  2040: 385960.3,
  2050: 671678.9}}

df2 的数据(df2.to_dict() 结果)

{'Biomass PP': {2023: 783.2,
  2025: 840.5,
  2030: 990.5,
  2040: 711.0,
  2050: 167.0},
 'Coal PP': {2023: 51235.8,
  2025: 48912.8,
  2030: 41527.8,
  2040: 24125.8,
  2050: 13409.8},
 'Diesel PP': {2023: 10498.41,
  2025: 10347.69,
  2030: 9020.56,
  2040: 6227.39,
  2050: 3049.75},
 'Geothermal PP': {2023: 1004.4,
  2025: 1074.4,
  2030: 1249.4,
  2040: 1148.4,
  2050: 328.3},
 'HFO PP': {2023: 6462.1,
  2025: 6358.04,
  2030: 5468.59,
  2040: 2521.35,
  2050: 205.58},
 'Large Hydro Dam PP': {2023: 28363.22,
  2025: 32053.86,
  2030: 41259.46,
  2040: 43980.76,
  2050: 32379.44},
 'Natural Gas PP': {2023: 116472.48,
  2025: 110897.38,
  2030: 106429.18000000001,
  2040: 69705.68,
  2050: 8774.35},
 'PumpStorage': {2023: 3721.0,
  2025: 4063.0,
  2030: 4918.0,
  2040: 6498.0,
  2050: 6498.0},
 'Solar PV - Utility PP': {2023: 10422.59,
  2025: 12731.45,
  2030: 18576.6,
  2040: 23338.15,
  2050: 16738.45},
 'Solar Thermal PP': {2023: 1095.0,
  2025: 1095.0,
  2030: 1095.0,
  2040: 670.0,
  2050: nan},
 'Transmission': {2023: 25.83,
  2025: 28.01,
  2030: 33.46,
  2040: 43.76,
  2050: 47.56},
 'Wind PP': {2023: 8193.02,
  2025: 9297.62,
  2030: 12193.52,
  2040: 7261.3,
  2050: 1735.0}}

尝试的代码与问题

第一次尝试(折线图不可见)

fig, ax = plt.subplots()

df1.plot(
    ax = ax,
    zorder = 0,
    marker = "o"
)

df2.plot(ax = ax,
        kind = "bar",
        stacked = True,
        color = color_map,
        zorder = 1)

plt.legend(bbox_to_anchor = (1.1, 1))

问题:折线图被堆叠柱状图完全覆盖,无法显示。

第二次尝试(X轴未对齐)

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

# Plot stacked bars
df2.plot(kind="bar",
                      stacked=True,
                      ax=ax,
                      color=color_map,
                      width=0.8,
                      position=0)

years = df1.index
offset = 0.5  # try small shifts like -0.2, 0.2, etc.

for col in df1.columns:
    ax.plot([x for x in range(len(years))],
            df1[col].values,
            label=col,
            linewidth=3,
            linestyle='--',
            marker='o')
    
# Adjust legend
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels, bbox_to_anchor=(1.1, 1))

plt.ylabel("GW")
plt.tight_layout()
plt.show()

问题:折线图可见,但折线的X轴刻度位置与柱状图的X轴位置不对齐。


解决方案

核心问题有两个:一是图层顺序导致折线被覆盖,二是手动指定X坐标未匹配柱状图的中心位置。以下是修正方案:

修正后的代码(推荐)

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

# 先绘制堆叠柱状图,设置zorder为1(底层)
df2.plot(kind="bar",
         stacked=True,
         ax=ax,
         color=color_map,
         width=0.8)

# 绘制折线图,设置zorder为2(上层),pandas会自动对齐X轴索引
df1.plot(ax=ax,
         marker="o",
         linewidth=3,
         linestyle='--',
         zorder=2)

# 调整图例位置
plt.legend(bbox_to_anchor=(1.1, 1))
plt.ylabel("GW")
plt.tight_layout()
plt.show()

关键说明

  1. 图层顺序调整:将柱状图的zorder设为1,折线图设为2,确保折线显示在柱状图上方,解决第一次尝试中折线被覆盖的问题。
  2. 自动X轴对齐:直接调用df1.plot(ax=ax)时,pandas会自动识别两个DataFrame的X轴索引(年份),将折线的点精准对齐到每个柱状图组的中心位置,无需手动计算坐标。

手动绘制折线的对齐方案(自定义样式时用)

如果需要手动循环绘制折线,可通过获取柱状图的中心位置来对齐:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

# 绘制堆叠柱状图
df2.plot(kind="bar",
         stacked=True,
         ax=ax,
         color=color_map,
         width=0.8)

# 获取每个柱状图组的中心位置
bars = ax.patches
# 堆叠柱状图中,每组的第一个柱子的x+width/2就是该组的中心
bar_centers = [bar.get_x() + bar.get_width()/2 for bar in bars[::len(df2.columns)]]

# 手动绘制折线并对齐
for col in df1.columns:
    ax.plot(bar_centers,
            df1[col].values,
            label=col,
            linewidth=3,
            linestyle='--',
            marker='o',
            zorder=2)

plt.legend(bbox_to_anchor=(1.1, 1))
plt.ylabel("GW")
plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:40:54