有没有人知道扩展绘图区域以包含注释的简单方法?我有一个图形,其中一些标签是长和/或多线字符串,而不是将它们剪切到轴,我想扩展轴以包括注释。
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)
答案 0 :(得分:3)
我也在努力解决这个问题。关键点在于,matplotlib在确定文本实际绘制之前不会确定文本的大小。因此,您需要显式调用plt.draw()
,然后调整边界,然后再次绘制它。
get_window_extent
方法应该根据documentation给出显示坐标的答案,而不是数据坐标。但是如果尚未绘制画布,它似乎会在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
代替xlim
和ylim
,因此自动缩放可以自动将自身划分为一个整数。
我用笔记本格式here发布了这个答案。
答案 1 :(得分:2)
对我来说tight_layout
通常会解决问题,但在某些情况下,我必须使用subplots_adjust进行“手动”调整,如下所示:
fig = plt.figure()
fig.subplots_adjust(bottom=0.2, top=0.12, left=0.12, right=0.1)
数字通常不会发生显着变化,因此您可以修复它们,而不是尝试从实际情节中进行计算。
顺便说一句,在示例中设置xlim只会更改您绘制的数据的范围,而不会更改所有标签周围的白色区域。
答案 2 :(得分:1)
在matplotlib1.1
中引入tight_layout
来解决一些布局问题。有一个很好的教程here。