Voici un exemple très simplifié:
xvalues = [2,3,4,6]
for x in xvalues:
plt.axvline(x,color='b',label='xvalues')
plt.legend()
La légende affichera maintenant 'xvalues' sous la forme d'une ligne bleue 4 fois dans la légende . Existe-t-il une manière plus élégante de corriger cela que la suivante?
for i,x in enumerate(xvalues):
if not i:
plt.axvline(x,color='b',label='xvalues')
else:
plt.axvline(x,color='b')
legend
prend comme argument une liste de descripteurs d'axe et d'étiquettes, par défaut à plt.gca().get_legend_handles_labels()
. Vous pouvez supprimer les étiquettes en double lorsque vous appelez legend
, par exemple:
from collections import OrderedDict
import matplotlib.pyplot as plt
handles, labels = plt.gca().get_legend_handles_labels()
by_label = OrderedDict(Zip(labels, handles))
plt.legend(by_label.values(), by_label.keys())
handles, labels = ax.get_legend_handles_labels()
handle_list, label_list = [], []
for handle, label in Zip(handles, labels):
if label not in label_list:
handle_list.append(handle)
label_list.append(label)
plt.legend(handle_list, label_list)
Ces extraits de code ne fonctionnaient pas pour moi personnellement. Je dessinais deux groupes différents dans deux couleurs différentes. La légende indiquait deux marqueurs rouges et deux marqueurs bleus, alors que je voulais seulement en voir un par couleur. Je vais coller une version simplifiée de ce qui a fonctionné pour moi:
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLine2D
points_grp, = plt.plot(x[grp_idx], y[grp_idx], color=c.c[1], marker=m, ms=4, lw=0, label=leglab[1])
points_ctrl, = plt.plot(x[ctrl_idx], y[ctrl_idx], color=c.c[0], marker=m, ms=4, lw=0, label=leglab[0])
points_dict = {points_grp: HandlerLine2D(numpoints=1),points_ctrl: HandlerLine2D(numpoints=1)}
leg = ax.legend(fontsize=12, loc='upper left', bbox_to_anchor=(1, 1.03),handler_map=points_dict)
Je ne sais pas si cela peut être considéré comme "élégant", mais vous pouvez attribuer à votre étiquette une variable dont la valeur est définie sur "_nolegend_"
après la première utilisation:
my_label = "xvalues"
xvalues = [2,3,4,6]
for x in xvalues:
plt.axvline(x, color='b', label=my_label)
my_label = "_nolegend_"
plt.legend()
Ceci peut être généralisé à l'aide d'un dictionnaire d'étiquettes si vous devez en mettre plusieurs:
my_labels = {"x1" : "x1values", "x2" : "x2values"}
x1values = [1, 3, 5]
x2values = [2, 4, 6]
for x in x1values:
plt.axvline(x, color='b', label=my_labels["x1"])
my_labels["x1"] = "_nolegend_"
for x in x2values:
plt.axvline(x, color='r', label=my_labels["x2"])
my_labels["x2"] = "_nolegend_"
plt.legend()
(Réponse inspirée par https://stackoverflow.com/a/19386045/1878788 )
Sur la base de answer https://stackoverflow.com/a/13589144/9132798 et https://stackoverflow.com/a/19386045/9132798plt.gca().get_legend_handles_labels()[1]
donne une liste de noms, c'est possible de vérifier si l'étiquette est déjà dans la liste pendant le traçage en boucle (label= name[i] if name[i] not in plt.gca().get_legend_handles_labels()[1] else ''
). Pour l'exemple donné, cette solution ressemblerait à ceci:
import matplotlib.pyplot as plt
xvalues = [2,3,4,6]
for x in xvalues:
plt.axvline(x,color='b',\
label= 'xvalues' if 'xvalues' \
not in plt.gca().get_legend_handles_labels()[1] else '')
plt.legend()
Ce qui est beaucoup plus court que https://stackoverflow.com/a/13589144/9132798 et plus flexible que https://stackoverflow.com/a/19386045/9132798 car il pourrait être utilisé pour n'importe quel type de boucle toute fonction de tracé dans la boucle individuellement . Cependant, pour de nombreux cycles, elle est probablement plus lente que https://stackoverflow.com/a/13589144/9132798 .