Pylab:将标签映射到颜色

Ano*_*sse 6 python matplotlib scatter-plot scipy

我只是从scipy堆栈开始.我正在使用CSV版本的虹膜数据集.我可以使用以下方法加载它:

iris=numpy.recfromcsv("iris.csv")
Run Code Online (Sandbox Code Playgroud)

并绘制它:

pylab.scatter(iris.field(0), iris.field(1))
pylab.show()
Run Code Online (Sandbox Code Playgroud)

现在我还要绘制存储在iris.field(4)以下类中的类:

chararray(['setosa', ...], dtype='|S10')
Run Code Online (Sandbox Code Playgroud)

将这些字符串映射到用于绘图的颜色的优雅方法是什么?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)))
Run Code Online (Sandbox Code Playgroud)

大概是我想要的,但我不太喜欢手动颜色规格.

编辑:最后一行稍微优雅的版本:

scatter(iris.field(0), iris.field(1), c=map(cols.get, iris.field(4)))
Run Code Online (Sandbox Code Playgroud)

Yan*_*ann 5

一种方式是否优雅在某种程度上是主观的.我个人认为你的方法比'matplotlib'更好.来自matplotlib的颜色模块:

着色映射通常涉及两个步骤:首先使用Normalize或子类的实例将数据数组映射到范围0-1; 然后使用Colormap子类的实例将0-1范围内的此数字映射到颜色.

关于你的问题,我从这里得到的是你需要一个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()
Run Code Online (Sandbox Code Playgroud)

这会产生:

在此输入图像描述

我选择了'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范围内的值数组.

请注意,对于不在列表中的sting,将返回值-1 textvals.这就是屏​​蔽会派上用场的地方.


Joe*_*ton 5

无论值多少钱,在这种情况下,您通常都会做类似的事情:

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()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

@Yann的建议没有什么问题,但是scatter更适合连续数据。

依赖于轴的颜色循环并多次调用绘图会更容易(您还会获得单独的艺术家而不是集合,这对于像这样的离散数据来说是一件好事)。

默认情况下,轴的颜色循环为:蓝色,绿色,红色,青色,品红色,黄色,黑色。

调用7次后plot,它将循环显示这些颜色,因此,如果您有更多项目,则需要手动设置(或在每次调用中指定颜色,以plot使用类似于上面@Yann建议的插值颜色栏) 。