How to put the legend out of the plot

后端 未结 17 3199
时光说笑
时光说笑 2020-11-21 04:42

I have a series of 20 plots (not subplots) to be made in a single figure. I want the legend to be outside of the box. At the same time, I do not want to change the axes, a

相关标签:
17条回答
  • 2020-11-21 05:32

    Here's another solution, similar to adding bbox_extra_artists and bbox_inches, where you don't have to have your extra artists in the scope of your savefig call. I came up with this since I generate most of my plot inside functions.

    Instead of adding all your additions to the bounding box when you want to write it out, you can add them ahead of time to the Figure's artists. Using something similar to Franck Dernoncourt's 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.

    0 讨论(0)
  • 2020-11-21 05:33

    You can also try figlegend. It is possible to create a legend independent of any Axes object. However, you may need to create some "dummy" Paths to make sure the formatting for the objects gets passed on correctly.

    0 讨论(0)
  • 2020-11-21 05:35

    It's worth refreshing this question, as newer versions of Matplotlib have made it much easier to position the legend outside the plot. I produced this example with Matplotlib version 3.1.1.

    Users can pass a 2-tuple of coordinates to the loc parameter to position the legend anywhere in the bounding box. The only gotcha is you need to run plt.tight_layout() to get matplotlib to recompute the plot dimensions so the legend is visible:

    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()
    

    This leads to the following plot:

    References:

    • https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html
    • https://showmecode.info/matplotlib/legend/reposition-legend/ (personal site)
    0 讨论(0)
  • 2020-11-21 05:35

    Here is an example from the matplotlib tutorial found here. This is one of the more simpler examples but I added transparency to the legend and added plt.show() so you can paste this into the interactive shell and get a result:

    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()
    
    0 讨论(0)
  • 2020-11-21 05:37

    The solution that worked for me when I had huge legend was to use extra empty image layout. In following example I made 4 rows and at the bottom I plot image with offset for legend (bbox_to_anchor) at the top it does not get cut.

    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')
    
    0 讨论(0)
提交回复
热议问题