Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 图例中的两种线条样式_Python_Matplotlib_Plot_Legend - Fatal编程技术网

Python 图例中的两种线条样式

Python 图例中的两种线条样式,python,matplotlib,plot,legend,Python,Matplotlib,Plot,Legend,我有一个带有两种线条样式(实线和虚线)的绘图。我希望它们用于相同的图例条目。下面的代码生成典型图例,带有两个条目 import matplotlib.pyplot as plt import numpy as np xy = np.linspace(0,10,10) plt.figure() plt.plot(xy,xy, c='k', label='solid') plt.plot(xy,xy+1, c='k', ls='dashed', label='dashed') plt.plot(

我有一个带有两种线条样式(实线和虚线)的绘图。我希望它们用于相同的图例条目。下面的代码生成典型图例,带有两个条目

import matplotlib.pyplot as plt
import numpy as np

xy = np.linspace(0,10,10)

plt.figure()
plt.plot(xy,xy, c='k', label='solid')
plt.plot(xy,xy+1, c='k', ls='dashed', label='dashed')
plt.plot(xy,xy-1, c='k', ls='dashed')
plt.legend()

plt.show()
我想要的是类似的东西:


我尝试过使用代理艺术家,但似乎无法获得两行,彼此偏移以显示一个条目。

我基于HandlerLineCollection类制作了一个自定义图例处理程序。它计算出集合中有多少行,并将它们垂直展开

示例图像:

下面是处理程序:

from matplotlib.legend_handler import HandlerLineCollection
from matplotlib.collections import LineCollection
from matplotlib.lines import Line2D


class HandlerDashedLines(HandlerLineCollection):
"""
Custom Handler for LineCollection instances.
"""
def create_artists(self, legend, orig_handle,
                   xdescent, ydescent, width, height, fontsize, trans):
    # figure out how many lines there are
    numlines = len(orig_handle.get_segments())
    xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent,
                                         width, height, fontsize)
    leglines = []
    # divide the vertical space where the lines will go
    # into equal parts based on the number of lines
    ydata = ((height) / (numlines + 1)) * np.ones(xdata.shape, float)
    # for each line, create the line at the proper location
    # and set the dash pattern
    for i in range(numlines):
        legline = Line2D(xdata, ydata * (numlines - i) - ydescent)
        self.update_prop(legline, orig_handle, legend)
        # set color, dash pattern, and linewidth to that
        # of the lines in linecollection
        try:
            color = orig_handle.get_colors()[i]
        except IndexError:
            color = orig_handle.get_colors()[0]
        try:
            dashes = orig_handle.get_dashes()[i]
        except IndexError:
            dashes = orig_handle.get_dashes()[0]
        try:
            lw = orig_handle.get_linewidths()[i]
        except IndexError:
            lw = orig_handle.get_linewidths()[0]
        if dashes[0] != None:
            legline.set_dashes(dashes[1])
        legline.set_color(color)
        legline.set_transform(trans)
        legline.set_linewidth(lw)
        leglines.append(legline)
    return leglines
下面是一个如何使用它的示例:

#make proxy artists
#make list of one line -- doesn't matter what the coordinates are
line = [[(0, 0)]]
#set up the line collections
lc = LineCollection(2 * line, linestyles = ['solid', 'dashed'], colors = ['black', 'black'])
lc2 = LineCollection(2 * line, linestyles = ['solid', 'dashed'], colors = ['blue', 'blue'])
lc3 = LineCollection(3 * line, linestyles = ['solid', 'dashed', 'solid'], colors = ['blue', 'red', 'green'])
#create the legend
plt.legend([lc, lc2, lc3], ['text', 'more text', 'extra line'], handler_map = {type(lc) : HandlerDashedLines()}, handlelength = 2.5)

基于@Amys answer,我构建了另一个实现,它扩展了HandlerTuple以垂直堆叠,因此您不需要添加代理

导入matplotlib.pyplot作为plt
从matplotlib.legend\u处理程序导入HandlerTuple
类HandlerTupleVertical(HandlerTuple):
定义初始(自我,**kwargs):
HandlerTuple.\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def创建艺术家(自我、传奇、原始手柄、,
xdescent、ydescent、宽度、高度、字体大小、trans):
#有多少行。
numlines=len(原始手柄)
handler\u map=legend.get\u legend\u handler\u map()
#在直线将要经过的垂直空间中进行分割
#根据行数分成相等的部分
高度_y=(高度/数字线)
腿线=[]
对于i,枚举中的句柄(原始句柄):
handler=legend.get\u legend\u handler(handler\u映射,handle)
legline=handler。创建艺术家(图例、把手、,
xdescent,
(2*i+1)*高度,
宽度,
2*高度,
字体大小(trans)
腿线。延伸(腿线)
回程线
然后它可以被使用,使用

line1=plt.plot(xy,xy,c='k',label='solid')
line2=plt.绘图(xy,xy+1,c='k',ls='虚线',标签='虚线〕
第3行=plt.绘图(xy,xy-1,c='k',ls='虚线',标签='虚线〕
plt.图例([(第1行,第2行),第3行],“文本”,“更多文本”,“甚至更多”],
handler_map={tuple:HandlerTupleVertical()})

See也可能是helpful@tcaswell谢谢你的建议。我用这些来回答我以前的另一个问题:。我就是找不到任何东西来处理抵消线。哇,谢谢艾米。我希望你写这篇文章不是为了我;好像要做很多工作。它确实工作得很好,正是我所需要的。哦,不用担心。如果我不觉得这很有趣的话,我就不会这么做,我主要是复制和修改了一个现有的图例处理程序@当然,我很乐意将其添加到示例中。我将看一看开发者指南,看看我是否能想出如何做到这一点。:)@眨眼,我更新了一点代码。我没有正确地计算线的高度,如果手柄高度改变,事情可能会看起来不对劲。我修复了这个问题。我无法运行此代码,因为我遇到了几个错误。有人能说出python版本是什么吗?行
类HandlerDashedLines(HandlerLineCollection)之后的所有内容:
缺少缩进simple,可以正常工作。谢谢(请注意,循环的
缩进缺少一个空格)感谢您的修复。:)当我单独绘制每条线时,是否可以这样做?所有这些答案似乎都依赖于紧凑地绘制线条。在我的应用程序中,
plot
处于for循环中…您可以将for循环中生成的行存储在数组中。我总是收到一个错误:发生异常:AttributeError'NoneType'对象没有行“legline=handler.create_artist…”的属性“create_artists”。有人能帮我吗?