Matplotlib: избегайте аннотаций и помечайте метки y_tick перекрывающимися - PullRequest
0 голосов
/ 06 июля 2019

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

На самом деле моя проблема довольно проста.Я использую следующие строки для создания графика, который вставляю чуть ниже них.Я использую аннотацию, чтобы показать, каково последнее значение для обеих строк.Я устанавливаю положение аннотации на основе отношения последнего значения к общему диапазону оси Y.Это работает довольно хорошо, за исключением случаев, когда аннотация перекрывает метку.Это не такая уж большая проблема, но она выглядит не очень хорошо при включении графика в отчет.

Вот код - я опускаю строки, которые манипулируют данными:

x = MERVAL.index[(MERVAL.index >= '2014-01-01')]
y1 = MERVAL['MERVAL'][(MERVAL.index >= '2014-01-01')]
y2 = MERVAL['MERVAL_USD'][(MERVAL.index >= '2014-01-01')]
last_date = MERVAL.tail(1).index
right_limit = last_date + datetime.timedelta(days=30)
months = mdates.MonthLocator(1)
monthsFmt = mdates.DateFormatter('%m/%Y')
datemin = datetime.datetime.strptime('01/01/2014', '%m/%d/%Y')
f, ax = plt.subplots()
ax.plot(x,y1, color='b', linewidth=1, label='MERVAL')
ax2 = ax.twinx()
ax2.plot(x,y2, color='r', linewidth=1, label='MERVAL in USD')
ax.set_title('MERVAL',fontsize=20,color='green')
ax.xaxis.set_major_locator(months)
ax.xaxis.set_major_formatter(monthsFmt)
ax.set_xlim(left=datemin, right=right_limit)
ax2.set_xlim(left=datemin, right=right_limit)
ax.grid(axis='x', linestyle=':')
ax.legend(loc=(0.01,0.9))
ax2.legend(loc=(0.01,0.8))
bottom, top = ax.get_ylim()
bottom1, top1 = ax2.get_ylim()
MERVAL_last_price = MERVAL.iloc[-1,0]
MERVAL_USD_last_price = MERVAL.iloc[-1,1]
ax.annotate(str(MERVAL.iloc[-1,0].round(2)), xy=(0,(MERVAL.iloc[-1,0])), xytext=(-0.13 ,((MERVAL_last_price - bottom) / (top - bottom))), xycoords='axes fraction', color='b', annotation_clip=False)
ax2.annotate(str(MERVAL.iloc[-1,1].round(2)), xy=(1,(MERVAL.iloc[-1,1])), xytext=(1.01,((MERVAL_USD_last_price - bottom1) / (top1 - bottom1))), xycoords='axes fraction',color='r', annotation_clip=False)
plt.show()

Вот график.Выделено желтым цветом, что я хотел бы исправить: enter image description here

Как отмечено в комментарии ниже, я бы хотел, чтобы красная метка была либо выше (желательно, поскольку это большее число)или ниже метки).Я знаю, как сделать это далеко направо или налево.Я также знаю, как переместить его вручную вверх или вниз.Есть ли способ заставить Matplotlib проверять, не перекрывается ли он с меткой тика, и автоматически перемещать его вверх или вниз?

Спасибо

1 Ответ

0 голосов
/ 08 июля 2019

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

Я добавил несколько строк, чтобы найти значения y_ticks, удалил все тики в определенном диапазоне вокруг последнего значения и, наконец, установил новые y_ticks.

Обновленный код:

x = MERVAL.index[(MERVAL.index >= '2014-01-01')]
y1 = MERVAL['MERVAL'][(MERVAL.index >= '2014-01-01')]
y2 = MERVAL['MERVAL_USD'][(MERVAL.index >= '2014-01-01')]
last_date = MERVAL.tail(1).index
right_limit = last_date + datetime.timedelta(days=30)
months = mdates.MonthLocator(1)
monthsFmt = mdates.DateFormatter('%m/%Y')
datemin = datetime.datetime.strptime('01/01/2014', '%m/%d/%Y')
f, ax = plt.subplots()
ax.plot(x,y1, color='b', linewidth=1, label='MERVAL')
ax2 = ax.twinx()
ax2.plot(x,y2, color='r', linewidth=1, label='MERVAL in USD')
ax.set_title('MERVAL',fontsize=20,color='green')
ax.xaxis.set_major_locator(months)
ax.xaxis.set_major_formatter(monthsFmt)
ax.set_xlim(left=datemin, right=right_limit)
ax2.set_xlim(left=datemin, right=right_limit)
ax.grid(axis='x', linestyle=':')
ax.legend(loc=(0.01,0.9))
ax2.legend(loc=(0.01,0.8))
bottom, top = ax.get_ylim()
bottom1, top1 = ax2.get_ylim()
MERVAL_last_price = MERVAL.iloc[-1,0]
MERVAL_USD_last_price = MERVAL.iloc[-1,1]
ax.annotate(str(MERVAL.iloc[-1,0].round(2)), xy=(0,(MERVAL.iloc[-1,0])), xytext=(-0.13 ,((MERVAL_last_price - bottom) / (top - bottom))), xycoords='axes fraction', color='b', annotation_clip=False)
ax2.annotate(str(MERVAL.iloc[-1,1].round(2)), xy=(1,(MERVAL.iloc[-1,1])), xytext=(1.01,((MERVAL_USD_last_price - bottom1) / (top1 - bottom1))), xycoords='axes fraction',color='r', annotation_clip=False)
loc = ax2.get_yticks()
space = loc[1] - loc[0]
print(space)
new_loc = list()
for x in loc:
    if x <= MERVAL.iloc[-1,1] + space / 2 and x >= MERVAL.iloc[-1,1] - space / 2:
        new_loc.append('')
    else:
        new_loc.append(x)
ax2.set_yticklabels(new_loc)
plt.show()

Обновленный график:

enter image description here

...