pythonpython-3.xmatplotlibbar-chartsubplot

Aligning matplotlib subplots one with stacked bar plot and another with line plot using matplotlib in Python


I have 2 dataframes as follows: df1.to_dict() results in

{'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.to_dict() results in

{'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}}

I want to create a sub-plot showing df1 as line plot and df2 as stacked bar plot. I tried:

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))

But i don't see the line plot: enter image description here

Next, i tried this code:

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()

enter image description here However, the x-axis is not aligned between the 2 sub-plots. How can I fix this?


Solution

  • I had to reset index of df1 and afterwards, it worked for me.

    fig, ax = plt.subplots()
    
    df2.plot(ax = ax,
            kind = "bar",
            stacked = True,
            color = color_map)
    
    df1.reset_index()[["Peak Demand PES", "Peak Demand TES", "Peak Demand DES"]].plot(ax = ax,
             marker = "o"
            )
    plt.legend(bbox_to_anchor = (1.1, 1))
    plt.show()
    

    enter image description here