Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move and resize legends-box in matplotlib

Tags:

I'm creating plots using Matplotlib that I save as SVG, export to .pdf + .pdf_tex using Inkscape, and include the .pdf_tex-file in a LaTeX document.

This means that I can input LaTeX-commands in titles, legends etc., giving an image like this plot

which renders like this when I use it in my LaTeX document. Notice that the font for the numbers on the axes change, and the LaTeX-code in the legend is compiled:

plot rendered using LaTeX

Code for the plot (how to export to SVG not shown here, but can be shown on request):

import numpy as np x = np.linspace(0,1,100) y = x**2  import matplotlib.pyplot as plt plt.plot(x, y, label = '{\\footnotesize \$y = x^2\$}') plt.legend(loc = 'best') plt.show() 

The problem is, as you can see, that the alignment and size of the box around the legend is wrong. This is because the size of the text of the label changes when the image is passed through Inkscape + pdflatex (because \footnotesize etc. disappears, and the font size changes).

I have figured out that I can choose the placement of the label by either

plt.label(loc = 'upper right') 

or if I want more control I can use

plt.label(bbox_to_anchor = [0.5, 0.2]) 

but I haven't found any way of making the box around the label smaller. Is this possible?

An alternative to making the box smaller is to remove the outline of the box using something like

legend = plt.legend() legend.get_frame().set_edgecolor('1.0') 

and then moving the label to where I want it. In that case I would like to be able to set the placement of the label by first letting python/matplotlib place it using

plt.label(loc = 'upper right') 

and then for example moving it a bit to the right. Is this possible? I have tried using get_bbox_to_anchor() and set_bbox_to_anchor(), but can't seem to get it to work.

like image 353
Filip S. Avatar asked Apr 23 '14 07:04

Filip S.


People also ask

How do I resize the legend box in Matplotlib?

To place a legend on the figure and to adjust the size of legend box, use borderpad=2 in legend() method. To display the figure, use show() method.

How do I move the legend box 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.

How do I resize my legend box?

Select the legend box by clicking once over the legend area. A frame with 8 “handles” appears. Click on any of these handles, then hold and drag to resize the box until all labels are visible.

How do I change my legend location?

Click the chart, and then click the Chart Layout tab. To change the position of the legend, under Labels, click Legend, and then click the legend position that you want. To change the format of the legend, under Labels, click Legend, click Legend Options, and then make the format changes that you want.


2 Answers

You can move a legend after automatically placing it by drawing it, and then getting the bbox position. Here's an example:

import matplotlib.pyplot as plt import numpy as np  # Plot data x = np.linspace(0,1,100) y = x**2 fig = plt.figure() ax = fig.add_subplot(221) #small subplot to show how the legend has moved.   # Create legend plt.plot(x, y, label = '{\\footnotesize \$y = x^2\$}') leg = plt.legend( loc = 'upper right')  plt.draw() # Draw the figure so you can find the positon of the legend.   # Get the bounding box of the original legend bb = leg.get_bbox_to_anchor().inverse_transformed(ax.transAxes)  # Change to location of the legend.  xOffset = 1.5 bb.x0 += xOffset bb.x1 += xOffset leg.set_bbox_to_anchor(bb, transform = ax.transAxes)   # Update the plot plt.show() 

legend moved after first drawing

like image 56
Molly Avatar answered Oct 17 '22 01:10

Molly


You may use the bbox_to_anchor and bbox_transform parameters to help you setting the anchor for your legend:

ax = plt.gca() plt.legend(bbox_to_anchor=(1.1, 1.1), bbox_transform=ax.transAxes) 

Note that (1.1, 1.1) are in the axes coordinates in this example. If you wish to use the data coordinates you have to use bbox_transform=ax.transData instead.

like image 34
Saullo G. P. Castro Avatar answered Oct 17 '22 02:10

Saullo G. P. Castro