I have a pandas dataframe df
which looks as follows:
World Coal Oil and natural gas Nuclear Renewables Storage Electricity networks
2015 79.6 79.8 28.4 309.9 1.6 316.8
2016 70.9 83.2 33.7 318.3 2.5 327.9
2017 65.8 77.2 36.9 325.9 3.1 318.6
2018 64.7 64.5 34.0 359.0 4.7 310.3
2019 62.2 67.4 34.8 393.2 4.6 291.8
2020 56.4 55.3 39.5 418.4 6.2 291.6
2021 51.6 67.0 43.7 445.8 9.4 308.1
2022 48.2 70.8 49.3 471.7 18.3 318.2
df.to_dict()
is as shown below:
{'Coal': {2015: 79.6,
2016: 70.9,
2017: 65.8,
2018: 64.7,
2019: 62.2,
2020: 56.4,
2021: 51.6,
2022: 48.2},
'Oil and natural gas': {2015: 79.8,
2016: 83.2,
2017: 77.2,
2018: 64.5,
2019: 67.4,
2020: 55.3,
2021: 67.0,
2022: 70.8},
'Nuclear': {2015: 28.4,
2016: 33.7,
2017: 36.9,
2018: 34.0,
2019: 34.8,
2020: 39.5,
2021: 43.7,
2022: 49.3},
'Renewables': {2015: 309.9,
2016: 318.3,
2017: 325.9,
2018: 359.0,
2019: 393.2,
2020: 418.4,
2021: 445.8,
2022: 471.7},
'Storage': {2015: 1.6,
2016: 2.5,
2017: 3.1,
2018: 4.7,
2019: 4.6,
2020: 6.2,
2021: 9.4,
2022: 18.3},
'Electricity networks': {2015: 316.8,
2016: 327.9,
2017: 318.6,
2018: 310.3,
2019: 291.8,
2020: 291.6,
2021: 308.1,
2022: 318.2}}
I am able to create a stacked bar plot using this entire data using
colors = ["black","gray","red","green","blue","yellow"]
df.plot(kind = "bar", stacked = True, color = colors)
The stacked bar plot is as shown below:
However, I'd like to have three separate bars for Generation, Storage and Electricity Networks. Generation here refers to data for Coal, Oil and natural gas, Nuclear and Renewables. How am I able to do it using matplotlib in Python?
CodePudding user response:
You can plot first the stacked bars right aligned and then, on the same axes, the remaining bars left aligned.
You can then fix the legend to your liking.
ax = df.iloc[:,:4].plot.bar(stacked=True, align='edge', width=-.2, color=colors[:4])
df.iloc[:,4:].plot.bar(ax=ax, align='edge', width=.4, color=colors[4:])
handles, labels = ax.get_legend_handles_labels()
labels = [f'Generation ({l})' if i < 4 else l for i,l in enumerate(labels)]
ax.legend(handles, labels, bbox_to_anchor=(1, 1))