s_mj
s_mj

Reputation: 580

Stacked Bar Chart in Matplotlib

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

Stacked Bar Chart using Pandas in Python

How can i get this based on Matplotlib?

Upvotes: 2

Views: 2352

Answers (2)

Timothy Chan
Timothy Chan

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.

ShiftType Stacked Bar Plot

Upvotes: 3

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

enter image description here

Upvotes: 1

Related Questions