2014-10-25 5 views
15

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

Вот мой код до сих пор:

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) 

ответ

9

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

Для легенды вам нужны некоторые формы, а также классы. Например, следующее создает список прямоугольников с именем 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. Поскольку легенды охватывали данные, я их переместил, а места для легенд можно найти here. Если есть еще один способ сделать легенду, я не смог найти ее после нескольких быстрых поисков в документах.

+0

Так что, в вашем примере, 'recs' и' labels 'имеют одинаковую длину? И нет ли способа добавить легенду, используя маркеры по умолчанию, как это показано в моем примере? Кажется странным, что единственный способ иметь легенду в плане рассеяния - создать список фигур для всех точек, а не просто автоматически назначать все точки одной и той же формы. – Karnivaurus

+0

«Ярлыки» в первом примере были неверными, я хотел использовать «классы». Я также нашел второй способ сделать легенду в документации, которую я добавил в ответ, а также скриншоты. Я написал второй блок кода с предположением, что данные из разных классов смешиваются. Если вы знаете, что ваши данные сгруппированы по классу и цвету, вы можете значительно упростить второй блок кода, используя, например, 'xc = x [0: 2]' для класса 'A'. Или если ваши данные были первоначально разделены классом, то просто никогда не объединяйте его в один список и не пропустите необходимость в создании списка. – TheSchwa

5

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

Вот первый способ:

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 объекта, второй allwos контролировать записи вручную, и описывается here.

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

Другой способ позволяет поместить все, что вы хотите в легенде, путем создания объектов и меток 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 легенда, но это не похоже на работу, так что я сдался.

1

В моем проекте, я также хочу, чтобы создать пустой разброс legend.Here мое решение:

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) 

Береги «ярлык», «scatterpoints» в выше.

Смежные вопросы