Question Comment mettre la légende hors de l'intrigue


J'ai une série de 20 parcelles (pas de sous-parcelles) à faire en un seul chiffre. Je veux que la légende soit en dehors de la boîte. En même temps, je ne veux pas changer les axes, car la taille de la figure est réduite. Veuillez m'aider pour les requêtes suivantes:

  1. Je veux garder la boîte de légende en dehors de la zone de traçage. (Je veux que la légende soit à l'extérieur du côté droit de la zone de traçage).
  2. Y at-il de toute façon que je réduis la taille de la police du texte à l'intérieur de la boîte de légende, de sorte que la taille de la boîte de légende sera petite.

587
2018-01-15 16:10


origine


Réponses:


Créer des propriétés de police

from matplotlib.font_manager import FontProperties

fontP = FontProperties()
fontP.set_size('small')
legend([plot1], "title", prop=fontP)

88
2018-01-15 16:21



Il y a plusieurs façons de faire ce que vous voulez. Pour ajouter à ce que @inalis et @Navi ont déjà dit, vous pouvez utiliser le bbox_to_anchor argument mot-clé pour placer la légende partiellement en dehors des axes et / ou diminuer la taille de la police.

Avant d'envisager de réduire la taille de la police (ce qui peut rendre les choses terriblement difficiles à lire), essayez de jouer en plaçant la légende à différents endroits:

Commençons par un exemple générique:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)

ax.legend()

plt.show()

alt text

Si nous faisons la même chose, mais utilisez le bbox_to_anchor argument mot-clé, nous pouvons déplacer la légende légèrement en dehors des limites des axes:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)

ax.legend(bbox_to_anchor=(1.1, 1.05))

plt.show()

alt text

De même, vous pouvez rendre la légende plus horizontale et / ou la placer en haut de la figure (je tourne également sur les coins arrondis et une simple ombre portée):

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
          ncol=3, fancybox=True, shadow=True)
plt.show()

alt text

Vous pouvez également réduire la largeur du tracé actuel et placer la légende entièrement en dehors de l'axe de la figure:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$'%i)

# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])

# Put a legend to the right of the current axis
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

plt.show()

alt text

Et d'une manière similaire, vous pouvez réduire l'intrigue verticalement, et mettre la légende horizontale en bas:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

fig = plt.figure()
ax = plt.subplot(111)

for i in xrange(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

# Shrink current axis's height by 10% on the bottom
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])

# Put a legend below current axis
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
          fancybox=True, shadow=True, ncol=5)

plt.show()

alt text

Jetez un oeil à la guide de légende matplotlib. Vous pourriez aussi jeter un oeil à plt.figlegend(). J'espère que cela aide un peu, de toute façon!


1274
2018-01-15 18:12



Placer la légende (bbox_to_anchor)

Une légende est positionnée à l'intérieur de la boîte englobante des axes en utilisant loc argument à plt.legend.
Par exemple. loc="upper right" place la légende dans le coin supérieur droit de la boîte englobante, qui par défaut s'étend de (0,0) à (1,1) dans les coordonnées des axes (ou dans la notation de la boîte englobante (x0,y0, width, height)=(0,0,1,1)).

Pour placer la légende en dehors de la zone de délimitation des axes, on peut spécifier un tuple (x0,y0) des coordonnées des axes du coin inférieur gauche de la légende.

plt.legend(loc=(1.04,0))

Cependant, une approche plus polyvalente consisterait à spécifier manuellement la boîte englobante dans laquelle la légende devrait être placée, en utilisant bbox_to_anchor argument. On peut se limiter à ne fournir que le (x0,y0) partie de la bbox. Cela crée une boîte de portée zéro, à partir de laquelle la légende s'étendra dans la direction donnée par le loc argument. Par exemple.

plt.legend (bbox_to_anchor = (1.04,1), loc = "en haut à gauche")

place la légende en dehors des axes, de telle sorte que le coin supérieur gauche de la légende soit en position (1.04,1) dans les coordonnées des axes.

D'autres exemples sont donnés ci-dessous, où en plus l'interaction entre différents arguments comme mode et ncols sont indiqués.

enter image description here

l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
                mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right", 
                bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")

