Je crée une figure avec plusieurs sous-intrigues. L'une de ces sous-intrigues me pose quelques problèmes, car aucun des coins ou centres des axes n'est libre (ou peut être libéré) pour placer la légende. Ce que j'aimerais faire, c'est que la légende soit placée quelque part entre les emplacements `` en haut à gauche '' et `` au centre à gauche '', tout en gardant le rembourrage entre elle et l'axe des y égal aux légendes des autres sous-parcelles (qui sont placé à l'aide de l'un des mots clés d'emplacement de légende prédéfinis).
Je sais que je peux spécifier une position personnalisée en utilisant loc=(x,y)
, mais je ne peux pas comprendre comment obtenir un rembourrage entre la légende et l'axe des y égal à celui utilisé par les autres légendes. Serait-il possible d'utiliser en quelque sorte la propriété borderaxespad
de la première légende? Bien que je ne réussisse pas à faire fonctionner cela.
Toutes les suggestions seront les bienvenues!
Edit: Voici une illustration (très simplifiée) du problème:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2, sharex=False, sharey=False)
ax[0].axhline(y=1, label='one')
ax[0].axhline(y=2, label='two')
ax[0].set_ylim([0.8,3.2])
ax[0].legend(loc=2)
ax[1].axhline(y=1, label='one')
ax[1].axhline(y=2, label='two')
ax[1].axhline(y=3, label='three')
ax[1].set_ylim([0.8,3.2])
ax[1].legend(loc=2)
plt.show()
Ce que j'aimerais, c'est que la légende dans le tracé de droite soit quelque peu abaissée pour ne plus chevaucher la ligne. En dernier recours, je pourrais changer les limites des axes, mais j'aimerais bien éviter cela.
Après avoir passé beaucoup trop de temps à ce sujet, j'ai trouvé la solution satisfaisante suivante (le Transformations Tutorial a certainement aidé):
bapad = plt.rcParams['legend.borderaxespad']
fontsize = plt.rcParams['font.size']
axline = plt.rcParams['axes.linewidth'] #need this, otherwise the result will be off by a few pixels
pad_points = bapad*fontsize + axline #padding is defined in relative to font size
pad_inches = pad_points/72.0 #convert from points to inches
pad_pixels = pad_inches*fig.dpi #convert from inches to pixels using the figure's dpi
Ensuite, j'ai trouvé que les deux travaux suivants donnent la même valeur pour le rembourrage:
# Define inverse transform, transforms display coordinates (pixels) to axes coordinates
inv = ax[1].transAxes.inverted()
# Inverse transform two points on the display and find the relative distance
pad_axes = inv.transform((pad_pixels, 0)) - inv.transform((0,0))
pad_xaxis = pad_axes[0]
ou
# Find how may pixels there are on the x-axis
x_pixels = ax[1].transAxes.transform((1,0)) - ax[1].transAxes.transform((0,0))
# Compute the ratio between the pixel offset and the total amount of pixels
pad_xaxis = pad_pixels/x_pixels[0]
Et puis définissez la légende avec:
ax[1].legend(loc=(pad_xaxis,0.6))
Terrain:
J'ai vu la réponse que vous avez publiée et je l'ai essayée. Le problème est cependant que cela dépend aussi de la taille de la figure.
Voici un nouvel essai:
import numpy
import matplotlib.pyplot as plt
x = numpy.linspace(0, 10, 10000)
y = numpy.cos(x) + 2.
x_value = .014 #Offset by eye
y_value = .55
fig, ax = plt.subplots(1, 2, sharex = False, sharey = False)
fig.set_size_inches(50,30)
ax[0].plot(x, y, label = "cos")
ax[0].set_ylim([0.8,3.2])
ax[0].legend(loc=2)
line1 ,= ax[1].plot(x,y)
ax[1].set_ylim([0.8,3.2])
axbox = ax[1].get_position()
fig.legend([line1], ["cos"], loc = (axbox.x0 + x_value, axbox.y0 + y_value))
plt.show()
Donc, ce que je fais maintenant, c'est essentiellement d'obtenir les coordonnées de la sous-intrigue. Je crée ensuite la légende en fonction des dimensions de la figure entière. Par conséquent, la taille de la figure ne change plus rien au positionnement de la légende.
Avec les valeurs de x_value
et y_value
la légende peut être positionnée dans le sous-tracé. x_value
a été oculaire pour une bonne correspondance avec la légende "normale". Cette valeur peut être modifiée à votre guise. y_value
détermine la hauteur de la légende.
Bonne chance!