Stacked Bar со значениями - PullRequest
       18

Stacked Bar со значениями

1 голос
/ 17 октября 2019
    +------------+------+------+---------+
    | promo_name | in   | out  | model   |
    +------------+------+------+---------+
    | A          | 0,87 | 0,13 | plan    |
    +------------+------+------+---------+
    | B          | 0,77 | 0,23 | plan    |
    +------------+------+------+---------+
    | C          | 0,54 | 0,46 | plan    |
    +------------+------+------+---------+
    | A          | 0,59 | 0,41 | predict |
    +------------+------+------+---------+
    | B          | 0,50 | 0,50 | predict |
    +------------+------+------+---------+
    | C          | 0,46 | 0,54 | predict |
    +------------+------+------+---------+

Привет. У меня есть данные, как в приведенной выше таблице, я хотел бы нарисовать столбчатую диаграмму со значениями, например:

enter image description here

Но пока это толькоработает так, мой код ниже:

ratio.set_index(['promo_name', 'model'], inplace=True)
ratio = ratio.reindex(index = [('A', 'plan'), ('A', 'predict'),
                              ('B', 'plan'), ('B', 'predict'),
                              ('C', 'plan'), ('C', 'predict')])
plt.rcParams["figure.figsize"] = (12,5)
ratio.plot(kind='bar', stacked=True)
plt.xticks(rotation=30)
plt.show()

Но пока я не ошибаюсь, как это исправить? Bar plot

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Используя matplotlib, вы можете легко поиграться с расположением и шириной полос:

 import matplotlib.pyplot as plt

# plan, predict
Aout = (0.87, 0.59)
Ain = (0.13, 0.41)
Bout = (0.77, 0.50)
Bin = (0.23, 0.50)  
Cout = (0.54, 0.46)
Cin = (0.46, 0.54)
width = 1.0       # the width of the bars

A_positions = [0, 1]  # Positions for A bars
p1A = plt.bar([0, 1], (1.0, 1.0), width, color='g', label='out')
p2A = plt.bar([0, 1], Ain, width, color='b', label='in')

B_positions = [3, 4]  # Positions for B bars
p1B = plt.bar(B_positions, (1.0, 1.0), width, color='g')
p2B = plt.bar(B_positions, Bin, width, color='b')

C_positions = [6, 7]  # Positions for C bars
p1C = plt.bar(C_positions, (1.0, 1.0), width, color='g')
p2C = plt.bar(C_positions, Cin, width, color='b')

positions = A_positions + B_positions + C_positions  # All together for ticks
plt.xticks(positions, ('A (plan)', 'A (predict)', 'B (plan)', 'B (predict)', 'C (plan)', 'C (predict)'))
plt.xticks(rotation=70)
plt.yticks([1, 0])
plt.legend()
plt.tight_layout()

И добавить текстовые метки (вы можете поиграть с местоположением):

plt.text(A_positions[0] - 0.25, Ain[0] / 2, str(Ain[0]))
plt.text(A_positions[0] - 0.25, Aout[0] / 2, str(Aout[0]))
plt.text(A_positions[1] - 0.25, Ain[1] / 2, str(Ain[1]))
plt.text(A_positions[1] - 0.25, Aout[1] / 2 + 0.5, str(Aout[1]))

plt.text(B_positions[0] - 0.25, Bin[0] / 2, str(Bin[0]))
plt.text(B_positions[0] - 0.25, Bout[0] / 2, str(Bout[0]))
plt.text(B_positions[1] - 0.25, Bin[1] / 2, str(Bin[1]))
plt.text(B_positions[1] - 0.25, Bout[1] / 2 + 0.5, str(Bout[1]))


plt.text(C_positions[0] - 0.25, Cin[0] / 2, str(Cin[0]))
plt.text(C_positions[0] - 0.25, Cout[0] / 2 + 0.5, str(Cout[0]))
plt.text(C_positions[1] - 0.25, Cin[1] / 2, str(Cin[1]))
plt.text(C_positions[1] - 0.25, Cout[1] / 2 + 0.5, str(Cout[1]))

enter image description here

1 голос
/ 17 октября 2019

Вот пример использования matplotlib.

Подготовьте исходные данные:

import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

source = {'promo_name': {0: 'A', 1: 'B', 2: 'C', 3: 'A', 4: 'B', 5: 'C'},  
         'in': {0: 0.87, 1: 0.77, 2: 0.54, 3: 0.59, 4: 0.5, 5: 0.46},
         'out': {0: 0.13, 1: 0.23, 2: 0.46, 3: 0.41, 4: 0.5, 5: 0.54},
         'model': {0: 'plan', 1: 'plan',2: 'plan', 3: 'predict', 4: 'predict', 5: 'predict'}}

ratio = pd.DataFrame.from_dict(source) 
ratio.head()

Out[1]:

         promo_name    in   out      model
    0   A            0.87  0.13   plan    
    1   B            0.77  0.23   plan    
    2   C            0.54  0.46   plan    
    3   A            0.59  0.41   predict 
    4   B            0.50  0.50   predict 
    5   C            0.46  0.54   predict 

это решение:

ind = list(ratio.index)

plt.rcParams["figure.figsize"] = (12,5)

bars_b = plt.bar(list(range(len(ind))), ratio['in'], width=0.3, color = 'b', label = 'in')
bars_r = plt.bar(list(range(len(ind))), ratio['out'], bottom = ratio['in'], width=0.3, color = 'r', label = 'out')

plt.xticks(rotation=30)
plt.legend()

for i in range(len(bars_b)):
    bar_b = bars_b[i]
    bar_r = bars_r[i]

    plt.gca().text(bar_b.get_x()+ bar_b.get_width()/2, 
                   bar_b.get_height()/2,
                   ratio['in'][i], 
                   ha='center', 
                   color = 'w')    

    plt.gca().text(bar_r.get_x()+ bar_r.get_width()/2, 
                   bar_r.get_height()/2 + bar_b.get_height(),ratio['out'][i], ha='center', color = 'w')


plt.show()

здесь результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...