【问题标题】:How to put the legend out of the plot如何将传说从情节中剔除
【发布时间】:2018-07-08 02:18:25
【问题描述】:

我有一系列 20 个图(不是子图)要在一个图中制作。我希望传说在盒子外面。同时,我不想更改轴,因为图形的大小会减小。请帮助我解决以下问题:

  1. 我想将图例框保留在绘图区域之外。 (我希望图例位于绘图区域的右侧之外)。
  2. 有没有我把图例框内文字的字号缩小,让图例框的尺寸变小。

【问题讨论】:

    标签: python matplotlib legend


    【解决方案1】:

    放置图例 (bbox_to_anchor)

    使用plt.legendloc 参数将图例定位在坐标区的边界框内。
    例如。 loc="upper right" 将图例放置在边界框的右上角,默认情况下,在坐标轴坐标(或边界框符号 (x0,y0, width, height)=(0,0,1,1))中范围从 (0,0)(1,1)

    要将图例放置在坐标区边界框之外,可以指定图例左下角坐标区坐标的元组(x0,y0)

    plt.legend(loc=(1.04,0))
    

    更通用的方法是使用 bbox_to_anchor 参数手动指定应放置图例的边界框。可以限制自己只提供 bbox 的 (x0, y0) 部分。这将创建一个零跨度框,其中的图例将按照loc 参数给出的方向展开。例如

    plt.legend(bbox_to_anchor=(1.04,1), loc="upper left")

    将图例放置在坐标区之外,使图例的左上角位于坐标区坐标中的(1.04,1) 位置。

    下面给出了更多示例,其中还显示了 modencols 等不同参数之间的相互作用。

    l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
    l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
    l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
    l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
                    mode="expand", borderaxespad=0, ncol=3)
    l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right", 
                    bbox_transform=fig.transFigure, ncol=3)
    l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")
    

    有关如何解释bbox_to_anchor 的四元组参数的详细信息,如l4,可以在this question 中找到。 mode="expand" 在 4 元组给出的边界框内水平扩展图例。有关垂直展开的图例,请参阅this question

    有时在图形坐标而不是轴坐标中指定边界框可能很有用。这在上面的示例l5 中显示,其中bbox_transform 参数用于将图例放在图的左下角。

    后处理

    将图例放置在轴之外通常会导致完全或部分位于图形画布之外的不良情况。

    这个问题的解决方法是:

    • 调整子图参数
      可以使用plt.subplots_adjust 调整子图参数,使轴在图中占用更少空间(从而为图例留出更多空间)。例如

      plt.subplots_adjust(right=0.7)
      

      在图的右侧留出 30% 的空间,可以放置图例。

    • 布局紧凑
      使用plt.tight_layout 允许自动调整子图参数,使图形中的元素紧贴图形边缘。不幸的是,图例没有被自动考虑在内,但我们可以提供一个矩形框,整个子图区域(包括标签)都可以放入其中。

      plt.tight_layout(rect=[0,0,0.75,1])
      
    • bbox_inches = "tight"保存图
      参数bbox_inches = "tight"plt.savefig 可用于保存图形,以便画布上的所有艺术家(包括图例)都适合保存的区域。如果需要,图形大小会自动调整。

      plt.savefig("output.png", bbox_inches="tight")
      
    • 自动调整子图参数
      可以在此答案中找到一种自动调整子图位置以使图例适合画布而不更改图形大小的方法:Creating figure with exact size and no padding (and legend outside the axes)

    上述案例的比较:

    替代方案

    人物传奇

    可以使用图例而不是轴,matplotlib.figure.Figure.legend。这对于 matplotlib 版本 >=2.1 尤其有用,不需要特殊参数

    fig.legend(loc=7) 
    

    为图形不同轴上的所有艺术家创建图例。图例使用loc 参数放置,类似于它放置在轴内的方式,但参考整个图 - 因此它会自动在轴外。剩下的就是调整子图,使图例和轴之间没有重叠。上面的 “调整子图​​参数” 点会有所帮助。一个例子:

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.linspace(0,2*np.pi)
    colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
    fig, axes = plt.subplots(ncols=2)
    for i in range(4):
        axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))
    
    fig.legend(loc=7)
    fig.tight_layout()
    fig.subplots_adjust(right=0.75)   
    plt.show()
    

    专用子图轴内的图例

    使用 bbox_to_anchor 的替代方法是将图例放置在其专用的子图轴 (lax) 中。 由于图例子图应该小于图,我们可以在创建轴时使用gridspec_kw={"width_ratios":[4,1]}。 我们可以隐藏坐标轴lax.axis("off"),但仍然放一个图例。图例句柄和标签需要通过h,l = ax.get_legend_handles_labels()从真实图中获得,然后可以在lax子图中提供给图例lax.legend(h,l) .下面是一个完整的例子。

    import matplotlib.pyplot as plt
    plt.rcParams["figure.figsize"] = 6,2
    
    fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
    ax.plot(x,y, label="y=sin(x)")
    ....
    
    h,l = ax.get_legend_handles_labels()
    lax.legend(h,l, borderaxespad=0)
    lax.axis("off")
    
    plt.tight_layout()
    plt.show()
    

    这会产生一个情节,在视觉上与上面的情节非常相似:

    我们也可以使用第一个轴来放置图例,但使用图例轴的bbox_transform

    ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
    lax.axis("off")
    

    这种方式不需要从外部获取图例句柄,但需要指定bbox_to_anchor参数。

    进一步阅读和笔记:

    • 考虑一下 matplotlib legend guide 以及一些您想用图例做的其他事情的例子。
    • 可以直接在回答这个问题时找到一些用于放置饼图图例的示例代码:Python - Legend overlaps with the pie chart
    • loc 参数可以采用数字而不是字符串,这使调用更短,但是它们之间的映射不是很直观。以下是供参考的映射:

    【讨论】:

      【解决方案2】:

      有很多方法可以做你想做的事。要添加 @inalis 和 @Navi 已经说过的内容,您可以使用 bbox_to_anchor 关键字参数将图例部分放置在轴之外和/或减小字体大小。

      在您考虑减小字体大小(这会使事情变得非常难以阅读)之前,请尝试将图例放置在不同的位置:

      所以,让我们从一个通用示例开始:

      import matplotlib.pyplot as plt
      import numpy as np
      
      x = np.arange(10)
      
      fig = plt.figure()
      ax = plt.subplot(111)
      
      for i in xrange(5):
          ax.plot(x, i * x, label='$y = %ix$' % i)
      
      ax.legend()
      
      plt.show()
      

      如果我们做同样的事情,但使用 bbox_to_anchor 关键字参数,我们可以将图例稍微移到轴边界之外:

      import matplotlib.pyplot as plt
      import numpy as np
      
      x = np.arange(10)
      
      fig = plt.figure()
      ax = plt.subplot(111)
      
      for i in xrange(5):
          ax.plot(x, i * x, label='$y = %ix$' % i)
       
      ax.legend(bbox_to_anchor=(1.1, 1.05))
      
      plt.show()
      

      同样,使图例更加水平和/或将其放在图形的顶部(我还打开了圆角和一个简单的阴影):

      import matplotlib.pyplot as plt
      import numpy as np
      
      x = np.arange(10)
      
      fig = plt.figure()
      ax = plt.subplot(111)
      
      for i in xrange(5):
          line, = ax.plot(x, i * x, label='$y = %ix$'%i)
      
      ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
                ncol=3, fancybox=True, shadow=True)
      plt.show()
      

      或者,缩小当前绘图的宽度,并将图例完全放在图形轴之外(注意:如果使用tight_layout(),则省略ax.set_position()

      import matplotlib.pyplot as plt
      import numpy as np
      
      x = np.arange(10)
      
      fig = plt.figure()
      ax = plt.subplot(111)
      
      for i in xrange(5):
          ax.plot(x, i * x, label='$y = %ix$'%i)
      
      # Shrink current axis by 20%
      box = ax.get_position()
      ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
      
      # Put a legend to the right of the current axis
      ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
      
      plt.show()
      

      并以类似的方式,将绘图垂直缩小,并在底部放置一个水平图例:

      import matplotlib.pyplot as plt
      import numpy as np
      
      x = np.arange(10)
      
      fig = plt.figure()
      ax = plt.subplot(111)
      
      for i in xrange(5):
          line, = ax.plot(x, i * x, label='$y = %ix$'%i)
      
      # Shrink current axis's height by 10% on the bottom
      box = ax.get_position()
      ax.set_position([box.x0, box.y0 + box.height * 0.1,
                       box.width, box.height * 0.9])
      
      # Put a legend below current axis
      ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
                fancybox=True, shadow=True, ncol=5)
      
      plt.show()
      

      看看matplotlib legend guide。你也可以看看plt.figlegend()

      【讨论】:

      • 多列图例(带有ncol=<num cols>)正是我所需要的。
      【解决方案3】:

      我只是使用字符串'center left' 作为位置,就像在 matlab 中一样。 我从 matplotlib 导入了 pylab。

      代码如下:

      from matplotlib as plt
      from matplotlib.font_manager import FontProperties
      t = A[:,0]
      sensors = A[:,index_lst]
          
      for i in range(sensors.shape[1]):
          plt.plot(t,sensors[:,i])
              
      plt.xlabel('s')
      plt.ylabel('°C')
      lgd = plt.legend(loc='center left', bbox_to_anchor=(1, 0.5),fancybox = True, shadow = True)
      

      【讨论】:

        【解决方案4】:
        import matplotlib.pyplot as plt
        from matplotlib.font_manager import FontProperties
        
        fontP = FontProperties()
        fontP.set_size('xx-small')
        
        p1, = plt.plot([1, 2, 3], label='Line 1')
        p2, = plt.plot([3, 2, 1], label='Line 2')
        plt.legend(handles=[p1, p2], title='title', bbox_to_anchor=(1.05, 1), loc='upper left', prop=fontP)
        

        • 正如Mateen Ulhaq 所指出的,fontsize='xx-small' 也可以工作,无需导入FontProperties
        plt.legend(handles=[p1, p2], title='title', bbox_to_anchor=(1.05, 1), loc='upper left', fontsize='xx-small')
        

        【讨论】:

          【解决方案5】:

          值得刷新这个问题,因为较新版本的 Matplotlib 使得将图例定位在情节之外变得更加容易。我使用 Matplotlib 版本 3.1.1 制作了这个示例。

          用户可以将 2 元组坐标传递给 loc 参数以将图例定位在边界框中的任何位置。唯一的问题是您需要运行 plt.tight_layout() 以让 matplotlib 重新计算绘图尺寸,以便图例可见:

          import matplotlib.pyplot as plt
          
          plt.plot([0, 1], [0, 1], label="Label 1")
          plt.plot([0, 1], [0, 2], label='Label 2')
          
          plt.legend(loc=(1.05, 0.5))
          plt.tight_layout()
          

          这导致以下情节:

          参考资料:

          【讨论】:

            【解决方案6】:

            除了这里的所有优秀答案之外,如果可能的话,matplotlibpylab 的较新版本可以自动确定放置图例的位置而不干扰绘图

            pylab.legend(loc='best')
            

            如果可能,这将自动将图例远离数据!

            但是,如果没有地方可以放置图例而不重叠数据,那么您将需要尝试其他答案之一;使用loc="best" 永远不会将图例放在情节之外

            【讨论】:

            • 感谢您指出这一点!几年前我找过这个,但没有找到,它确实让我的生活更轻松。
            • 这个选项很有帮助,但不能回答问题,所以我投了反对票。据我所知,最好不要把传说放在情节之外
            • @Tommy:在 OP 的 cmets 中(现在似乎已经消失了),明确说明 OP 希望图例不涵盖图形数据,他认为情节之外是唯一的方法来做到这一点。您可以在 mefathy、Mateo Sanchez、Bastiaan 和 radtek 的回答中看到这一点。 OPasked for X, but he wanted Y.
            • 其实不是。他/她特意要求传说在情节之外。它以问题的名义;)“如何将传说排除在情节之外”。
            • 这并不能保证图例不会遮挡数据。只是做一个非常密集的情节——没有地方放传说。例如,试试这个... from numpy import arange, sin, pi import matplotlib.pyplot as plt t = arange(0.0, 100.0, 0.01) fig = plt.figure(1) ax1 = fig.add_subplot(211) ax1。 scatter(t, sin(2*pi*t),label='test') ax1.grid(True) # ax1.set_ylim((-2, 2)) ax1.set_ylabel('1 Hz') ax1.set_title( '一两个正弦波')用于 ax1.get_xticklabels() 中的标签: label.set_color('r') plt.legend(loc='best') plt.show()
            【解决方案7】:

            要将图例放置在绘图区域之外,请使用 legend()locbbox_to_anchor 关键字。例如,以下代码会将图例放置在绘图区域的右侧:

            legend(loc="upper left", bbox_to_anchor=(1,1))
            

            有关详细信息,请参阅legend guide

            【讨论】:

            • 好的 - 我喜欢这个实现,但是当我去保存图形时(没有在窗口中手动调整它的大小,我不想每次都这样做),图例被砍掉了.关于如何解决这个问题的任何想法?
            • @astromax 我不确定,但也许可以尝试致电plt.tight_layout()
            【解决方案8】:

            只需在plot() 调用之后调用legend(),如下所示:

            # matplotlib
            plt.plot(...)
            plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
            
            # Pandas
            df.myCol.plot().legend(loc='center left', bbox_to_anchor=(1, 0.5))
            

            结果如下所示:

            【讨论】:

            • 在将相同的参数传递给 matplotlib.pyplot.legend 时也可以工作
            • 这是否会为其他人切断图例中的文字?
            • 调用“tight_layout()”为我修复了被截断的单词。
            【解决方案9】:

            这是另一种解决方案,类似于添加bbox_extra_artistsbbox_inches,您不必在savefig 调用范围内添加额外的艺术家。我想出了这个,因为我在函数中生成了大部分情节。

            当您想写出来时,您可以提前将它们添加到Figure 的艺术家中,而不是将所有添加内容添加到边界框中。使用类似于 Franck Dernoncourt 的answer above

            import matplotlib.pyplot as plt
            
            # data 
            all_x = [10,20,30]
            all_y = [[1,3], [1.5,2.9],[3,2]]
            
            # plotting function
            def gen_plot(x, y):
                fig = plt.figure(1)
                ax = fig.add_subplot(111)
                ax.plot(all_x, all_y)
                lgd = ax.legend( [ "Lag " + str(lag) for lag in all_x], loc="center right", bbox_to_anchor=(1.3, 0.5))
                fig.artists.append(lgd) # Here's the change
                ax.set_title("Title")
                ax.set_xlabel("x label")
                ax.set_ylabel("y label")
                return fig
            
            # plotting
            fig = gen_plot(all_x, all_y)
            
            # No need for `bbox_extra_artists`
            fig.savefig("image_output.png", dpi=300, format="png", bbox_inches="tight")
            

            Here's the generated plot.

            【讨论】:

              【解决方案10】:

              当我有巨大的传奇时,对我有用的解决方案是使用额外的空白图像布局。 在以下示例中,我制作了 4 行,并在底部绘制了带有图例偏​​移的图像(bbox_to_anchor),顶部没有被剪切。

              f = plt.figure()
              ax = f.add_subplot(414)
              lgd = ax.legend(loc='upper left', bbox_to_anchor=(0, 4), mode="expand", borderaxespad=0.3)
              ax.autoscale_view()
              plt.savefig(fig_name, format='svg', dpi=1200, bbox_extra_artists=(lgd,), bbox_inches='tight')
              

              【讨论】:

                【解决方案11】:

                简答:在图例上调用 draggable 并以交互方式将其移动到您想要的任何位置:

                ax.legend().draggable()
                

                长答案:如果您更喜欢以交互方式/手动方式而不是编程方式放置图例,您可以切换图例的可拖动模式,以便将其拖动到任何您想要的位置。检查以下示例:

                import matplotlib.pylab as plt
                import numpy as np
                #define the figure and get an axes instance
                fig = plt.figure()
                ax = fig.add_subplot(111)
                #plot the data
                x = np.arange(-5, 6)
                ax.plot(x, x*x, label='y = x^2')
                ax.plot(x, x*x*x, label='y = x^3')
                ax.legend().draggable()
                plt.show()
                

                【讨论】:

                • 不确定我是否完全理解这一点。我如何将图例“拖动”到我想要的任何地方?我正在使用 Python 3.6 和 Jupyter Notebook
                【解决方案12】:

                简答:你可以使用bbox_to_anchor + bbox_extra_artists + bbox_inches='tight'


                更长的答案: 正如其他人在答案中指出的那样,您可以使用bbox_to_anchor 手动指定图例框的位置。

                但是,通常的问题是图例框被裁剪,例如:

                import matplotlib.pyplot as plt
                
                # data 
                all_x = [10,20,30]
                all_y = [[1,3], [1.5,2.9],[3,2]]
                
                # Plot
                fig = plt.figure(1)
                ax = fig.add_subplot(111)
                ax.plot(all_x, all_y)
                
                # Add legend, title and axis labels
                lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
                ax.set_title('Title')
                ax.set_xlabel('x label')
                ax.set_ylabel('y label')
                
                fig.savefig('image_output.png', dpi=300, format='png')
                

                为了防止图例框被裁剪,保存图时可以使用参数bbox_extra_artistsbbox_inches要求savefig在保存的图像中包含裁剪的元素:

                fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')

                例子(我只改了最后一行给fig.savefig()添加了2个参数):

                import matplotlib.pyplot as plt
                
                # data 
                all_x = [10,20,30]
                all_y = [[1,3], [1.5,2.9],[3,2]]
                
                # Plot
                fig = plt.figure(1)
                ax = fig.add_subplot(111)
                ax.plot(all_x, all_y)
                
                # Add legend, title and axis labels
                lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
                ax.set_title('Title')
                ax.set_xlabel('x label')
                ax.set_ylabel('y label')    
                
                fig.savefig('image_output.png', dpi=300, format='png', bbox_extra_artists=(lgd,), bbox_inches='tight')
                

                我希望 matplotlib 本身允许图例框的外部位置为 Matlab does

                figure
                x = 0:.2:12;
                plot(x,besselj(1,x),x,besselj(2,x),x,besselj(3,x));
                hleg = legend('First','Second','Third',...
                              'Location','NorthEastOutside')
                % Make the text of the legend italic and color it brown
                set(hleg,'FontAngle','italic','TextColor',[.3,.2,.1])
                

                【讨论】:

                • 谢谢,但实际上bbox_inches='tight' 对我来说非常适合,即使没有 bbox_extra_artist
                • @avtomaton 谢谢,很高兴知道,您使用哪个版本的 matplotlib?
                • @FranckDernoncourt python3,matplotlib 版本 1.5.3
                【解决方案13】:

                这是来自 here 的 matplotlib 教程中的一个示例。这是更简单的示例之一,但我为图例添加了透明度并添加了 plt.show() 以便您可以将其粘贴到交互式 shell 中并获得结果:

                import matplotlib.pyplot as plt
                p1, = plt.plot([1, 2, 3])
                p2, = plt.plot([3, 2, 1])
                p3, = plt.plot([2, 3, 1])
                plt.legend([p2, p1, p3], ["line 1", "line 2", "line 3"]).get_frame().set_alpha(0.5)
                plt.show()
                

                【讨论】:

                  【解决方案14】:

                  不完全符合您的要求,但我发现它是同一问题的替代方案。 使图例半透明,如下所示:

                  这样做:

                  fig = pylab.figure()
                  ax = fig.add_subplot(111)
                  ax.plot(x,y,label=label,color=color)
                  # Make the legend transparent:
                  ax.legend(loc=2,fontsize=10,fancybox=True).get_frame().set_alpha(0.5)
                  # Make a transparent text box
                  ax.text(0.02,0.02,yourstring, verticalalignment='bottom',
                                       horizontalalignment='left',
                                       fontsize=10,
                                       bbox={'facecolor':'white', 'alpha':0.6, 'pad':10},
                                       transform=self.ax.transAxes)
                  

                  【讨论】:

                    【解决方案15】:

                    如前所述,您还可以将图例放置在情节中,或者也可以稍微偏离它的边缘。这是一个使用Plotly Python API 的示例,由IPython Notebook 制作。我在团队中。

                    首先,您需要安装必要的软件包:

                    import plotly
                    import math
                    import random
                    import numpy as np
                    

                    然后,安装 Plotly:

                    un='IPython.Demo'
                    k='1fw3zw2o13'
                    py = plotly.plotly(username=un, key=k)
                    
                    
                    def sin(x,n):
                    sine = 0
                    for i in range(n):
                        sign = (-1)**i
                        sine = sine + ((x**(2.0*i+1))/math.factorial(2*i+1))*sign
                    return sine
                    
                    x = np.arange(-12,12,0.1)
                    
                    anno = {
                    'text': '$\\sum_{k=0}^{\\infty} \\frac {(-1)^k x^{1+2k}}{(1 + 2k)!}$',
                    'x': 0.3, 'y': 0.6,'xref': "paper", 'yref': "paper",'showarrow': False,
                    'font':{'size':24}
                    }
                    
                    l = {
                    'annotations': [anno], 
                    'title': 'Taylor series of sine',
                    'xaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
                    'yaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
                    'legend':{'font':{'size':16},'bordercolor':'white','bgcolor':'#fcfcfc'}
                    }
                    
                    py.iplot([{'x':x, 'y':sin(x,1), 'line':{'color':'#e377c2'}, 'name':'$x\\\\$'},\
                          {'x':x, 'y':sin(x,2), 'line':{'color':'#7f7f7f'},'name':'$ x-\\frac{x^3}{6}$'},\
                          {'x':x, 'y':sin(x,3), 'line':{'color':'#bcbd22'},'name':'$ x-\\frac{x^3}{6}+\\frac{x^5}{120}$'},\
                          {'x':x, 'y':sin(x,4), 'line':{'color':'#17becf'},'name':'$ x-\\frac{x^5}{120}$'}], layout=l)
                    

                    这会创建您的图表,并让您有机会将图例保留在图表本身中。如果未设置图例,则默认将其放置在图中,如此处所示。

                    对于替代放置,您可以紧密对齐图表的边缘和图例的边框,并移除边框线以更紧密地配合。

                    您可以使用代码或 GUI 移动和重新设置图例和图形的样式。要移动图例,您可以使用以下选项通过将 x 和 y 值指定为

                    • {"x" : 0,"y" : 0} -- 左下
                    • {"x" : 1, "y" : 0} -- 右下
                    • {"x" : 1, "y" : 1} -- 右上角
                    • {"x" : 0, "y" : 1} -- 左上
                    • {"x" :.5, "y" : 0} -- 底部中心
                    • {"x": .5, "y" : 1} -- 顶部中心

                    在这种情况下,我们选择右上角legendstyle = {"x" : 1, "y" : 1},在the documentation中也有描述:

                    【讨论】:

                    • 哦...漂亮的颜色(在第一个情节中)。
                    【解决方案16】:

                    这些方面的东西对我有用。从 Joe 的一些代码开始,此方法修改窗口宽度以自动将图例适合图的右侧。

                    import matplotlib.pyplot as plt
                    import numpy as np
                    
                    plt.ion()
                    
                    x = np.arange(10)
                    
                    fig = plt.figure()
                    ax = plt.subplot(111)
                    
                    for i in xrange(5):
                        ax.plot(x, i * x, label='$y = %ix$'%i)
                    
                    # Put a legend to the right of the current axis
                    leg = ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
                    
                    plt.draw()
                    
                    # Get the ax dimensions.
                    box = ax.get_position()
                    xlocs = (box.x0,box.x1)
                    ylocs = (box.y0,box.y1)
                    
                    # Get the figure size in inches and the dpi.
                    w, h = fig.get_size_inches()
                    dpi = fig.get_dpi()
                    
                    # Get the legend size, calculate new window width and change the figure size.
                    legWidth = leg.get_window_extent().width
                    winWidthNew = w*dpi+legWidth
                    fig.set_size_inches(winWidthNew/dpi,h)
                    
                    # Adjust the window size to fit the figure.
                    mgr = plt.get_current_fig_manager()
                    mgr.window.wm_geometry("%ix%i"%(winWidthNew,mgr.window.winfo_height()))
                    
                    # Rescale the ax to keep its original size.
                    factor = w*dpi/winWidthNew
                    x0 = xlocs[0]*factor
                    x1 = xlocs[1]*factor
                    width = box.width*factor
                    ax.set_position([x0,ylocs[0],x1-x0,ylocs[1]-ylocs[0]])
                    
                    plt.draw()
                    

                    【讨论】:

                    • 我发现这非常有用并且对我有用。请注意,如果您在 wx 后端(例如使用 windows),请将 mgr.window.wm_geometry("%ix%i"%(winWidthNew,mgr.window.winfo_height())) 替换为 mgr.window.SetClientSizeWH(winWidthNew ,winHeightNew) 等
                    • 如果您使用的是 Qt4Agg 后端(这是我的 Linux 安装的 matplotlib 的默认设置),请将 mgr.window.wm_geometry(...) 行替换为 mgr.window.setFixedWidth(winWidthNew)
                    • 而且,正如我刚刚发现的那样,如果您使用的后端不显示任何窗口,即直接保存到文件(如 SVG 和 AGG 后端),请跳过窗口完全调整大小。 fig.set_size_inches(...) 负责调整您需要的大小。
                    【解决方案17】:

                    你也可以试试figlegend。可以创建独立于任何 Axes 对象的图例。但是,您可能需要创建一些“虚拟”路径以确保正确传递对象的格式。

                    【讨论】:

                      猜你喜欢
                      • 2020-01-15
                      • 1970-01-01
                      • 1970-01-01
                      • 2022-06-10
                      • 2011-09-08
                      • 2019-06-18
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多