pandas : plot stacked barchart for row values

Question:

I have below data frame and I wanted to plot stacked bar chart for ‘closed’/’open’ state.

             state  requests
created                          
2016-09-28    OPEN              1
2017-02-03    OPEN              1 
2017-06-15  CLOSED              1
2017-06-15    OPEN              1
2017-06-16  CLOSED              2
2017-08-23    OPEN              1
2017-10-25    OPEN              1
2018-01-19    OPEN              1
2018-03-01    OPEN              1
2018-03-05    OPEN              1
2018-06-12    OPEN              1
2018-06-15    OPEN              1

I have tried following(df_temp is dataframe of above data)

fig,ax = plt.subplots()
ax.set_ylabel('Requests')
df_closed = df_temp[df_temp['state'] == 'CLOSED']
df_open = df_temp[df_temp['state'] == 'OPEN']

b = ax.bar(x = df_open.index.get_level_values(0), height = df_open['requests'])
a = ax.bar(x = df_closed.index.get_level_values(0), height = df_closed['requests'],bottom = df_open['requests'])

but it is giving me error as

ValueError: shape mismatch: objects cannot be broadcast to a single shape
Asked By: Vishal Soni

||

Answers:

I’m posting a proper answer here since it’s probably easier than keeping commenting. This also includes the further case (asked in the comment) where there might be an arbitrary, unknown set of values in state.

fig, ax = plt.subplots()
index = df_temp.index.unique()
cumsum = pd.Series(0, index=index)
for s in df.state.unique():
    new_vals = df_temp.loc[df.state == s, 'requests'].reindex(index).fillna(0)
    ax.bar(index, new_vals, bottom = cumsum)
    cumsum += new_vals
ax.set_ylabel('Requests')

This should take care of everything. Within each ax, I’d probably also put a label=s and add an ax.legend() in the end to map each resulting color to one status.

Answered By: Marco Spinaci

Since you mention pandas pivot function – you can transform your dataset with it in one line before you stack the bar chart:

df_temp.pivot(columns = "state", values = "requests").plot(kind = "bar", stacked = True)

Now we can additionally beautify the graph – label the y-axis, rotate the x-tick labels:

plt.ylabel("Requests")
plt.xticks(rotation = 45, ha = "right")
plt.tight_layout()
plt.show()
Answered By: Mr. T