You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Matplotlib多子图图形中自动将图例(legend)适配到坐标轴(ax)内部?

让Matplotlib多子图的图例自动适配坐标轴尺寸

我明白你的需求——不想手动设置字体大小或图例尺寸,希望每个子图的图例能自动适配所在坐标轴的空间,不会超出边界。这里有个可行的方案,通过动态计算坐标轴和图例的尺寸来自动调整,代码实现起来也很直观:

核心思路

  1. 临时创建一个图例,获取它的初始尺寸(只有绘制画布后才能拿到准确的尺寸数据)
  2. 对比坐标轴的可用空间,计算出合适的缩放比例
  3. 根据缩放比例调整图例的字体大小,再创建最终的图例并放置在坐标轴内部

完整实现代码

import matplotlib.pyplot as plt
import numpy as np

def auto_adjust_legend(ax, legend_label):
    # 获取坐标轴的英寸尺寸(转换后适配当前DPI)
    ax_extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
    ax_width, ax_height = ax_extent.width, ax_extent.height
    
    # 创建临时图例来获取初始尺寸
    temp_legend = ax.legend([legend_label], [legend_label])
    fig.canvas.draw()
    legend_extent = temp_legend.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
    temp_legend.remove()  # 删掉临时图例,避免干扰
    
    # 计算缩放比例:让图例最多占坐标轴80%的空间,避免过于拥挤
    scale_factor = min(ax_width / legend_extent.width * 0.8, ax_height / legend_extent.height * 0.8)
    # 基于Matplotlib默认字体大小调整新的字体尺寸
    adjusted_font_size = plt.rcParams['legend.fontsize'] * scale_factor
    
    # 创建适配后的图例,放在右上角靠近边缘的位置,减少留白
    ax.legend(
        fontsize=adjusted_font_size,
        loc='upper right',
        bbox_to_anchor=(0.97, 0.97),
        borderaxespad=0  # 消除图例和坐标轴之间的默认 padding
    )

# 示例数据
x = np.linspace(0, 2 * np.pi, 400)
a = x ** 2
b = x ** 3
c = x ** 4
functions = [a, b, c]
long_label = "This is a long label for a legend and I try to fit to its ax"

# 创建2x2子图,用constrained_layout代替tight_layout,自动处理子图间距
fig, axs = plt.subplots(2, 2, constrained_layout=True)

# 绘制曲线
for y in functions:
    axs[0, 0].plot(x, y, label=long_label)
    axs[0, 1].plot(x, -y, label=long_label)
    axs[1, 0].plot(x, y, label=long_label)
    axs[1, 1].plot(x, -y, label=long_label)

# 配置每个子图并应用自动适配的图例
for ax in axs.flat:
    ax.set_title('Title')
    ax.set(xlabel='x-label', ylabel='y-label')
    auto_adjust_legend(ax, long_label)

plt.show()

额外说明

  • constrained_layout=True代替tight_layout(),能更智能地处理标题、坐标轴标签和子图之间的间距,避免重叠问题
  • 如果你觉得图例和坐标轴边缘太近,可以微调bbox_to_anchor的数值(比如改成(0.95, 0.95))或者给borderaxespad设置一个小值(比如0.1
  • 这个方法会根据每个子图的实际尺寸动态调整,不管子图布局怎么变,图例都能适配所在坐标轴的空间

内容的提问来源于stack exchange,提问作者allabur

火山引擎 最新活动