2012-03-16 6 views
5

Я только начинаю с стека scipy. Я использую набор диафрагмы iris в версии CSV. Я могу загрузить его просто отлично с помощью:Pylab: наклейки на карты цветов

iris=numpy.recfromcsv("iris.csv") 

и сюжет его:

pylab.scatter(iris.field(0), iris.field(1)) 
pylab.show() 

Теперь я хотел бы также построить классы, которые хранятся в iris.field(4):

chararray(['setosa', ...], dtype='|S10') 

Каков элегантный способ сопоставить эти строки с цветами для построения графика? scatter(iris.field(0), iris.field(1), c=iris.field(4)) не работает (из документов, которые он ожидает значения float или colormap). Я не нашел элегантный способ автоматического создания цветовой карты.

cols = {"versicolor": "blue", "virginica": "green", "setosa": "red"} 
scatter(iris.field(0), iris.field(1), c=map(lambda x:cols[x], iris.field(4))) 

делает примерно то, что я хочу, но я не люблю ручной цвет спецификации слишком много.

Редактировать: чуть более элегантный вариант последней строки:

scatter(iris.field(0), iris.field(1), c=map(cols.get, iris.field(4))) 

ответ

4

По какой-то стоит, вы обычно делаете что-то больше, как это в этом случае:

import numpy as np 
import matplotlib.pyplot as plt 

iris = np.recfromcsv('iris.csv') 
names = set(iris['class']) 

x,y = iris['sepal_length'], iris['sepal_width'] 

for name in names: 
    cond = iris['class'] == name 
    plt.plot(x[cond], y[cond], linestyle='none', marker='o', label=name) 

plt.legend(numpoints=1) 
plt.show() 

enter image description here

Там нет ничего плохого в том, что предложил @Yann, но scatter лучше подходит для непрерывного данные.

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

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

После 7 звонков в plot, это будет цикл назад на эти цвета, поэтому если у вас есть больше деталей, вам нужно set it manually (или просто указать цвет в каждом вызове plot используя интерполированное Colorbar, похожий на то, что @ Янн предложил выше).

+0

Спасибо. Я видел вариант многострочной печати, но я еще не знал об элегантном трюке, который вы использовали здесь (+1). Я должен не согласиться на «разброс». Насколько я понимаю, это точно предназначено для такого рода сюжетов, где точки независимы и не связаны (что вы обходите, установив 'linestyle =" none "') –

+0

Точка 'plot' vs' scatter' является неудачной и распространенное заблуждение. Используйте «plot» для построения точек и используйте «разброс», чтобы строить сюжеты, когда вам нужно постоянно изменять размер и/или цвет маркеров на основе третьей или четвертой переменной. 'scatter' возвращает коллекцию, которой намного сложнее управлять. 'plot' _really is_ предназначен для построения отключенных точек, по умолчанию просто строка. Если вы хотите более сжатый вызов, 'plt.plot (x, y, 'o')' будет делать то же, что и 'plt.plot (x, y, linestyle = 'none', marker = 'o')' , –

+0

Спасибо. Я использую 'np.unique (iris.field (4))' (так как у моего CSV нет строки метки colum). Но кроме этого я сейчас использую ваш код. Мне очень нравится трюк. –

5

ли способ элегантна или нет несколько субъективны. Я лично нахожу ваши подходы лучше, чем «matplotlib». Из color модуля Matplotlib в:

обычно включает в себя преобразование цвета в два этапа: массив данных сначала отображается на интервале 0-1, используя экземпляр или Нормализовать в подкласса; то это число в диапазоне 0-1 отображается на цвет, используя экземпляр подкласса Colormap.

Что я беру из этого в связи с вашей проблемой, так это то, что вам нужен подкласс Normalize, который берет строки и отображает их в 0-1.

Вот пример, который наследует от Normalize, чтобы сделать подкласс TextNorm, который используется для преобразования строки в значение от 0 до 1. Эта нормализация используется для получения соответствующего цвета.

import matplotlib.pyplot as plt 
from matplotlib.colors import Normalize 
import numpy as np 
from numpy import ma 

class TextNorm(Normalize): 
    '''Map a list of text values to the float range 0-1''' 

    def __init__(self, textvals, clip=False): 
     self.clip = clip 
     # if you want, clean text here, for duplicate, sorting, etc 
     ltextvals = set(textvals) 
     self.N = len(ltextvals) 
     self.textmap = dict(
      [(text, float(i)/(self.N-1)) for i, text in enumerate(ltextvals)]) 
     self.vmin = 0 
     self.vmax = 1 

    def __call__(self, x, clip=None): 
     #Normally this would have a lot more to do with masking 
     ret = ma.asarray([self.textmap.get(xkey, -1) for xkey in x]) 
     return ret 

    def inverse(self, value): 
     return ValueError("TextNorm is not invertible") 

iris = np.recfromcsv("iris.csv") 
norm = TextNorm(iris.field(4)) 

plt.scatter(iris.field(0), iris.field(1), c=norm(iris.field(4)), cmap='RdYlGn') 
plt.savefig('textvals.png') 
plt.show() 

Это дает:

enter image description here

Я выбрал «RdYlGn» цветовую карту так, чтобы легко можно было различить три типа точек. Я не включил функцию clip как часть __call__, хотя это возможно с несколькими модификациями.

Традиционно вы можете проверить нормализацию метода scatter используя norm ключевое слово, но scatter проверяет c ключевое слово, чтобы увидеть, если он хранит строки, и если это произойдет, то это предполагает, что вы передаете в цветах, как их строковых значений, например «Красный», «Синий» и т. Д. Поэтому вызов plt.scatter(iris.field(0), iris.field(1), c=iris.field(4), cmap='RdYlGn', norm=norm) терпит неудачу. Вместо этого я просто использую TextNorm и «работаю» на iris.field(4), чтобы вернуть массив значений от 0 до 1.

Обратите внимание, что значение -1 возвращается для укуса не в списке textvals. Здесь маскировка пригодится.

+0

Я работаю над примером .... – Yann

+0

Поскольку я просто сделал то же самое в 'R' (пытаясь сделать обзор инструментов), мне было интересно, есть ли эквивалент' unclass' в ' scipy'. –

+0

@ Anony-Mousse Я не уверен, что вы просите в своем комментарии. Как бы вы использовали 'unclass' и что бы вы использовали. – Yann

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