matplotlib自动缩放轴至包括注解(matplotlib autoscale axes to

2019-06-26 09:30发布

有谁知道一个简单的方法来扩大绘图区,包括注解? 我有一个数字,其中有些标签很长和/或多个字符串,而非剪裁这些到轴,我想扩大轴,包括注释。

Autoscale_view不这样做,并ax.relim不拿起注释的位置,这样似乎并没有成为一种选择。

我试图做类似下面的代码,它遍历所有注释(假设他们是在数据坐标),以获得他们的程度,然后相应地更新轴,但最好我不希望我的数据坐标标注(他们是从实际数据点偏移)。

xmin, xmax = plt.xlim()
ymin, ymax = plt.ylim()
# expand figure to include labels
for l in my_labels:
    # get box surrounding text, in data coordinates
    bbox = l.get_window_extent(renderer=plt.gcf().canvas.get_renderer())
    l_xmin, l_ymin, l_xmax, l_ymax = bbox.extents
    xmin = min(xmin, l_xmin); xmax = max(xmax, l_xmax); ymin = min(ymin, l_ymin); ymax = max(ymax, l_ymax)
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)

Answer 1:

我这个挣扎过。 关键的一点是,matplotlib没有确定文本有多大将是直到它实际上已经被画出。 所以,你需要显式调用plt.draw()然后调整自己的边界,然后再绘制它。

get_window_extent方法应该得到在显示坐标,而不是数据坐标的答案,每文档 。 但是,如果画布还没有被抽的是,它似乎什么坐标系统,你在指定的响应textcoords关键字参数来annotate 。 这就是为什么你上面的代码工作使用textcoords='data' ,而不是'offset points'

下面是一个例子:

x = np.linspace(0,360,101)
y = np.sin(np.radians(x))

line, = plt.plot(x, y)
label = plt.annotate('finish', (360,0),
                     xytext=(12, 0), textcoords='offset points',
                     ha='left', va='center')

bbox = label.get_window_extent(plt.gcf().canvas.get_renderer())
print(bbox.extents)

array([ 12.     ,  -5.     ,  42.84375,   5.     ])

我们希望改变的限制使得文本标签是轴内。 值bbox给出的是没有太大的帮助:因为这是在点相对于标记点:通过在X 12分,一个字符串偏移显然会稍微超过30分长,在10点字体(-5至5在Y)。 这是平凡弄清楚如何从那里得到一组新轴界。

但是,如果我们再现在我们已经绘制它调用该方法,我们得到了一个完全不同的BBOX:

bbox = label.get_window_extent(plt.gcf().canvas.get_renderer())
print(bbox.extents)

现在,我们得到

array([ 578.36666667,  216.66666667,  609.21041667,  226.66666667])

这是在显示坐标,我们可以用变换ax.transData就像我们已经习惯了。 所以,让我们的标签进入范围,我们可以这样做:

x = np.linspace(0,360,101)
y = np.sin(np.radians(x))

line, = plt.plot(x, y)
label = plt.annotate('finish', (360,0),
                     xytext=(8, 0), textcoords='offset points',
                     ha='left', va='center')

plt.draw()
bbox = label.get_window_extent()

ax = plt.gca()
bbox_data = bbox.transformed(ax.transData.inverted())
ax.update_datalim(bbox_data.corners())
ax.autoscale_view()

注意它不再需要明确地传递plt.gcf().canvas.get_renderer()get_window_extent情节已经绘一次之后。 另外,我使用update_datalim代替xlimylim直接,从而使自动缩放可以自动缺口本身长达一个整数。

我贴在笔记本格式这个答案在这里 。



Answer 2:

对我来说tight_layout通常解决了这个问题,但在某些情况下,我不得不使用“手动”调整与subplots_adjust ,就像这样:

fig = plt.figure()
fig.subplots_adjust(bottom=0.2, top=0.12, left=0.12, right=0.1)

这些数字通常不会发生巨大的变化,这样就可以解决这些问题而不是试图从实际的情节来计算。

BTW,设置XLIM,你在你的例子做只会改变你绘制的数据,而不是周围的所有标签的白色区域的范围。



Answer 3:

matplotlib1.1tight_layout的引入解决了一些布局问题。 有一个很好的教程在这里 。



文章来源: matplotlib autoscale axes to include annotations