Графический график Matplotlib с легендой

Я хочу создать график разброса Matplotlib с легендой, показывающей цвет для каждого класса. Например, у меня есть список значений x и y и список значений classes. Каждый элемент в списках x, y и classes соответствует одной точке графика. Я хочу, чтобы каждый класс имел свой собственный цвет, который я уже закодировал, но затем я хочу, чтобы классы отображались в легенде. Какие параметры я могу передать функции legend() для достижения этого?

Вот мой код:

x = [1, 3, 4, 6, 7, 9]
y = [0, 0, 5, 8, 8, 8]
classes = ['A', 'A', 'B', 'C', 'C', 'C']
colours = ['r', 'r', 'b', 'g', 'g', 'g']
plt.scatter(x, y, c=colours)

Ответ 1

Во-первых, у меня такое чувство, что вы хотели использовать апострофы, а не обратные сигналы при объявлении цветов.

Для легенды вам нужны некоторые формы, а также классы. Например, следующее создает список прямоугольников с названием recs для каждого цвета в class_colours.

import matplotlib.patches as mpatches

classes = ['A','B','C']
class_colours = ['r','b','g']
recs = []
for i in range(0,len(class_colours)):
    recs.append(mpatches.Rectangle((0,0),1,1,fc=class_colours[i]))
plt.legend(recs,classes,loc=4)

Output from first code block

Вы можете использовать круги тоже, если хотите, просто ознакомьтесь с документацией matplotlib.patches. Существует второй способ создания легенды, в которой вы указываете "Ярлык" для набора точек, используя отдельную команду разброса для каждого набора. Пример этого приведен ниже.

classes = ['A','A','B','C','C','C']
colours = ['r','r','b','g','g','g']
for (i,cla) in enumerate(set(classes)):
    xc = [p for (j,p) in enumerate(x) if classes[j]==cla]
    yc = [p for (j,p) in enumerate(y) if classes[j]==cla]
    cols = [c for (j,c) in enumerate(colours) if classes[j]==cla]
    plt.scatter(xc,yc,c=cols,label=cla)
plt.legend(loc=4)

enter image description here

Первый метод - тот, который я лично использовал, второй, который я только что нашел, рассматривая документацию matplotlib. Поскольку легенды охватывали точки данных, я переместил их, а места для легенд можно найти здесь. Если есть другой способ сделать легенду, я не смог найти ее после нескольких быстрых поисков в документах.

Ответ 2

Есть два способа сделать это. Один из них дает вам легендарные записи для каждой вещи, которую вы замышляете, а другой позволяет вам вставить все, что вы хотите в легенде, сильно воруя от этого ответа.

Здесь первый способ:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-1,1,100)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

#Plot something
ax.plot(x,x, color='red', ls="-", label="$P_1(x)$")
ax.plot(x,0.5 * (3*x**2-1), color='green', ls="--", label="$P_2(x)$")
ax.plot(x,0.5 * (5*x**3-3*x), color='blue', ls=":", label="$P_3(x)$")

ax.legend()
plt.show()

enter image description here

Функция ax.legend() имеет более одного использования, первая просто создает легенду, основанную на строках в объекте axes, вторая - все, чтобы вы вручную управляли записями, и описывается здесь.

Вам в основном нужно дать легенде строки и соответствующие метки.

Другой способ позволяет поместить все, что вы хотите в легенде, путем создания объектов и меток Artist и передачи их в функцию ax.legend(). Вы можете использовать это, чтобы поместить некоторые из ваших строк в легенду, или вы можете использовать его, чтобы поместить все, что вы хотите в легенде.

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-1,1,100)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

#Plot something
p1, = ax.plot(x,x, color='red', ls="-", label="$P_1(x)$")
p2, = ax.plot(x,0.5 * (3*x**2-1), color='green', ls="--", label="$P_2(x)$")
p3, = ax.plot(x,0.5 * (5*x**3-3*x), color='blue', ls=":", label="$P_3(x)$")

#Create legend from custom artist/label lists
ax.legend([p1,p2], ["$P_1(x)$", "$P_2(x)$"])

plt.show()

enter image description here

Или здесь мы создаем новые объекты Line2D и даем их легенде.

import matplotlib.pyplot as pltit|delete|flag
import numpy as np
import matplotlib.patches as mpatches

x = np.linspace(-1,1,100)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

#Plot something
p1, = ax.plot(x,x, color='red', ls="-", label="$P_1(x)$")
p2, = ax.plot(x,0.5 * (3*x**2-1), color='green', ls="--", label="$P_2(x)$")
p3, = ax.plot(x,0.5 * (5*x**3-3*x), color='blue', ls=":", label="$P_3(x)$")

fakeLine1 = plt.Line2D([0,0],[0,1], color='Orange', marker='o', linestyle='-')
fakeLine2 = plt.Line2D([0,0],[0,1], color='Purple', marker='^', linestyle='')
fakeLine3 = plt.Line2D([0,0],[0,1], color='LightBlue', marker='*', linestyle=':')

#Create legend from custom artist/label lists
ax.legend([fakeLine1,fakeLine2,fakeLine3], ["label 1", "label 2", "label 3"])

plt.show()

enter image description here

Я также попытался использовать метод patches для работы, как на странице руководства по легенде matplotlib, но, похоже, он не работал, поэтому я сдался.

Ответ 3

В моем проекте я также хочу создать пустую легенду разброса. Вот мое решение:

from mpl_toolkits.basemap import Basemap
#use the scatter function from matplotlib.basemap
#you can use pyplot or other else.
select = plt.scatter([], [],s=200,marker='o',linewidths='3',edgecolor='#0000ff',facecolors='none',label=u'监测站点') 
plt.legend(handles=[select],scatterpoints=1)

Позаботьтесь о "метке", "местах рассеяния" выше.

Ответ 4

Это легко обрабатывается на графике рассеяния морского происхождения. Вот реализация этого.

import matplotlib.pyplot as plt
import seaborn as sns

x = [1, 3, 4, 6, 7, 9]
y = [0, 0, 5, 8, 8, 8]
classes = ['A', 'A', 'B', 'C', 'C', 'C']
colours = ['r', 'r', 'b', 'g', 'g', 'g']

sns.scatterplot(x=x, y=y, hue=classes)
plt.show()

plot