Отрегулируйте правый текст внутри графика - PullRequest
1 голос
/ 23 апреля 2020

Я хотел бы напечатать какой-нибудь текст на правой стороне каждого столбца с накоплением. Я нашел способ сделать это путем аннотирования, но есть некоторые проблемы: функция autolabel кажется мне очень излишним способом аннотирования, есть ли что-нибудь проще для достижения того же визуального эффекта, проще? И что еще более важно, как я могу исправить этот текст, выходящий за правую сторону рисунка, как вы можете видеть ниже? Я пытался subplots_adjust, но не вполне сработало ...

enter image description here

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 34, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]

x = np.arange(len(labels))  # the x-axis label locations
width = 0.35  # the width of the bars

fig, ax = plt.subplots()#(figsize=(6, 4), dpi=200)
# FOR SIDE-BY-SIDE plotting:
# rects1 = ax.bar(x - width/2, men_means, width, label='Men')
# rects2 = ax.bar(x + width/2, women_means, width, label='Women')
rects1 = ax.bar(x, men_means, width, label='Men')
rects2 = ax.bar(x, women_means, width, bottom=men_means, label='Women')

# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()

def autolabel(rects):
    for rect in rects:
        height = rect.get_height()
        ax.annotate('{}'.format(height),
                    xy=(rect.get_x() + 3 * rect.get_width() / 2, rect.get_y() + height / 2),
                    xytext=(0, -5),
                    textcoords="offset points",
                    ha='center', va='center')

autolabel(rects1)
autolabel(rects2)
fig.subplots_adjust(left=0.9, right=1.9, top=0.9, bottom=0.1)
plt.show()

1 Ответ

1 голос
/ 23 апреля 2020

Если вы не возражаете против того, чтобы крайняя правая полоса была немного смещена от центра метки, вы можете просто слегка переместить ее влево, чтобы она соответствовала.

Если вы печатаете то, что возвращается При вызове bar() вы видите, что это BarContainer объект с 5 исполнителями:

<BarContainer object of 5 artists>

..., который вы можете перебирать:

Rectangle(xy=(-0.175, 0), width=0.35, height=20, angle=0)
Rectangle(xy=(0.825, 0), width=0.35, height=34, angle=0)
Rectangle(xy=(1.825, 0), width=0.35, height=30, angle=0)
Rectangle(xy=(2.825, 0), width=0.35, height=35, angle=0)
Rectangle(xy=(3.825, 0), width=0.35, height=27, angle=0)

Каждый Rectangle объект имеет метод set_xy () . Таким образом, вы можете переместить последний верхний и нижний столбец следующим образом:

bar, bar2 = rects1[4], rects2[4]
bar.set_xy((bar.get_x()-0.05,bar.get_y()))
bar2.set_xy((bar2.get_x()-0.05,bar2.get_y()))

, поместив вышеуказанный код чуть ниже вашего

rects1 = ax.bar(x, men_means, width, label='Men')
rects2 = ax.bar(x, women_means, width, bottom=men_means, label='Women')

и убрав свой вызов на subplots_adjust() и используя tight_layout() вместо этого, я смог добиться этого:

first_option

В качестве альтернативы, если вы не возражаете против расстояния между меткой и уменьшение полосы вы можете просто изменить rect.get_x() + 3 на rect.get_x() + 2.5 в функции autolabel(), чтобы получить это: second_option

...