我刚开始使用scipy
堆栈。我正在使用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))
不起作用(来自它预期浮点值或色彩映射的文档)。我没有找到一种自动生成彩色地图的优雅方式。
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)))
答案 0 :(得分:5)
一种方式是否优雅有点主观。我个人认为你的方法比'matplotlib'更好。来自matplotlib的color模块:
Colormapping通常涉及两个步骤:首先是数据数组 使用Normalize或a的实例映射到范围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之间的值数组。
请注意,对于不在列表textvals
中的sting,将返回值-1。这就是屏蔽会派上用场的地方。
答案 1 :(得分: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()
@Yann建议的内容没有错,但scatter
更适合连续数据。
依靠轴颜色循环更容易,只需多次调用绘图(你也可以获得单独的艺术家而不是集合,这对于像这样的离散数据来说是一件好事。)
默认情况下,轴的颜色周期为:蓝色,绿色,红色,青色,品红色,黄色,黑色。
在对plot
进行7次调用后,它会循环显示这些颜色,因此如果您有更多项目,则需要set it manually(或者只需指定每次调用{{3}的颜色1}}使用类似于@Yann建议的内插颜色条。)