How to annotate a pandas stacked bar, with more than 2 stacks?

孤街浪徒 提交于 2020-08-19 11:07:13

问题


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 add the values corresponding to each color on chart?

import numpy as np
import pandas as pd
import matplotlib as plt
plt.style.use('ggplot')
%matplotlib inline

rng=pd.date_range('2020-01-02', periods=10,freq='7D')
level=['low', 'medium', 'high', 'very_high']
values=np.random.randint(1, 100, size=(10, 4))
df=pd.DataFrame(index=rng, data=values, columns=level)

df.plot.bar(stacked=True,figsize=(15,10), alpha=0.6)
plt.legend(loc='upper right', bbox_to_anchor=(1.1, 1.05))

I tried using a similar question using this code, but it does not seem to work for 4 axis. Also, all the bars should be equal to 1 and they aren't

res = df.div(df.sum(axis=1), axis=0)
fig = plt.figure(facecolor="white")

ax = fig.add_subplot(1, 1, 1)
bar_width = 3
bar_l = df.index
# tick_pos = [i + (bar_width / 2) for i in bar_l]
ax1 = ax.bar(bar_l, res['low'], width=bar_width, label="A", color="green")
ax2 = ax.bar(bar_l, res['medium'], bottom=res['low'], width=bar_width, label="medium", color="blue")
ax3 = ax.bar(bar_l, res['high'], bottom=res['low'], width=bar_width, label="high", color="yellow")
ax4 = ax.bar(bar_l, res['very_high'], bottom=res['low'], width=bar_width, label="very_high", color="red")


回答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 with res = 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


来源:https://stackoverflow.com/questions/60875468/how-to-annotate-a-pandas-stacked-bar-with-more-than-2-stacks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!