Python 3.x 使用绘图数据的微型版本作为python中的图例句柄

Python 3.x 使用绘图数据的微型版本作为python中的图例句柄,python-3.x,matplotlib,legend,Python 3.x,Matplotlib,Legend,有没有办法将matplotlib中图形中绘制的线用作图例中的控制柄?例如,我想在这个基本代码中,而不是图例中的一条直线中,有一个小版本的正弦波作为句柄 import matplotlib.pyplot as plt import numpy as np x = np.arange(0,15,0.1) y = [np.sin(x1) for x1 in x] plt.plot(x,y, label = 'sine wave') plt.legend() plt.show() 提前谢谢 我觉得

有没有办法将matplotlib中图形中绘制的线用作图例中的控制柄?例如,我想在这个基本代码中,而不是图例中的一条直线中,有一个小版本的正弦波作为句柄

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0,15,0.1)
y = [np.sin(x1) for x1 in x]

plt.plot(x,y, label = 'sine wave')
plt.legend()
plt.show()

提前谢谢

我觉得这是一个很有趣的问题。解决问题所需的大部分信息都已提供。但是,我肯定认为文档有点稀疏

解决问题的关键是创建一个新的“处理程序”,在尝试绘制艺术家的图例时将调用该处理程序,并返回一个艺术家,该艺术家可以具有任何属性或形状。在本例中,我们只需使用正确的数据创建一个新的Line2D对象来绘制正弦波

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


class HandlerSinWave(HandlerLine2D):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize,
                       trans):
        xdata, y1 = orig_handle.get_data()

        # scale the sin wave amplitude so that it fits neatly in the legend box
        # first, rescale so that it is centered around 0 and have an amplitude of 1
        min_val = np.min(y1)
        max_val = np.max(y1)
        y2 = (y1-(min_val+(max_val-min_val)/2))/((max_val-min_val)/2)
        # then rescale based on the dimension of the box
        y3 = height*y2 + xdescent+height/2
        legline = matplotlib.lines.Line2D(xdata, y3)

        self.update_prop(legline, orig_handle, legend)
        legline.set_transform(trans)
        return [legline]


fig, ax = plt.subplots()
x = np.arange(0,15,0.1)
y = np.sin(x)

sin1, = plt.plot(x,y, label='sine wave')

plt.legend(handler_map={sin1: HandlerSinWave()})

对于这个简单的例子,@DizietAsahi的答案给出了正确的结果,但是对于其他x值,结果会失败。因此,人们可以更普遍地使用经过转换的bbox,从而不必关心数据的实际值

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLine2D
import matplotlib.path as mpath
from matplotlib.transforms import BboxTransformFrom, BboxTransformTo, Bbox


class HandlerMiniatureLine(HandlerLine2D):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize,
                       trans):

        legline, _ = HandlerLine2D.create_artists(self,legend, orig_handle,
                                xdescent, ydescent, width, height, fontsize, trans)

        legline.set_data(*orig_handle.get_data())

        ext = mpath.get_paths_extents([orig_handle.get_path()])
        if ext.width == 0:
            ext.x0 -= 0.1
            ext.x1 += 0.1
        bbox0 = BboxTransformFrom(ext)
        bbox1 = BboxTransformTo(Bbox.from_bounds(xdescent, ydescent, width, height))

        legline.set_transform(bbox0 + bbox1 + trans)
        return legline,


fig, ax = plt.subplots()
x = np.arange(0,15,0.1)
y = np.sin(x)

plt.plot(x-900,y+1500, label='sine wave')

plt.legend(handler_map={plt.Line2D: HandlerMiniatureLine()})

plt.show()

一般来说,你需要证明你已经研究过这个主题,并且在提问时自己尝试了一些事情。另请参见,仅供参考:
np.sin()
可以非常高效地处理数组。您可以简单地执行
y=np.sin(x)
操作,而不是使用列表理解来获取
y
数组。不幸的是,对于其他x值,这将失败(例如,尝试
plt.plot(x+1000,y)
)。我在下面给出了一个答案,这避免了手动规范化的问题。做得很好,感谢您展示了正确的方法,关于转换,我还有很多需要学习的地方