web-dev-qa-db-fra.com

Déplacer et redimensionner la boîte de légendes dans matplotlib

Je crée des tracés à l'aide de Matplotlib que j'enregistre au format SVG, que j'exporte vers .pdf + .pdf_tex à l'aide d'Inkscape et que j'inclus le fichier .pdf_tex dans un document LaTeX.

Cela signifie que je peux entrer des commandes LaTeX dans des titres, des légendes, etc., donnant une image comme celle-ci plot

qui s'affiche comme ceci lorsque je l'utilise dans mon document LaTeX. Notez que la police des nombres sur les axes change et que le code LaTeX dans la légende est compilé:

plot rendered using LaTeX

Code pour l'intrigue (comment exporter vers SVG non montré ici, mais peut être montré sur demande):

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

Le problème est, comme vous pouvez le voir, que l'alignement et la taille de la boîte autour de la légende sont incorrects. En effet, la taille du texte de l'étiquette change lorsque l'image passe par Inkscape + pdflatex (car \footnotesize Etc. disparaît et la taille de police change).

J'ai compris que je pouvais choisir l'emplacement de l'étiquette soit

plt.label(loc = 'upper right')

ou si je veux plus de contrôle je peux utiliser

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

mais je n'ai trouvé aucun moyen de rendre la boîte autour de l'étiquette plus petite. Est-ce possible?

Une alternative à la réduction de la taille de la boîte consiste à supprimer le contour de la boîte à l'aide de quelque chose comme

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

puis déplacer l'étiquette à l'endroit où je le veux. Dans ce cas, je voudrais pouvoir définir le placement de l'étiquette en laissant d'abord python/matplotlib le placer en utilisant

plt.label(loc = 'upper right')

puis par exemple en le déplaçant un peu vers la droite. Est-ce possible? J'ai essayé d'utiliser get_bbox_to_anchor() et set_bbox_to_anchor(), mais je n'arrive pas à le faire fonctionner.

13
Filip S.

Vous pouvez déplacer une légende après l'avoir placée automatiquement en la dessinant, puis en obtenant la position de la bbox. Voici un exemple:

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

18
Molly

Vous pouvez utiliser le bbox_to_anchor et bbox_transform paramètres pour vous aider à définir l'ancre de votre légende:

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

Notez que (1.1, 1.1) sont dans les coordonnées des axes dans cet exemple. Si vous souhaitez utiliser les coordonnées de données, vous devez utiliser bbox_transform=ax.transData au lieu.

10