【问题标题】:How to produce nested legends in Matplotlib如何在 Matplotlib 中生成嵌套图例
【发布时间】:2020-08-03 19:26:26
【问题描述】:

我必须在 Matplotlib 中绘制一个数量,该数量是各种贡献的 sum

我想通过将各种贡献列为主要图例条目的子元素来在情节图例中突出这一事实。

我想获得的结果草图可以在下面的图片中找到。请注意,我不一定要完全实现所描绘的图例,而只是类似的东西。

【问题讨论】:

    标签: python matplotlib legend


    【解决方案1】:

    您可以尝试为您的人物创建两个单独的图例。当然,这是一个技巧,而不是图例对象的直接功能,因为在 matplotlib 中似乎没有实现您需要的功能。但是使用 bbox 中的数字和字体大小,您可以很好地自定义它。

    import matplotlib.pyplot as plt 
    import numpy as np
    
    x = np.arange(0.0, 1, 0.01)
    x1 = np.sin(2*np.pi*x)
    x2 = np.sin(2*np.pi*x+1)
    x3 = np.sin(2*np.pi*x+2)
    
    
    fig, ax = plt.subplots()
    f1, = ax.plot(x1, 'r', lw=4)
    f2, = ax.plot(x2, 'k', lw=2)
    f3, = ax.plot(x3, 'b', lw=2)
    
    legend1 = plt.legend([f1], ["Main legend"], fontsize=12, loc=3, bbox_to_anchor=(0,0.1,0,0), frameon=False)
    legend2 = plt.legend((f2, f3), ('sublegend 1', 'sublegend 2'), fontsize=9,
                     loc=3, bbox_to_anchor=(0.05,0,0,0), frameon=False)
    plt.gca().add_artist(legend1)
    plt.show()
    

    编辑:

    好吧,如果我们插入 2 个图例,为什么不在更大的图中插入一个全新的图作为插图,专用于图例,在其中您可以绘制和写任何您喜欢的东西?诚然,这是一项艰巨的工作,您必须设计内部的每条线,包括精确的位置坐标。但这是我能想到的做你想做的事的方式:

    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.arange(0.0, 1, 0.01)
    x1 = np.sin(2*np.pi*x)
    x2 = np.sin(2*np.pi*x+1)
    x3 = np.sin(2*np.pi*x+2)
    
    
    fig, ax = plt.subplots()
    f1, = ax.plot(x1, 'r', lw=4)
    f2, = ax.plot(x2, 'k', lw=2)
    f3, = ax.plot(x3, 'b', lw=2)
    
    ## set all lines for inner figure
    yline1 = np.array([-0.15, -0.15]) 
    line1 = np.array([2, 10])
    yline2 = np.array([3, 0])
    line2 = np.array([4, 4])
    yline3 = np.array([1.5, 1.5])
    line3 = np.array([4, 6])
    yline4 = np.array([1.5, 1.5])
    line4 = np.array([7, 10])
    yline5 = np.array([3, 3])
    line5 = np.array([4, 6])
    yline6 = np.array([3, 3])
    line6 = np.array([7, 10])
    
    ## inset figure
    axin1 = ax.inset_axes([2.5, -1, 30, 0.5], transform=ax.transData)  # 
    
    ## plot all lines
    axin1.plot(line1, yline1, linewidth=4, c='r')
    axin1.plot(line2, yline2, 'k', lw=1)
    axin1.plot(line3, yline3, 'k', lw=1)
    axin1.plot(line4, yline4, 'b', lw=3)
    axin1.plot(line5, yline5, 'k', lw=1)
    axin1.plot(line6, yline6, 'k', lw=3)
    
    ## text
    axin1.text(12, 0, 'MAIN', fontsize=12)
    axin1.text(12, 1.7, 'Subtext 1', fontsize=10)
    axin1.text(12, 3.2, 'Subtext 2', fontsize=10)
    
    ## adjust
    axin1.set_ylim([4, -1])
    axin1.set_xlim([0, 27])
    axin1.set_xticklabels('')
    axin1.set_yticklabels('')
    

    【讨论】:

      【解决方案2】:

      我在图例中查找了一个自定义示例,但没有看到任何降低级别的迹象。您只需排列图例中的对象即可。我以颜色和标记的形式创建了呈现图像的层次结构。官方reference已定制。这具有消除以特殊方式仅注释图例的需要的效果。

      import matplotlib.pyplot as plt
      from matplotlib.legend_handler import HandlerLineCollection, HandlerTuple
      
      fig, ax1 = plt.subplots(1, 1, constrained_layout=True)
      
      params = {'legend.fontsize': 16,
                'legend.handlelength': 3}
      
      plt.rcParams.update(params)
      
      x = np.linspace(0, np.pi, 25)
      xx = np.linspace(0, 2*np.pi, 25)
      xxx = np.linspace(0, 3*np.pi, 25)
      
      p1, = ax1.plot(x, np.sin(x), lw=5, c='r')
      p2, = ax1.plot(x, np.sin(xx), 'm-d', c='g')
      p3, = ax1.plot(x, np.sin(xxx), 'm-s', c='b')
      
      # Assign two of the handles to the same legend entry by putting them in a tuple
      # and using a generic handler map (which would be used for any additional
      # tuples of handles like (p1, p2)).
      l = ax1.legend([p1, (p1, p2), (p1, p3)], ['Legend entry', 'Contribution 1', 'Contribution 2'], scatterpoints=1,
                     numpoints=1, markerscale=1.3, handler_map={tuple: HandlerTuple(ndivide=None, pad=1.0)})
      
      plt.show()
      

      【讨论】:

      • 谢谢你的回答,但这并不是我想要的效果
      • 有什么区别?请为问题添加额外的解释,以便其他人回答。
      • 您提供的答案并没有使图例足够清楚(我知道您建议的技巧)。我问是否可以根据主条目的形式设置元素条目,就像嵌套的项目符号列表一样。
      • 我认为这是您将得到的最佳答案。不支持您要查找的内容。或者您可以尝试实现从 matplotlib 继承的自定义 Legend 类
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 2021-12-29
      相关资源
      最近更新 更多