Reputation: 580
I am trying to create stacked Bar Chart in Matplotlib. I have created a simple one using Pandas, but i am now interested in Matplotlib one but cant make it work.
My data
ShiftType ShiftNumber cnt
0 Non-Standard 1.0 154478
1 Non-Standard 2.0 140421
2 Non-Standard 3.0 159990
3 Standard 1.0 211100
4 Standard 2.0 198652
5 Standard 3.0 190857
Code that works using Pandas.
df.groupby(by=['ShiftType','ShiftNumber']).size().rename('cnt').unstack().plot(kind='bar', stacked=True)
plt.legend(title='Shift Numbers', bbox_to_anchor=(1.0, 1), loc='upper left')
How can i get this based on Matplotlib?
Upvotes: 2
Views: 2352
Reputation: 503
The sample code you provided does not accurately tally the sum. It's also somewhat unclear what you mean by "create stacked Bar Chart in Matplotlib" as the Pandas plot() function you called is a matplotlib integration. Regardless, as standard (and possibly best) practice, I regularly use figure and axes to set up my plots. This allows careful control of the plots which I think you are trying to do here.
I would suggest this code as a solution to your question and starting point for further plot manipulation.
fig, ax = plt.subplots()
df.groupby(['ShiftType', 'ShiftNumber']) \
['cnt'].sum() \
.reset_index() \
.pivot_table(index='ShiftType', columns='ShiftNumber', values='cnt') \
.plot(kind='bar', stacked=True, ax=ax)
ax.legend(title='Shift Numbers', bbox_to_anchor=(1.0, 1), loc='upper left')
I would then add some standard features that every chart should have, for example a y-label and a title.
ax.set_ylabel('cnt')
ax.set_title('Count of Shift Types')
Combining those, you will then get this final plot.
Upvotes: 3
Reputation: 11474
There might be someting more compact but here is a solution. Here is your df
ShiftType ShiftNumber cnt
0 Non-Standard 1.0 154478
1 Non-Standard 2.0 140421
2 Non-Standard 3.0 159990
3 Standard 1.0 211100
4 Standard 2.0 198652
5 Standard 3.0 190857
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
fig, ax = plt.subplots(figsize=(10,7))
m = df['ShiftNumber'].drop_duplicates()
margin_bottom = np.zeros(len(df['ShiftType'].drop_duplicates()))
colors = ["#006D2C", "#31A354","#74C476"]
for num, m in enumerate(m):
values = list(df[df['ShiftNumber'] == m].loc[:, 'cnt'])
df[df['ShiftNumber'] == m].plot.bar(x='ShiftType',y='cnt', ax=ax, stacked=True,
bottom = margin_bottom, color=colors[num], label=m)
margin_bottom += values
plt.show()
Upvotes: 1