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:
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.
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.
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).
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.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With