在matplotlib中对齐图例行

2 投票
1 回答
1816 浏览
提问于 2025-04-19 10:12

我正在用matplotlib绘制图表,并为它创建一个图例(见下面的代码)。我希望图例的行能够水平对齐,这样“>”和“<”就能对齐。尝试参考这个这个关于类似问题的代码时,我遇到了困难。

我明白基本的思路:使用\makebox[width][alignment]{对齐前的数学表达式}<对齐后的数学表达式作为标签,这样那个epsilon表达式占用的空间总是相同,并且右对齐,因此左边会有空余的空间。

但是链接中使用的\hfill方法只有在它前面有文本时才有效,或者当对齐方式是标准的(左对齐)时才有效。解决方案应该很接近,任何帮助都将不胜感激。这是图例文本应该呈现的样子:

enter image description here
import numpy
from matplotlib import pyplot as plt

plt.rc('text', usetex=True)  # needed for interpeting tex strings, but changes appearence of axis-tick labels also
fig = plt.figure(1,figsize=(12.0, 8.0))
plt.ion()

# does not align the '<', '<' and '>' in the legend
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{$\varepsilon_i$}$< -\xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{$|\varepsilon_i|$}$< \xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{$\varepsilon_i$}$ > \xi$')

# \hfill doesnt change anything
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{\hfill$\varepsilon_i$}$< -\xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{\hfill$|\varepsilon_i|$}$< \xi$')
# plt.plot(numpy.random.rand(10), label=r'\makebox[24cm][r]{\hfill$\varepsilon_i$}$ > \xi$')

# the relations are aligned, but i do not want to plot the 'bla' for this
plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{bla\hfill$\varepsilon_i$}$< -\xi$')
plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{bla\hfill$|\varepsilon_i|$}$< \xi$')
plt.plot(numpy.random.rand(10), label=r'\makebox[2cm][r]{bla\hfill$\varepsilon_i$}$ > \xi$')
plt.legend(loc='upper right')
plt.show()

相关问题:

1 个回答

2

这里有一个解决方案,可以让LaTeX完美对齐数学公式,但用户需要自己把它放到图例里面。这个方法是:

  • 在指定的位置画一个图例框,并留一个占位符
  • 手动把amsmath的array放进去

下面是代码:

#!/usr/bin/python3

from numpy import arange

import matplotlib
from matplotlib import pyplot as plt
custom_preamble = {
    "text.usetex": True,
    "text.latex.preamble": [
        r"\usepackage{amsmath}", # for the array macros
        ],
    }
matplotlib.rcParams.update(custom_preamble)

x = arange(5)
y = arange(5)

fig = plt.figure()
ax = fig.add_subplot(111)

l1, = ax.plot(x, y)
l2, = ax.plot(x * 2, y)
l3, = ax.plot(x * 3, y)

leg = ax.legend(
    [l1, l2, l3],
    ["", "", ""],
    bbox_to_anchor = (0.98, 0.25),
    handletextpad = 4,  # space between lines and text -- used here as a placeholder
    labelspacing = 0.1, # space between lines in a legend
    )
leg.set_zorder(1)

ax.text(0.955, 0.21,

    r"\begin{array}{rcl}"
    r"     \varepsilon_i & < & -\xi"
    r"\\ |\varepsilon_i| & < & \xi"
    r"\\   \varepsilon_i & > & \xi"
    r"\end{array}",

    transform = ax.transAxes,
    horizontalalignment = 'right',
    verticalalignment = 'top',
    zorder = 5,
        )

fig.savefig("mwe.png")

结果:

在这里输入图片描述

你可能需要编译两次:第一次编译可能会报错,但之后的编译就会正常。

关于图例中<符号之间的空格,可以通过以下方式减少:

ax.text(0.94, 0.21,

    r"\begin{array}{r@{}c@{}l}"
    r"     \varepsilon_i \,\,& < &\,\, -\xi"
    r"\\ |\varepsilon_i| \,\,& < &\,\, \xi"
    r"\\   \varepsilon_i \,\,& > &\,\, \xi"
    r"\end{array}",

(其他部分保持不变)。这样得到的效果是:

在这里输入图片描述

撰写回答