在图例中垂直堆叠线

时间:2020-08-06 11:55:04

标签: matplotlib

enter image description here

在matplotlib图例中寻找垂直堆栈线的解决方案时,我遇到了此堆栈帖子Two line styles in legend,但是我无法使代码正常工作,我总是在“ legline = handler”行中遇到错误.createartists(...):

“发生异常:AttributeError'NoneType'对象没有 属性“创建艺术家””

在这里,我从那个stackoverflow问题中复制代码(@gyger):

import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerTuple

class HandlerTupleVertical(HandlerTuple):
    def __init__(self, **kwargs):
        HandlerTuple.__init__(self, **kwargs)

    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        # How many lines are there.
        numlines = len(orig_handle)
        handler_map = legend.get_legend_handler_map()

        # divide the vertical space where the lines will go
        # into equal parts based on the number of lines
        height_y = (height / numlines)

        leglines = []
        for i, handle in enumerate(orig_handle):
            handler = legend.get_legend_handler(handler_map, handle)

            legline = handler.create_artists(legend, handle,
                                             xdescent,
                                             (2*i + 1)*height_y,
                                             width,
                                             2*height,
                                             fontsize, trans)
            leglines.extend(legline)

        return leglines

要使用此代码:

line1 = plt.plot(xy,xy, c='k', label='solid')
line2 = plt.plot(xy,xy+1, c='k', ls='dashed', label='dashed')
line3 = plt.plot(xy,xy-1, c='k', ls='dashed', label='dashed')

plt.legend([(line1, line2), line3], ['text', 'more text', 'even more'],
           handler_map = {tuple : HandlerTupleVertical()})

2 个答案:

答案 0 :(得分:1)

看来handle循环中的for是一个内有句柄的Legnth-1列表,这使get_legend_handler函数感到困惑,因为它期待的是句柄,而不是列表。

如果相反,您只是从该列表内部将处理程序发送到legend.get_legend_handler()handler.create_artists(),那么它似乎可以正常工作。

也许最简单的方法是在调用handle = handle[0]函数之前添加一行代码get_legend_handler

for i, handle in enumerate(orig_handle):

    handle = handle[0]
    handler = legend.get_legend_handler(handler_map, handle)

    legline = handler.create_artists(legend, handle,
                                     xdescent,
                                     (2*i + 1)*height_y,
                                     width,
                                     2*height,
                                     fontsize, trans)
    leglines.extend(legline)

enter image description here

答案 1 :(得分:0)

正如@tmdavison所指出的那样,问题在于get_legend_handler函数需要一个句柄,而不是一个列表。我可能发现的原始代码来自matplotlib版本,该行为有所不同。 我通过使线成为句柄(通过添加逗号)解决了这个问题:

line1, = plt.plot(xy,xy, c='k', label='solid')
line2, = plt.plot(xy,xy+1, c='k', ls='dashed', label='dashed')
line3, = plt.plot(xy,xy-1, c='k', ls='dashed', label='dashed')

plt.legend([(line1, line2), line3], ['text', 'more text', 'even more'],
           handler_map = {tuple : HandlerTupleVertical()})