Détails sur la façon d'interpréter l'argument 4-tuple bbox_to_anchor, un péché l4, peuvent être trouvés dans cette question. le mode="expand" agrandit la légende horizontalement à l'intérieur de la boîte de délimitation donnée par le 4-tuple. Pour une légende agrandie verticalement, voir cette question.

Parfois, il peut être utile de spécifier la boîte englobante dans les coordonnées de la figure au lieu des coordonnées des axes. Ceci est montré dans l'exemple l5 d'en haut, où le bbox_transform argument est utilisé pour mettre la légende dans le coin inférieur gauche de la figure.

Post-traitement

Ayant placé la légende en dehors des axes conduit souvent à la situation indésirable qu'il est complètement ou partiellement en dehors de la toile de la figure.

Les solutions à ce problème sont:

  • Ajuster les paramètres du sous-placage
    On peut ajuster les paramètres de sous-placette tels que les axes prennent moins d'espace à l'intérieur de la figure (et laisser ainsi plus d'espace à la légende) en utilisant plt.subplots_adjust. Par exemple.

    plt.subplots_adjust(right=0.7)
    

    laisse 30% d'espace sur le côté droit de la figure, où l'on pourrait placer la légende.

  • Une mise en page serrée
    En utilisant plt.tight_layout Permet d'ajuster automatiquement les paramètres de sous-placette de telle sorte que les éléments de la figure soient bien serrés contre les bords de la figure. Malheureusement, la légende n'est pas prise en compte dans cet automatisme, mais nous pouvons fournir une boîte rectangle dans laquelle la zone entière des sous-placettes (y compris les étiquettes) s'insérera.

    plt.tight_layout(rect=[0,0,0.75,1])
    
  • Sauver la figure avec bbox_inches = "tight"
    L'argument bbox_inches = "tight" à plt.savefig peut être utilisé pour sauvegarder la figure de sorte que tous les artistes sur la toile (y compris la légende) soient bien dans la zone sauvegardée. Si nécessaire, la taille de la figure est automatiquement ajustée.

    plt.savefig("output.png", bbox_inches="tight")
    
  • Ajustement automatique des paramètres du sous-placage
    Un moyen d'ajuster automatiquement la position de l'intrigue secondaire de sorte que la légende s'insère à l'intérieur de la toile sans changer la taille de la figure peut être trouvé dans cette réponse: Création de la figure avec la taille exacte et pas de rembourrage (et la légende en dehors des axes)

Comparaison entre les cas discutés ci-dessus:

enter image description here

Alternatives

Une légende de la figure
On peut utiliser une légende sur la figure au lieu des axes, matplotlib.figure.Figure.legend. Ceci est devenu particulièrement utile pour la version de matplotlib> = 2.1, où aucun argument spécial n'est nécessaire

fig.legend(loc=7) 

créer une légende pour tous les artistes dans les différents axes de la figure. La légende est placée en utilisant le loc argument, similaire à la façon dont il est placé à l'intérieur d'un axe, mais en référence à l'ensemble de la figure - d'où il sera en dehors des axes quelque peu automatiquement. Reste à ajuster les sous-placettes de telle sorte qu'il n'y ait pas de chevauchement entre la légende et les axes. Ici le point "Ajuster les paramètres du sous-placage"  d'en haut sera utile. Un exemple:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,2*np.pi)
colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
    axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))

fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)   
plt.show()

enter image description here

Légende à l'intérieur des axes de sous-repères dédiés
Une alternative à l'utilisation bbox_to_anchor serait de placer la légende dans ses axes dédiés au sous-schéma (lax). Puisque la sous-parcelle de légende devrait être plus petite que la parcelle, nous pouvons utiliser gridspec_kw={"width_ratios":[4,1]} à la création d'axes. Nous pouvons cacher les axes lax.axis("off") mais toujours mettre une légende. Les légendes poignées et étiquettes doivent être obtenues à partir de la parcelle réelle via h,l = ax.get_legend_handles_labels(), et peut ensuite être fourni à la légende dans le lax sous-parcelle, lax.legend(h,l). Un exemple complet est ci-dessous.

import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6,2

fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
ax.plot(x,y, label="y=sin(x)")
....

h,l = ax.get_legend_handles_labels()
lax.legend(h,l, borderaxespad=0)
lax.axis("off")

plt.tight_layout()
plt.show()

Ceci produit un complot qui est visuellement assez semblable à la parcelle d'en haut:

