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”。有人能帮我吗?