Pyplot объединяет многострочные метки в легенде
У меня есть данные, которые приводят к построению нескольких строк, я хочу дать этим строкам единую метку в моей легенде. Я думаю, что это можно лучше продемонстрировать, используя приведенный ниже пример,
a = np.array([[ 3.57, 1.76, 7.42, 6.52],
[ 1.57, 1.2 , 3.02, 6.88],
[ 2.23, 4.86, 5.12, 2.81],
[ 4.48, 1.38, 2.14, 0.86],
[ 6.68, 1.72, 8.56, 3.23]])
plt.plot(a[:,::2].T, a[:, 1::2].T, 'r', label='data_a')
plt.legend(loc='best')
Как вы можете видеть на Out [23], сюжет привел к 5 различным строкам. Получившийся сюжет выглядит так
![legend of multiple line plot]()
Есть ли способ, которым я могу рассказать метод plot, чтобы избежать нескольких ярлыков? Я не хочу использовать пользовательскую легенду (где вы указываете метку и форму линии все сразу) насколько я могу.
Ответы
Ответ 1
Я бы сделал небольшую вспомогательную функцию лично, если бы я планировал делать это часто;
from matplotlib import pyplot
import numpy
a = numpy.array([[ 3.57, 1.76, 7.42, 6.52],
[ 1.57, 1.2 , 3.02, 6.88],
[ 2.23, 4.86, 5.12, 2.81],
[ 4.48, 1.38, 2.14, 0.86],
[ 6.68, 1.72, 8.56, 3.23]])
def plotCollection(ax, xs, ys, *args, **kwargs):
ax.plot(xs,ys, *args, **kwargs)
if "label" in kwargs.keys():
#remove duplicates
handles, labels = pyplot.gca().get_legend_handles_labels()
newLabels, newHandles = [], []
for handle, label in zip(handles, labels):
if label not in newLabels:
newLabels.append(label)
newHandles.append(handle)
pyplot.legend(newHandles, newLabels)
ax = pyplot.subplot(1,1,1)
plotCollection(ax, a[:,::2].T, a[:, 1::2].T, 'r', label='data_a')
plotCollection(ax, a[:,1::2].T, a[:, ::2].T, 'b', label='data_b')
pyplot.show()
Более простой (и более понятный IMO) способ удаления дубликатов (чем у вас) из handles
и labels
легенды таков:
handles, labels = pyplot.gca().get_legend_handles_labels()
newLabels, newHandles = [], []
for handle, label in zip(handles, labels):
if label not in newLabels:
newLabels.append(label)
newHandles.append(handle)
pyplot.legend(newHandles, newLabels)
Ответ 2
Итак, используя предложение и другой вопрос здесь, я оставляю здесь свое лекарство
handles, labels = plt.gca().get_legend_handles_labels()
i =1
while i<len(labels):
if labels[i] in labels[:i]:
del(labels[i])
del(handles[i])
else:
i +=1
plt.legend(handles, labels)
И новый сюжет выглядит,
![modified multiple line plot legend]()
Ответ 3
Matplotlib дает вам приятный интерфейс для коллекций строк, LineCollection. Код прямолинейный
import numpy
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
a = numpy.array([[ 3.57, 1.76, 7.42, 6.52],
[ 1.57, 1.2 , 3.02, 6.88],
[ 2.23, 4.86, 5.12, 2.81],
[ 4.48, 1.38, 2.14, 0.86],
[ 6.68, 1.72, 8.56, 3.23]])
xs = a[:,::2]
ys = a[:, 1::2]
lines = LineCollection([list(zip(x,y)) for x,y in zip(xs, ys)], label='data_a')
f, ax = plt.subplots(1, 1)
ax.add_collection(lines)
ax.legend()
ax.set_xlim([xs.min(), xs.max()]) # have to set manually
ax.set_ylim([ys.min(), ys.max()])
plt.show()
В результате получается результат ниже:
![График строк, собранных под одной записью.]()
Ответ 4
Решение на основе Numpy на основе ответа на ответ выше.
import numpy as np
import matplotlib.pylab as plt
a = np.array([[3.57, 1.76, 7.42, 6.52],
[1.57, 1.20, 3.02, 6.88],
[2.23, 4.86, 5.12, 2.81],
[4.48, 1.38, 2.14, 0.86],
[6.68, 1.72, 8.56, 3.23]])
plt.plot(a[:,::2].T, a[:, 1::2].T, 'r', label='data_a')
handles, labels = plt.gca().get_legend_handles_labels()
Предполагая, что равные метки имеют одинаковые дескрипторы, получают уникальные метки и их соответствующие индексы, соответствующие индексам обработки.
labels, ids = np.unique(labels, return_index=True)
handles = [handles[i] for i in ids]
plt.legend(handles, labels, loc='best')
plt.show()
Ответ 5
Низкотехнологичное решение состоит в том, чтобы сделать два вызова графика. Один, который отображает ваши данные, и второй, который ничего не содержит, но несет ручку:
a = np.array([[ 3.57, 1.76, 7.42, 6.52],
[ 1.57, 1.2 , 3.02, 6.88],
[ 2.23, 4.86, 5.12, 2.81],
[ 4.48, 1.38, 2.14, 0.86],
[ 6.68, 1.72, 8.56, 3.23]])
plt.plot(a[:,::2].T, a[:, 1::2].T, 'r')
plt.plot([],[], 'r', label='data_a')
plt.legend(loc='best')
Здесь результат:
![result]()