Pylab: наложение меток на цвета
Я только начинаю со scipy
стека. Я использую набор диафрагмы iris в версии CSV. Я могу загрузить его просто отлично, используя:
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)))
- Выбор размера маркера в Matplotlib
- Недопустимый rgba arg "#" в matplotlib
- График разметки matplotlib с разными маркерами и цветами
- Matplotlib: график рассеяния – размер символа на основе расстояния между пикселями
- Выровнять маркер разметки matplotlib слева и справа
Что бы это ни стоило, в этом случае вы обычно делаете нечто подобное:
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()
Нет ничего плохого в том, что предложил @Yann, но scatter
лучше подходит для непрерывных данных.
Легче полагаться на цветной цикл осей и просто называть график несколько раз (вы также получаете отдельных художников вместо коллекции, что хорошо для дискретных данных, таких как это).
По умолчанию цикл цвета для осей: синий, зеленый, красный, голубой, пурпурный, желтый, черный.
После 7 звонков на plot
он будет циклически возвращаться к этим цветам, поэтому, если у вас есть больше предметов, вам нужно будет установить его вручную (или просто указать цвет в каждом вызове на plot
используя интерполированный цветной байт, аналогичный тому, что предложил @Yann выше).
Является ли способ элегантным или нет, является несколько субъективным. Я лично нахожу ваши подходы лучше, чем «matplotlib». Из цветового модуля matplotlib:
Коллаппирование обычно включает в себя два этапа: массив данных сначала отображается на диапазон 0-1, используя экземпляр Normalize или подкласса; то это число в диапазоне 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()
Это дает:
Я выбрал цветовую карту «RdYlGn», чтобы было легко различать три типа точек. Я не включил функцию clip
как часть __call__
, хотя это возможно с несколькими изменениями.
Традиционно вы можете протестировать нормализацию метода scatter
с использованием ключевого слова norm
, но scatter
тестирует ключевое слово c
чтобы увидеть, хранит ли он строки, и если это так, то предполагается, что вы передаете цвета в качестве их строковых значений, например, «Красный», , «Синий» и т. Д. Поэтому вызов plt.scatter(iris.field(0), iris.field(1), c=iris.field(4), cmap='RdYlGn', norm=norm)
терпит неудачу. Вместо этого я просто использую TextNorm
и « TextNorm
» на iris.field(4)
чтобы вернуть массив значений от 0 до 1.
Обратите внимание, что значение -1 возвращается для укуса не в textvals
списка. Здесь маскировка пригодится.
- Как остановить скрипт Python, но продолжать перевод интерпретатора
- python csv reader, цикл из второй строки
- Как построить график рассеяния с использованием вывода гистограммы в matplotlib?
- Plotly hoverinfo показывает все точки данных вместо текущей точки
- Получить данные из графика с помощью matplotlib
- разброс графика в matplotlib
- Диафрагма
- matplotlib 3D-диаграмма рассеяния с цветом маркера, соответствующим значениям RGB
- matplotlib – chartplot, выбрать цвета для y кортежей