如何解决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()
关键说明
- 图层顺序调整:将柱状图的
zorder设为1,折线图设为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
相关产品推荐
相关产品推荐

