ли способ элегантна или нет несколько субъективны. Я лично нахожу ваши подходы лучше, чем «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()
Это дает:
Я выбрал «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
. Здесь маскировка пригодится.
Спасибо. Я видел вариант многострочной печати, но я еще не знал об элегантном трюке, который вы использовали здесь (+1). Я должен не согласиться на «разброс». Насколько я понимаю, это точно предназначено для такого рода сюжетов, где точки независимы и не связаны (что вы обходите, установив 'linestyle =" none "') –
Точка 'plot' vs' scatter' является неудачной и распространенное заблуждение. Используйте «plot» для построения точек и используйте «разброс», чтобы строить сюжеты, когда вам нужно постоянно изменять размер и/или цвет маркеров на основе третьей или четвертой переменной. 'scatter' возвращает коллекцию, которой намного сложнее управлять. 'plot' _really is_ предназначен для построения отключенных точек, по умолчанию просто строка. Если вы хотите более сжатый вызов, 'plt.plot (x, y, 'o')' будет делать то же, что и 'plt.plot (x, y, linestyle = 'none', marker = 'o')' , –
Спасибо. Я использую 'np.unique (iris.field (4))' (так как у моего CSV нет строки метки colum). Но кроме этого я сейчас использую ваш код. Мне очень нравится трюк. –