在matplotlib中移动和调整图例框大小

25 投票
3 回答
84779 浏览
提问于 2025-04-18 03:53

我正在使用Matplotlib创建图表,然后将它们保存为SVG格式,再通过Inkscape导出为.pdf和.pdf_tex文件,最后把这个.pdf_tex文件放到LaTeX文档里。

这样一来,我就可以在标题、图例等地方使用LaTeX命令,得到像这样的图像:

plot

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

plot rendered using 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 个回答

1

更新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()) 来解决这个问题。

18

你可以使用 bbox_to_anchorbbox_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 来替代。

28

你可以在自动放置图例后,通过绘制它来移动图例,然后获取它的位置。下面是一个例子:

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()

图例在第一次绘制后被移动

撰写回答