Matplotlib:是否有 rcParams 方法来调整图例边框宽度?

Matplotlib: is there an rcParams way to adjust legend border width?

This site shows many (all?) rc parameters that can be adjusted in Matplotlib plots, either through the matplotlibrc file or using matplotlib.rcParams[] in a Python script. I can see no way to adjust the width of the border box of a legend using the parameters listed in that site. I know it is possible to change the line width of the box "manually", i.e., in the script (for example),但我希望有一种方法可以使用 matplotlib.rcParams[] 或在 matplotlibrc 文件中进行设置。我该怎么做?

我想要一个自动化的、外部的(或者至少可以轻松复制和粘贴)的原因是因为我有几个数字,用几个不同的 Python 脚本生成这些数字,我会喜欢尽可能简单的方法来在不同的 Python 脚本中保持每个数字之间的标准外观。

在某些脚本中,我将图例称为 pyplot.legend(),而在其他脚本中,我将其称为 ax.legend()

根据您要执行的操作,实际上可以通过 rcParams.

设置图例边框的宽度

TL;DR

matplotlibrc 中设置 patch.linewidth 或更好,为 legend 编写一个两行包装函数,然后在您的脚本中使用它。

长版

查看 legend 的代码,您可以看到框架存储为 matplotlib.patched.FancyBBoxPatch 对象,属于 matplotlib.patches.Patch 类型。 Patch 个对象从 matplotlib.rcParams['patch.linewidth'] 中获取它们的默认线宽。这意味着如果您在 matplotlibrc 中设置 patch.linewidth,图例边框的大小将会改变。

patch.edgecolor 类似的修改将更改边框颜色,但 patch.facecolor 将被忽略以用于图例。

这里有一个代码示例来说明更改,其中包含一些输出:

>>> import matplotlib as mpl
>>> from matplotlib import pyplot as plt
>>> mpl.rcParams['patch.linewidth']
1.0
>>> plt.plot((0, 1), label='a')[0].axes.legend()
<matplotlib.legend.Legend object at 0x7f6d7b0a0e48>
>>> mpl.rcParams['patch.linewidth'] = 15
>>> plt.plot((0, 1), label='a')[0].axes.legend()
<matplotlib.legend.Legend object at 0x7f6d7ae20908>

这里明显的问题是,如果您在图表上绘制任何其他补丁,默认线宽将被丢弃。您当然可以通过 "manually" 将您创建的所有补丁的线宽改回 1 来缓解这种情况。显然这不是最佳解决方案。

更好的方法

更好的解决方案是创建一个小脚本,您可以在所有图表生成脚本之间共享该脚本。这是此类脚本的示例:

from matplotlib.axes import Axes

def add_legend(ax, *args, **kwargs):
    """
    Adds a legend to the specified axes, along with some common formatting. All additional arguments are the same as for `ax.legend`.
    """
    legend = _originalFn(ax, *args, **kwargs)
    legend.set_linewidth(15)
    return legend

if Axes.legend is not add_legend:
    _originalFn = Axes.legend
    Axes.legend = add_legend

此脚本的结构使您永远不需要手动调用 add_legend。只需导入脚本子类 matplotlib.axes.Axes 以便像以前一样调用 ax.legend(...) 会将默认的图例边框宽度设置为 15 磅。

上面的脚本适用于调用 ax.legend,其中 ax 是一个 Axes 实例,在 plt.legend 上,因为 plt.legend 实际上只是委托给gca().legend 有一些额外的处理。

即使您的程序由多个导入共享脚本的 scripts/modules 组成,这种子类化机制也将起作用。这是因为 Python 不会在第一次后实际重新加载模块,而只是 return 对它的引用,所有属性都完好无损。如果您开始使用 importlib.reload,事情就会崩溃,但这种可能性很小。