在matplotlib中移动和调整图例框大小
我正在使用Matplotlib创建图表,然后将它们保存为SVG格式,再通过Inkscape导出为.pdf和.pdf_tex文件,最后把这个.pdf_tex文件放到LaTeX文档里。
这样一来,我就可以在标题、图例等地方使用LaTeX命令,得到像这样的图像:

当我在LaTeX文档中使用它时,效果是这样的。注意,坐标轴上的数字字体发生了变化,图例中的LaTeX代码也被正确显示了:

这是生成图表的代码(如何导出为SVG的部分这里没有展示,但可以根据需要提供):
import numpy as np
x = np.linspace(0,1,100)
y = x**2
import matplotlib.pyplot as plt
plt.plot(x, y, label = '{\\footnotesize \$y = x^2\$}')
plt.legend(loc = 'best')
plt.show()
问题是,正如你所看到的,图例周围的框的对齐和大小不太对。这是因为在通过Inkscape和pdflatex处理后,标签的文本大小发生了变化(比如\footnotesize
等消失了,字体大小也变了)。
我发现可以通过以下方式选择标签的位置:
plt.label(loc = 'upper right')
或者如果我想要更多控制的话,可以使用:
plt.label(bbox_to_anchor = [0.5, 0.2])
但我还没有找到缩小标签周围框的方法。这可能吗?
缩小框的一个替代方法是使用类似于:
legend = plt.legend()
legend.get_frame().set_edgecolor('1.0')
来去掉框的轮廓,然后把标签移动到我想要的位置。在这种情况下,我希望能够先让python/matplotlib使用:
plt.label(loc = 'upper right')
来放置标签,然后再比如向右移动一点。这样可以吗?我尝试过使用get_bbox_to_anchor()
和set_bbox_to_anchor()
,但似乎没有成功。
3 个回答
更新Molly的回答,使其与Matplotlib 3.3及以上版本兼容。之前的回答是通过以下方式移动图例:
import matplotlib.pyplot as plt import numpy as np # Plot data x = np.linspace(0,1,100) y = x**2 fig = plt.figure() ax = fig.add_subplot(221) #small subplot to show how the legend has moved. # Create legend plt.plot(x, y, label = '{\\footnotesize \$y = x^2\$}') leg = plt.legend( loc = 'upper right') plt.draw() # Draw the figure so you can find the positon of the legend. # Get the bounding box of the original legend bb = leg.get_bbox_to_anchor().inverse_transformed(ax.transAxes) # Change to location of the legend. xOffset = 1.5 bb.x0 += xOffset bb.x1 += xOffset leg.set_bbox_to_anchor(bb, transform = ax.transAxes) # Update the plot plt.show()
但是在Matplotlib 3.3及以上版本中,这个方法不再有效。你可以通过将 bb = leg.get_bbox_to_anchor().inverse_transformed(ax.transAxes)
改为 bb = leg.get_bbox_to_anchor().transformed(ax.transAxes.inverted())
来解决这个问题。
你可以使用 bbox_to_anchor
和 bbox_transform
这两个参数来帮助你设置图例的位置:
ax = plt.gca()
plt.legend(bbox_to_anchor=(1.1, 1.1), bbox_transform=ax.transAxes)
注意,在这个例子中,(1.1, 1.1)
是在坐标轴的坐标系中。如果你想使用数据的坐标系,你需要用 bbox_transform=ax.transData
来替代。
你可以在自动放置图例后,通过绘制它来移动图例,然后获取它的位置。下面是一个例子:
import matplotlib.pyplot as plt
import numpy as np
# Plot data
x = np.linspace(0,1,100)
y = x**2
fig = plt.figure()
ax = fig.add_subplot(221) #small subplot to show how the legend has moved.
# Create legend
plt.plot(x, y, label = '{\\footnotesize \$y = x^2\$}')
leg = plt.legend( loc = 'upper right')
plt.draw() # Draw the figure so you can find the positon of the legend.
# Get the bounding box of the original legend
bb = leg.get_bbox_to_anchor().inverse_transformed(ax.transAxes)
# Change to location of the legend.
xOffset = 1.5
bb.x0 += xOffset
bb.x1 += xOffset
leg.set_bbox_to_anchor(bb, transform = ax.transAxes)
# Update the plot
plt.show()