Axe secondaire avec twinx (): comment ajouter à la légende?
j'ai un tracé avec deux axes en y, en utilisant twinx()
. Je donne aussi des étiquettes aux lignes, et je veux les montrer avec legend()
, mais je ne réussis à obtenir les étiquettes d'un 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()
donc je n'obtiens que les étiquettes du premier axe dans la légende, et pas l'étiquette 'temp' du deuxième axe. Comment pourrais-je ajouter cette troisième étiquette de la légende?
6 réponses
Vous pouvez facilement ajouter une deuxième légende en ajoutant la ligne:
ax2.legend(loc=0)
, Vous obtiendrez ceci:
mais si vous voulez toutes les étiquettes sur une légende, alors vous devriez faire quelque chose comme ceci:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
time = np.arange(10)
temp = np.random.random(10)*30
Swdown = np.random.random(10)*100-10
Rn = np.random.random(10)*100-10
fig = plt.figure()
ax = fig.add_subplot(111)
lns1 = ax.plot(time, Swdown, '-', label = 'Swdown')
lns2 = ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
lns3 = ax2.plot(time, temp, '-r', label = 'temp')
# added these three lines
lns = lns1+lns2+lns3
labs = [l.get_label() for l in lns]
ax.legend(lns, labs, 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()
qui vous donnera ceci:
Je ne suis pas sûr que cette fonctionnalité soit nouvelle, mais vous pouvez également utiliser la méthode get_legend_handles_labels() plutôt que de garder une trace des lignes et des étiquettes vous-même:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
pi = np.pi
# fake data
time = np.linspace (0, 25, 50)
temp = 50 / np.sqrt (2 * pi * 3**2) \
* np.exp (-((time - 13)**2 / (3**2))**2) + 15
Swdown = 400 / np.sqrt (2 * pi * 3**2) * np.exp (-((time - 13)**2 / (3**2))**2)
Rn = Swdown - 10
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')
# ask matplotlib for the plotted objects and their labels
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, 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()
, Vous pouvez facilement obtenir ce que vous voulez en ajoutant la ligne ax:
ax.plot(0, 0, '-r', label = 'temp')
ou
ax.plot(np.nan, '-r', label = 'temp')
cela ne ferait qu'ajouter une étiquette à la légende de la hache.
je pense que c'est un moyen beaucoup plus facile. Il n'est pas nécessaire de suivre les lignes automatiquement lorsque vous avez seulement quelques lignes dans les second axes, car la fixation à la main comme ci-dessus serait assez facile. De toute façon, ça dépend de ce dont tu as besoin.
le le code entier est comme ci-dessous:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
time = np.arange(22.)
temp = 20*np.random.rand(22)
Swdown = 10*np.random.randn(22)+40
Rn = 40*np.random.rand(22)
fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()
#---------- look at below -----------
ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2.plot(time, temp, '-r') # The true line in ax2
ax.plot(np.nan, '-r', label = 'temp') # Make an agent in ax
ax.legend(loc=0)
#---------------done-----------------
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()
la parcelle est comme suit:
mise à jour: ajouter une meilleure version:
ax.plot(np.nan, '-r', label = 'temp')
cela ne fera rien alors que plot(0, 0)
peut changer la plage des axes.
à partir de la version 2.1 de matplotlib, vous pouvez utiliser une légende . Au lieu de ax.legend()
, qui produit une légende avec les poignées des axes ax
, on peut créer une légende de figure
fig.legend(loc=1)
qui rassemblera toutes les poignées de tous les sous-lots de la figure. Comme il s'agit d'une légende de figure, elle sera placée au coin de la figure, et l'argument loc
est relatif à la figure.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10)
y = np.linspace(0,10)
z = np.sin(x/3)**2*98
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y, '-', label = 'Quantity 1')
ax2 = ax.twinx()
ax2.plot(x,z, '-r', label = 'Quantity 2')
fig.legend(loc=1)
ax.set_xlabel("x [units]")
ax.set_ylabel(r"Quantity 1")
ax2.set_ylabel(r"Quantity 2")
plt.show()
pour replacer la légende dans les axes, on fournit un bbox_to_anchor
et un bbox_transform
. Ce dernier serait la transformation des axes des axes dans lesquels la légende devrait résider. La première peut être les coordonnées du bord défini par loc
données en coordonnées d'axes.
fig.legend(loc=1, bbox_to_anchor=(1,1), bbox_transform=ax.transAxes)
un piratage rapide qui pourrait convenir à vos besoins..
enlevez le cadre de la boîte et placez manuellement les deux légendes l'une à côté de l'autre. Quelque chose comme cela..
ax1.legend(loc = (.75,.1), frameon = False)
ax2.legend( loc = (.75, .05), frameon = False)
où le N-UPL est le pourcentage de gauche à droite et le pourcentage de bas en haut qui représentent l'emplacement dans le graphique.
j'ai trouvé un exemple de matplotlib officiel suivant qui utilise host_subplot pour afficher plusieurs axes y et toutes les différentes étiquettes dans une légende. Pas de contournement nécessaire. La meilleure solution que j'ai trouvé 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()