Matplotlib: Adjust legend location/position

后端 未结 2 1630
青春惊慌失措
青春惊慌失措 2021-02-07 14:28

I\'m creating a figure with multiple subplots. One of these subplots is giving me some trouble, as none of the axes corners or centers are free (or can be freed up) for placing

相关标签:
2条回答
  • 2021-02-07 14:35

    After spending way too much time on this, I've come up with the following satisfactory solution (the Transformations Tutorial definitely helped):

    bapad = plt.rcParams['legend.borderaxespad']
    fontsize = plt.rcParams['font.size']
    axline = plt.rcParams['axes.linewidth']  #need this, otherwise the result will be off by a few pixels
    pad_points = bapad*fontsize + axline  #padding is defined in relative to font size
    pad_inches = pad_points/72.0  #convert from points to inches
    pad_pixels = pad_inches*fig.dpi  #convert from inches to pixels using the figure's dpi
    

    Then, I found that both of the following work and give the same value for the padding:

    # Define inverse transform, transforms display coordinates (pixels) to axes coordinates
    inv = ax[1].transAxes.inverted()
    # Inverse transform two points on the display and find the relative distance
    pad_axes = inv.transform((pad_pixels, 0)) - inv.transform((0,0))  
    pad_xaxis = pad_axes[0]
    

    or

    # Find how may pixels there are on the x-axis
    x_pixels = ax[1].transAxes.transform((1,0)) - ax[1].transAxes.transform((0,0))
    # Compute the ratio between the pixel offset and the total amount of pixels 
    pad_xaxis = pad_pixels/x_pixels[0]
    

    And then set the legend with:

    ax[1].legend(loc=(pad_xaxis,0.6))
    

    Plot:

    0 讨论(0)
  • 2021-02-07 14:47

    I saw the answer you posted and tried it out. The problem however is that it is also depended on the figure size.

    Here's a new try:

    import numpy
    import matplotlib.pyplot as plt
    
    
    x = numpy.linspace(0, 10, 10000)
    y = numpy.cos(x) + 2.
    
    x_value = .014    #Offset by eye
    y_value = .55
    
    fig, ax = plt.subplots(1, 2, sharex = False, sharey = False)
    fig.set_size_inches(50,30)
    
    ax[0].plot(x, y, label = "cos")
    ax[0].set_ylim([0.8,3.2])
    ax[0].legend(loc=2)
    
    line1 ,= ax[1].plot(x,y)
    ax[1].set_ylim([0.8,3.2])
    
    axbox = ax[1].get_position()
    
    fig.legend([line1], ["cos"], loc = (axbox.x0 + x_value, axbox.y0 + y_value))
    
    plt.show()
    

    So what I am now doing is basically getting the coordinates from the subplot. I then create the legend based on the dimensions of the entire figure. Hence, the figure size does not change anything to the legend positioning anymore.

    With the values for x_value and y_value the legend can be positioned in the subplot. x_value has been eyeballed for a good correspondence with the "normal" legend. This value can be changed at your desire. y_value determines the height of the legend.

    enter image description here

    Good luck!

    0 讨论(0)
提交回复
热议问题