How To Annotate A Pandas Stacked Bar, With More Than 2 Stacks?
I have the following dataset that contains weekly information for 4 different levels. I created a stacked bar chart, each stack representing a level, and each bar a week. How can I
Solution 1:
- A stacked bar is not going to equal 1 unless the sum of the values in each row are equal to 1.
- I suggest adding columns to the DataFrame with the "normed" values, then plot that. This will also resolve issues of correctly labeling the stacked bars.
- In this case, replace
df
withres = df.div(df.sum(axis=1), axis=0)
.
- The labels come from the value in the DataFrame
Imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
Data
rng=pd.date_range('2020-01-02', periods=10,freq='7D')
level=['low', 'medium', 'high', 'very_high']
np.random.seed(450)
values=np.random.randint(1, 100, size=(10, 4))
df=pd.DataFrame(index=rng, data=values, columns=level)
# display(df)
low medium high very_high
2020-01-02 64 47 79 43
2020-01-09 50 56 24 71
2020-01-16 44 66 68 21
2020-01-23 16 52 77 12
2020-01-30 92 83 9 14
2020-02-06 89 5 92 58
2020-02-13 30 66 3 89
2020-02-20 59 15 93 22
2020-02-27 95 68 56 47
2020-03-05 88 58 59 20
Horizontal Stacked Bar
plt.style.use('ggplot')
ax = df.plot(stacked=True, kind='barh', figsize=(12, 8))
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
ax.set_yticklabels(labels=df.index.date)
# .patches is everything inside of the chart
for rect in ax.patches:
# Find where everything is located
height = rect.get_height()
width = rect.get_width()
x = rect.get_x()
y = rect.get_y()
# The width of the bar is the data value and can used as the label
label_text = width # f'{width:.2f}' if you have decimal values as labels
label_x = x + width / 2
label_y = y + height / 2
ax.text(label_x, label_y, label_text, ha='center', va='center', fontsize=8)
Vertical Stacked Bar
ax = df.plot(stacked=True, kind='bar', figsize=(12, 8))
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
ax.set_xticklabels(labels=df.index.date)
# .patches is everything inside of the chart
for rect in ax.patches:
# Find where everything is located
height = rect.get_height()
width = rect.get_width()
x = rect.get_x()
y = rect.get_y()
# The width of the bar is the data value and can used as the label
label_text = f'{height}' # f'{height:.2f}' if you have decimal values as labels
label_x = x + width / 2
label_y = y + height / 2
ax.text(label_x, label_y, label_text, ha='center', va='center', fontsize=8)
- Attribution: jsoma/chart.py
Post a Comment for "How To Annotate A Pandas Stacked Bar, With More Than 2 Stacks?"