Matplotlib:避免注释和刻度y_tick标签重叠

时间:2019-07-05 21:01:56

标签: python matplotlib annotate

我经历了几个问题,但似乎都没有解决与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 :(得分:0)

由于以上评论,我认为用找到的解决方案来完成帖子是一个好主意。在乔迪·克利马克(Jody Klymak)的评论中,我选择了第三个选项。

我添加了几行以查找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