464 votes

Axe secondaire avec twinx() : comment ajouter à la légende ?

J'ai un tracé avec deux axes y, utilisant twinx() . Je donne également des étiquettes aux lignes, et je veux les afficher avec legend() mais je ne parviens à faire apparaître les étiquettes d'un seul axe dans la légende :

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
ax2.plot(time, temp, '-r', label = 'temp')
ax.legend(loc=0)
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()

Je n'obtiens donc que les étiquettes du premier axe dans la légende, et pas l'étiquette "temp" du deuxième axe. Comment puis-je ajouter cette troisième étiquette à la légende ?

enter image description here

25 votes

[ Ne faites pas cela dans un code de production, même s'il est très proche de celui-ci. Lorsque mon seul objectif est de générer un beau graphique avec la légende appropriée le plus rapidement possible, j'utilise une astuce peu glorieuse qui consiste à tracer un tableau vide sur ax avec le style que j'utilise sur ax2 : dans votre cas, ax.plot([], [], '-r', label = 'temp') . C'est beaucoup plus rapide et plus simple que de le faire correctement...

0 votes

Voir aussi stackoverflow.com/a/57484812/3642162 pour les pandas et les twinx

9voto

user2105997 Points 131

Un hack rapide qui peut répondre à vos besoins

Enlevez le cadre de la boîte et positionnez manuellement les deux légendes l'une à côté de l'autre. Quelque chose comme ça..

ax1.legend(loc = (.75,.1), frameon = False)
ax2.legend( loc = (.75, .05), frameon = False)

Où le tuple loc est un pourcentage de gauche à droite et de bas en haut qui représente l'emplacement dans le graphique.

5voto

gerrit Points 71

J'ai trouvé un exemple officiel de matplotlib qui utilise host_subplot pour afficher plusieurs axes y et toutes les différentes étiquettes dans une légende. Aucune solution de contournement n'est nécessaire. C'est la meilleure solution que j'ai trouvée jusqu'à présent. http://matplotlib.org/examples/axes_grid/demo_parasite_axes2.html

from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt

host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)

par1 = host.twinx()
par2 = host.twinx()

offset = 60
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
                                    axes=par2,
                                    offset=(offset, 0))

par2.axis["right"].toggle(all=True)

host.set_xlim(0, 2)
host.set_ylim(0, 2)

host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")

par1.set_ylim(0, 4)
par2.set_ylim(1, 65)

host.legend()

plt.draw()
plt.show()

0 votes

Bienvenue à Stack Overflow ! Veuillez citer la partie la plus pertinente du lien, au cas où le site cible serait inaccessible ou hors ligne de façon permanente. Voir Comment rédiger une bonne réponse . Concentrez-vous sur des questions plus actuelles à l'avenir, celle-ci a presque 4 ans.

1 votes

En effet, c'est une bonne découverte, mais j'aurais aimé que vous preniez ce que vous avez appris de l'exemple, que vous l'appliquiez au MWE du PO et que vous incluiez une image.

0voto

Comme le prévoit la exemple de matplotlib.org, une façon propre d'implémenter une légende unique à partir de plusieurs axes est avec les poignées de tracé :

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
fig.subplots_adjust(right=0.75)

twin1 = ax.twinx()
twin2 = ax.twinx()

# Offset the right spine of twin2.  The ticks and label have already been
# placed on the right by twinx above.
twin2.spines.right.set_position(("axes", 1.2))

p1, = ax.plot([0, 1, 2], [0, 1, 2], "b-", label="Density")
p2, = twin1.plot([0, 1, 2], [0, 3, 2], "r-", label="Temperature")
p3, = twin2.plot([0, 1, 2], [50, 30, 15], "g-", label="Velocity")

ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
twin1.set_ylim(0, 4)
twin2.set_ylim(1, 65)

ax.set_xlabel("Distance")
ax.set_ylabel("Density")
twin1.set_ylabel("Temperature")
twin2.set_ylabel("Velocity")

ax.yaxis.label.set_color(p1.get_color())
twin1.yaxis.label.set_color(p2.get_color())
twin2.yaxis.label.set_color(p3.get_color())

tkw = dict(size=4, width=1.5)
ax.tick_params(axis='y', colors=p1.get_color(), **tkw)
twin1.tick_params(axis='y', colors=p2.get_color(), **tkw)
twin2.tick_params(axis='y', colors=p3.get_color(), **tkw)
ax.tick_params(axis='x', **tkw)

ax.legend(handles=[p1, p2, p3])

plt.show()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X