enter image description here

Nous pourrions également utiliser les premiers axes pour placer la légende, mais utilisez le bbox_transform des axes de la légende,

ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")

Dans cette approche, nous n'avons pas besoin d'obtenir les poignées de légende à l'extérieur, mais nous devons spécifier bbox_to_anchor argument.

Lectures complémentaires et notes:

  • Considérez le matplotlib guide de légende avec quelques exemples d'autres choses que vous voulez faire avec les légendes.
  • Un exemple de code pour placer des légendes pour les camemberts peut être trouvé directement dans la réponse à cette question: Python - Legend chevauche le camembert
  • le loc l'argument peut prendre des nombres au lieu de chaînes, ce qui rend les appels plus courts, mais ils ne sont pas très intuitivement mis en correspondance les uns avec les autres. Voici la cartographie pour référence:

enter image description here


308
2018-04-16 16:04



Si vous utilisez des pandas plot() fonction d'emballage et que vous voulez placer la légende à l'extérieur alors voici la façon très simple:

df.myCol.plot().legend(loc='center left', bbox_to_anchor=(1, 0.5))

Nous juste la chaîne legend() appeler après le plot().

Les résultats ressembleraient à ceci:

enter image description here


107
2017-07-03 02:43



Réponse courte: vous pouvez utiliser bbox_to_anchor + bbox_extra_artists + bbox_inches='tight'.


Réponse plus longue: Vous pouvez utiliser bbox_to_anchor pour spécifier manuellement l'emplacement de la boîte de légende, comme d'autres personnes l'ont souligné dans les réponses.

Cependant, le problème habituel est que la boîte de légende est recadrée, par exemple:

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)

# Add legend, title and axis labels
lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')

fig.savefig('image_output.png', dpi=300, format='png')

enter image description here

Afin d'éviter le recadrage de la boîte de légende, lorsque vous enregistrez la figure, vous pouvez utiliser les paramètres bbox_extra_artists et bbox_inches demander savefig pour inclure des éléments recadrés dans l'image enregistrée:

fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')

Exemple (J'ai seulement changé la dernière ligne pour ajouter 2 paramètres à fig.savefig()):

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)

# Add legend, title and axis labels
lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')    

fig.savefig('image_output.png', dpi=300, format='png', bbox_extra_artists=(lgd,), bbox_inches='tight')

enter image description here

Je souhaite que matplotlib permette nativement l'emplacement extérieur de la boîte de légende comme Matlab fait:

figure
x = 0:.2:12;
plot(x,besselj(1,x),x,besselj(2,x),x,besselj(3,x));
hleg = legend('First','Second','Third',...
              'Location','NorthEastOutside')
% Make the text of the legend italic and color it brown
set(hleg,'FontAngle','italic','TextColor',[.3,.2,.1])

enter image description here


69
2017-08-16 22:49



Réponse courte: Appelez draggable sur la légende et déplacez-la de manière interactive où vous le souhaitez:

ax.legend().draggable()

Longue réponse: Si vous préférez placer la légende de manière interactive / manuelle plutôt que par programmation, vous pouvez basculer entre le mode de la légende qui peut être déplacé à l'endroit de votre choix. Vérifiez l'exemple ci-dessous:

import matplotlib.pylab as plt
import numpy as np
#define the figure and get an axes instance
fig = plt.figure()
ax = fig.add_subplot(111)
#plot the data
x = np.arange(-5, 6)
ax.plot(x, x*x, label='y = x^2')
ax.plot(x, x*x*x, label='y = x^3')
ax.legend().draggable()
plt.show()

50
2018-02-20 19:41



En plus de toutes les excellentes réponses ici, les nouvelles versions de matplotlib et pylab pouvez déterminer automatiquement où mettre la légende sans interférer avec les parcelles.

pylab.legend(loc='best')

Cela placera automatiquement la légende en dehors de la parcelle! Compare the use of loc='best'


46
2017-12-08 09:46



Pour placer la légende en dehors de la zone de traçage, utilisez loc et bbox_to_anchor keywords of legend (). Par exemple, le code suivant placera la légende à droite de la zone de traçage:

legend(loc="upper left", bbox_to_anchor=(1,1))

Pour plus d'informations, voir le guide de légende


45
2018-01-15 16:41