Matplotlib注释文本在轴外扩展

时间:2019-02-07 21:00:59

标签: python python-3.x matplotlib

我有一个散点图,其中有多个点,有时是重叠的,因此在每个点上都有一个悬停框注释(使用solution here来创建)。为了处理多个要点,有时还要进行较长的描述,注释中有一个换行符。问题是多行,注记框会建立而不是向下移动,从而使其超出轴,如下所示。有没有一种方法可以使文本从轴下方的直线开始,然后向下扩展到绘图中?

相关代码:

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)

x = np.random.rand(15)
y = np.random.rand(15)
names = np.array(list("ABCDEFGHIJKLMNO"))
c = np.random.randint(1,5,size=15)

norm = plt.Normalize(1,4)
cmap = plt.cm.RdYlGn

fig,ax = plt.subplots()
sc = plt.scatter(x,y,c=c, s=100, cmap=cmap, norm=norm)

annot = ax.annotate("", xy=(0.05, 0.95), xycoords='axes fraction',
                    bbox=dict(boxstyle="round", fc="w"),
                    zorder=1000)
annot.set_visible(False)

def update_annot(ind):

    pos = sc.get_offsets()[ind["ind"][0]]
    annot.xy = pos
    text = "{}".format("\n".join([f"{n}: {names[n]}" for n in ind["ind"]]))
    annot.set_text(text)
    annot.get_bbox_patch().set_facecolor(cmap(norm(c[ind["ind"][0]])))
    annot.get_bbox_patch().set_alpha(0.4)


def hover(event):
    vis = annot.get_visible()
    if event.inaxes == ax:
        cont, ind = sc.contains(event)
        if cont:
            update_annot(ind)
            annot.set_visible(True)
            fig.canvas.draw_idle()
        else:
            if vis:
                annot.set_visible(False)
                fig.canvas.draw_idle()

fig.canvas.mpl_connect("motion_notify_event", hover)

plt.show()

注释中一行文本的外观

enter image description here

注释中有两行文字时的外观(悬停点与两点重叠)。理想情况下,将0: A放在8: I所在的位置,然后在其下方的8: I

enter image description here

1 个答案:

答案 0 :(得分:3)

我认为该代码对于问一个简单的问题如何对齐文本或注解有点过大。

这是通过verticalalignmentva参数(或horizontalalignment / ha)完成的。将其设置为"top",以使文本从顶部对齐。

使用xytexttextcoords自变量(就像在链接的代码中一样)为文本提供一些以点为单位的偏移量(即,与图形的大小无关)。

import matplotlib.pyplot as plt

fig,ax = plt.subplots()

annot = ax.annotate("Three\nLine\nText", xy=(0, 1), xycoords='axes fraction',
                    xytext=(5,-5), textcoords="offset points",
                    bbox=dict(boxstyle="round", fc="w"), va="top")

plt.show()

enter image description here