Хватит повторять метки matplotlib в легенде
Вот очень упрощенный пример:
xvalues = [2,3,4,6]
for x in xvalues:
plt.axvline(x,color='b',label='xvalues')
plt.legend()
Легенда теперь будет отображать "xvalues" в виде синей линии 4 раза в легенде. Есть ли более элегантный способ исправить это, чем следующий?
for i,x in enumerate(xvalues):
if not i:
plt.axvline(x,color='b',label='xvalues')
else:
plt.axvline(x,color='b')
5 ответов
legend
принимает в качестве аргументов список маркеров оси и меток, по умолчанию plt.gca().get_legend_handles_labels()
, Вы можете удалить дубликаты ярлыков при звонке legend
, например:
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)
Я не знаю, можно ли это считать "элегантным", но вы можете присвоить метке переменную, которая будет установлена в "_nolegend_"
после первого использования:
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()
Это можно обобщить, используя словарь меток, если вам нужно поставить несколько меток:
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()
(Ответ вдохновлен /questions/1026068/povtoryayuschiesya-elementyi-v-legende-v-matplotlib/1026071#1026071)
Проблема - 3D-массив
Вопросы: ноя 2012 г., октябрь 2013 г.
import numpy as np
a = np.random.random((2, 100, 4))
b = np.random.random((2, 100, 4))
c = np.random.random((2, 100, 4))
Решение - уникальность диктата
Для моего случая _nolegend_
( bli и DSM) не будут работать иlabel if i==0
. В ответе ecatmur используетсяget_legend_handles_labels
и уменьшает легенду с помощью collections.OrderedDict
. Fons демонстрирует, что это возможно без импорта.
В соответствии с этими ответами я предлагаю использовать dict
для уникальных этикеток.
# Step-by-step
ax = plt.gca() # Get the axes you need
a = ax.get_legend_handles_labels() # a = [(h1 ... h2) (l1 ... l2)] non unique
b = {l:h for h,l in zip(*a)} # b = {l1:h1, l2:h2} unique
c = [*zip(*b.items())] # c = [(l1 l2) (h1 h2)]
d = c[::-1] # d = [(h1 h2) (l1 l2)]
plt.legend(*d)
Или
plt.legend(*[*zip(*{l:h for h,l in zip(*ax.get_legend_handles_labels())}.items())][::-1])
Может быть, менее разборчивый и запоминающийся, чем решение Мэтью Бурка. Код гольф приветствуется.
пример
import numpy as np
a = np.random.random((2, 100, 4))
b = np.random.random((2, 100, 4))
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1)
ax.plot(*a, 'C0', label='a')
ax.plot(*b, 'C1', label='b')
ax.legend(*[*zip(*{l:h for h,l in zip(*ax.get_legend_handles_labels())}.items())][::-1])
# ax.legend() # Old, ^ New
plt.show()
На основании ответа /questions/32205844/hvatit-povtoryat-metki-matplotlib-v-legende/32205855#32205855 и /questions/1026068/povtoryayuschiesya-elementyi-v-legende-v-matplotlib/1026071#1026071 plt.gca().get_legend_handles_labels()[1]
дает список имен, можно проверить, есть ли метка уже в списке во время прохождения цикла (label= name[i] if name[i] not in plt.gca().get_legend_handles_labels()[1] else ''
). Для данного примера это решение будет выглядеть так:
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()
Который намного короче, чем /questions/32205844/hvatit-povtoryat-metki-matplotlib-v-legende/32205855#32205855 и более гибкий, чем /questions/1026068/povtoryayuschiesya-elementyi-v-legende-v-matplotlib/1026071#1026071 поскольку его можно использовать для любого вида цикла любой функции графика в петля индивидуально. Однако для многих циклов это, вероятно, медленнее, чем /questions/32205844/hvatit-povtoryat-metki-matplotlib-v-legende/32205855#32205855.
Эти фрагменты кода не сработали лично для меня. Я строил две разные группы в двух разных цветах. Легенда показала бы два красных маркера и два синих маркера, когда я хотел видеть только один на цвет. Я вставлю упрощенную версию того, что у меня сработало:
Импорт заявлений
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)