Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: expand legend vertically

I have a plot whose legend is anchored to the top-right corner: how can I expand the legend to fit the height of the chart?

borderaxespad=0. would expand it horizontally, but I could not find an equivalent to expand it vertically.

I am using matplotlib 2.0

Sample Code:

import numpy as np

x = np.linspace(0, 2*np.pi, 100)
data = [np.sin(x * np.pi/float(el)) for el in range(1, 5)]

fig, ax = plt.subplots(1)
for key, el in enumerate(data):
    ax.plot(x, el, label=str(key))
ax.legend(bbox_to_anchor=(1.04,1), loc="upper left", borderaxespad=0., mode='expand')
plt.tight_layout(rect=[0,0,0.8,1])

Which produces:

enter image description here

like image 500
FLab Avatar asked Oct 12 '17 13:10

FLab


People also ask

How do I create a vertical legend in Matplotlib?

MatPlotLib with PythonCreate a figure and a set of subplots. Plot the vertical line with red color. The line can have both a solid linestyle connecting all the vertices, and a marker at each vertex. Place a legend on the plot with vertical line.

How do I make the legend bigger in Matplotlib?

The prop keyword is used to change the font size property. It is used in Matplotlib as Using a prop keyword for changing the font size in legend.

How do you expand a legend in Python?

The mode="expand" will expand the legend horizontally into this bounding box, which has zero extend, effectively shrinking it to zero size. If mode is set to "expand" the legend will be horizontally expanded to fill the axes area (or bbox_to_anchor if defines the legend's size).

How do I change the position of a legend in Matplotlib?

To change the position of a legend in Matplotlib, you can use the plt. legend() function. The default location is “best” – which is where Matplotlib automatically finds a location for the legend based on where it avoids covering any data points.


1 Answers

First to explain the output from the question: When using the 2-tuple notation for bbox_to_anchor, a bounding box without extent is created. The mode="expand" will expand the legend horizontally into this bounding box, which has zero extend, effectively shrinking it to zero size.

The problem is that mode="expand" will expand the legend only horizontally. From the documentation:

mode : {“expand”, None}
If mode is set to "expand" the legend will be horizontally expanded to fill the axes area (or bbox_to_anchor if defines the legend’s size).

For a solution you need to dig deep into the legend internals. First off you need to set the bbox-to-anchor with a 4-tuple, specifying also width and height of the bbox, bbox_to_anchor=(x0,y0,width,height), where all numbers are in normalized axes coordinates. Then you need to calculate the height of of the legend's _legend_box. Since there is some padding being set, you need to subtract that padding from the bounding box's height. In order to calculate the padding the current legend's fontsize must be known. All of this has to take place after the axes' position is last changed.

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi, 100)
data = [np.sin(x * np.pi/float(el)) for el in range(1, 5)]

fig, ax = plt.subplots(1)
for key, el in enumerate(data):
    ax.plot(x, el, label=str(key))

# legend:    
leg = ax.legend(bbox_to_anchor=(1.04,0.0,0.2,1), loc="lower left",
                borderaxespad=0, mode='expand')

plt.tight_layout(rect=[0,0,0.8,1])

# do this after calling tight layout or changing axes positions in any way:
fontsize = fig.canvas.get_renderer().points_to_pixels(leg._fontsize)
pad = 2 * (leg.borderaxespad + leg.borderpad) * fontsize
leg._legend_box.set_height(leg.get_bbox_to_anchor().height-pad)

plt.show()

enter image description here

like image 186
ImportanceOfBeingErnest Avatar answered Sep 28 '22 02:09

ImportanceOfBeingErnest