Matplotlib 图例中的字幕

Subtitles within Matplotlib legend

我正在用 matplotlib 做一些绘图,我有一个图例告诉查看器这些点是用哪个传感器记录的。有多种类型的多个传感器,我想在图例中加上字幕来告诉观众每组是什么类型的传感器。我有一个可行的解决方案,但有点乱七八糟,如下所示:

创建图例时,它接受两个重要参数:图例标记列表和图例标签列表。我目前的解决方案是将字幕标记设置为带有白色轮廓的白框,并让字幕标签被两个换行符包围。看起来不错,但如果字幕不缩进,它看起来会更专业。我尝试过的两种变通方法是将字幕的标记设置为 None,并将字幕的标记设置为所需的字幕字符串并将其标签设置为空字符串。都没有工作。有人对这个有经验么?非常感谢。

我能想到的最好办法是为字符串创建自定义处理程序。

import matplotlib.pyplot as plt
import matplotlib.text as mtext


class LegendTitle(object):
    def __init__(self, text_props=None):
        self.text_props = text_props or {}
        super(LegendTitle, self).__init__()

    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        title = mtext.Text(x0, y0, r'\underline{' + orig_handle + '}', usetex=True, **self.text_props)
        handlebox.add_artist(title)
        return title


[line1] = plt.plot(range(10))
[line2] = plt.plot(range(10, 0, -1), 'o', color='red')
plt.legend(['Title 1', line1, 'Title 2', line2], ['', 'Line 1', '', 'Line 2'],
           handler_map={basestring: LegendTitle({'fontsize': 18})})

plt.show()

我基于 http://matplotlib.org/users/legend_guide.html 中的示例。

这是 Python3 的简化版本,不需要 LaTeX。它基于您可以在 seaborn documentation 中找到的这个简单图,但它也应该适用于 matplotlib。

import seaborn as sns
flights = sns.load_dataset("flights")
sns.lineplot(data=flights, x="year", y="passengers", hue="month")

所以要添加字幕,您可以使用此代码。

# Seaborn example
import seaborn as sns
flights = sns.load_dataset("flights")
g = sns.lineplot(data=flights, x="year", y="passengers", hue="month")

# Here is where the magic happens
h,l = g.get_legend_handles_labels()

import matplotlib.pyplot as plt
import matplotlib.text as mtext


class LegendTitle(object):
    def __init__(self, text_props=None):
        self.text_props = text_props or {}
        super(LegendTitle, self).__init__()

    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        title = mtext.Text(x0, y0, orig_handle,  **self.text_props)
        handlebox.add_artist(title)
        return title


# ['','2nd Title'], and ['',''] is a hackish to leave some 
# space between the titles
g.legend(['1st Title'] + h[:6] + ['','2nd Title'] + h[6:12], 
          ['']         + l[:6] + ['','']          + l[6:12],
           handler_map={str: LegendTitle({'fontsize': 16})},
          bbox_to_anchor=(1, 1)
        )