单个图例项目有两行

时间:2017-01-19 21:47:25

标签: python matplotlib

我想生成一个自定义matplotlib图例,对于每个条目,每个条目都有两行,如下例所示:

enter image description here

从某些研究中,似乎可以简单地提供两个handles' to the fig.legend(句柄,标签)`方法,(参见this post作为例子)。但是,如以下示例代码所示,这只是将行重叠在彼此之上。

import matplotlib.lines as mlines
import matplotlib.pyplot as plt

blue_line = mlines.Line2D([], [], color='r')
green_line = mlines.Line2D([], [], linestyle='--', color='k')
fig, ax = plt.subplots(figsize=(5, 5))
handles = [(blue_line,green_line)]
labels = ['test'] 
fig.legend(handles=handles, labels=labels, fontsize=20)  

所以,我想我要么转换其中一个Line2D对象,要么生成一个包含两行的新Patch对象。但是,我无法弄清楚如何做到这一点 - 是否有一种简单的方法来组合两个补丁,或者我错过了组合句柄的技巧?

上下文

如果这有助于其他人,那么上下文就是我正在使用所讨论的技术here,这是一个双轴,它被着色以同时显示两个不同的图。但是,这两行具有相同的标签,因此我想将它们组合在一起。

2 个答案:

答案 0 :(得分:3)

在matplotlib图例指南中有一章关于custom legend handlers。您可以根据自己的需要进行调整,例如:像这样:

Handler

enter image description here

为了有多个这样的条目,可以提供一些参数元组,然后import matplotlib.pyplot as plt import numpy as np from matplotlib.legend_handler import HandlerBase class AnyObjectHandler(HandlerBase): def create_artists(self, legend, orig_handle, x0, y0, width, height, fontsize, trans): l1 = plt.Line2D([x0,y0+width], [0.7*height,0.7*height], linestyle=orig_handle[1], color='k') l2 = plt.Line2D([x0,y0+width], [0.3*height,0.3*height], color=orig_handle[0]) return [l1, l2] x = np.linspace(0, 3) fig, axL = plt.subplots(figsize=(4,3)) axR = axL.twinx() axL.plot(x, np.sin(x), color='k', linestyle='--') axR.plot(x, 100*np.cos(x), color='r') axL.plot(x, .3*np.sin(x), color='k', linestyle=':') axR.plot(x, 20*np.cos(x), color='limegreen') axL.set_ylabel('sin(x)', color='k') axR.set_ylabel('100 cos(x)', color='r') axR.tick_params('y', colors='r') plt.legend([("r","--"), ("limegreen",":")], ['label', "label2"], handler_map={tuple: AnyObjectHandler()}) plt.show() 用来绘制图例。

{{1}}

enter image description here

答案 1 :(得分:1)

这是我玩完之后来的一个不充分的解决方案。我发布它,以防它帮助其他人,但更愿意做得恰到好处。它使用两列,第一列的标签为'/'或者一个可以同样使用“和”。

import matplotlib.pyplot as plt

x = np.linspace(0, 3)
fig, axL = plt.subplots()
axR = axL.twinx()

axL.plot(x, np.sin(x), color='k', label='/')
axR.plot(x, 100*np.cos(x), color='r', label='label')

axL.set_ylabel('sin(x)', color='k')
axR.set_ylabel('100 cos(x)', color='r')
axR.tick_params('y', colors='r')

handlesL, labelsL = axL.get_legend_handles_labels()
handlesR, labelsR = axR.get_legend_handles_labels()
handles = handlesL + handlesR
labels = labelsL + labelsR
axR.legend(handles, labels, loc='lower center', ncol=2, fontsize=16,
           handletextpad=0.4, columnspacing=0.4)

enter image description here