Как добавить метки на диаграмму с накоплением (более 2 стеков) в pandas - PullRequest
0 голосов
/ 26 марта 2020

У меня есть следующий набор данных, который содержит еженедельную информацию для 4 различных уровней. Я создал гистограмму с накоплением, каждый стек представляет уровень, а каждый бар - неделю. Как добавить значения, соответствующие каждому цвету на графике?

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

Я пытался использовать аналогичный вопрос, используя этот код, но, похоже, он не работает для 4-х осей. Кроме того, все бары должны быть равны 1, и они не

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

enter image description here

1 Ответ

1 голос
/ 27 марта 2020

Примечание

  • Столбец с накоплением не будет равен 1, если сумма значений в каждой строке не равна 1.
    • Я предлагаю добавить столбцы в DataFrame с «нормированные» значения, а затем построить график. Это также решит проблемы с правильной маркировкой столбцов с накоплением.
    • В вашем случае замените df на res = df.div(df.sum(axis=1), axis=0).
  • Метки происходят от значения в DataFrame

Импорт

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

Данные

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)

enter image description here

Горизонтальный столбец с накоплением

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

# .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
    label_y = y + height / 2
    ax.text(label_x, label_y, label_text, ha='right', va='center', fontsize=8)

enter image description here

Вертикальный с накоплением Бар

ax = df.plot(stacked=True, kind='bar', figsize=(12, 8))
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)

# .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 - 0.125
    label_y = y + height / 2
    ax.text(label_x, label_y, label_text, ha='right', va='center', fontsize=8)

enter image description here

...