Matplotlib: линии сверху баров, легенда слева, без сплайнов - PullRequest
0 голосов
/ 21 января 2020

У меня проблемы с настройкой графика ниже.

graph

Вот как выглядит фрейм данных:

   Year  Some  All     Ratio
0  2016     9  157  0.057325
1  2017    13  189  0.068783
2  2018    21  216  0.097222
3  2019    18  190  0.094737
4  2020    28  284  0.098592

Вот что я хочу сделать:

  • Оранжевая линия должна быть перед решеткой. Я попытался использовать параметр zorder, и это не помогло. Я также попытался изменить порядок объекта осей, но он ничего не сделал.
  • Я хочу, чтобы легенда была слева. В приведенном ниже коде вы заметите, что я использую довольно большой аргумент figsize. Если я использую меньший, легенда волшебным образом переместится влево, но я не хочу использовать меньший.
  • Я хочу пометить гистограммы в верхней части каждого бара соответствующим значением , Я пытался перебирать каждое значение и индивидуально аннотировать столбцы с помощью ax.annotate, но я не мог автоматически центрировать значения. В этом минимальном примере все значения имеют длину три цифры, но в исходных данных у меня есть числа длиной четыре цифры, и я не смог найти хороший способ сделать его центрированным для всех них.
  • Наконец Хочу избавиться от верхних и правых шипиков. Мой код ниже по какой-то причине не удалил их.

Ниже приведен код, помогающий людям начать работу.

data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
 'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
 'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
 'Ratio': {0: 0.05732484076433121,
  1: 0.06878306878306878,
  2: 0.09722222222222222,
  3: 0.09473684210526316,
  4: 0.09859154929577464}}

df = __import__("pandas").DataFrame(data)

ax = df.plot(x="Year", y="Ratio",
                 kind="line", linestyle='-', marker='o', color="orange",
                 figsize=((24,12))
                )
df.plot(x="Year", y="All",
            kind="bar", ax=ax, secondary_y=True
           )

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

1 Ответ

0 голосов
/ 21 января 2020

Следующий ответ был скопирован из этого.

import pandas as pd
from matplotlib import pyplot as plt

data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
        'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
        'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
        'Ratio': {0: 0.05732484076433121,
                  1: 0.06878306878306878,
                  2: 0.09722222222222222,
                  3: 0.09473684210526316,
                  4: 0.09859154929577464}}

df = pd.DataFrame(data)

ax1 = df.plot(x="Year", y="All",
              kind="bar",
              )
for i, a in df.All.items():
    ax1.text(i, a, str(a), ha='center', va='bottom', fontsize=18)
xlims = ax1.get_xlim()

ax2 = df.plot(x="Year", y="Ratio",
              kind="line", linestyle='-', marker='o', color="orange", ax=ax1, secondary_y=True,
              figsize=((24, 12))
              )
ax2.set_xlim(xlims)  # needed because the line plot shortens the xlims

# ax1.get_legend().set_bbox_to_anchor((0.03, 0.9, 0.1, 0.1)) # unpredictable behavior when loc='best'
# ax1.legend(loc='upper left') # in our case, this would create a second legend

ax1.get_legend().remove() # remove badly placed legend
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(handles=handles1 + handles2,   # create a new legend
           labels=labels1 + labels2,
           loc='upper left')

# ax1.yaxis.tick_right()  # place the yticks for ax1 at the right
ax2.yaxis.tick_left()  # place the yticks for ax2 at the left
ax2.set_ylabel('Ratio')
ax2.yaxis.set_label_position('left')
ax1.axes.yaxis.set_ticks([]) # remove ticks

for ax in (ax1, ax2):
    for where in ('top', 'right'):
        ax.spines[where].set_visible(False)

plt.show()

img

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