6

私はちょうど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)))
4

2 に答える 2

5

方法がエレガントであるかどうかは、いくぶん主観的です。私は個人的にあなたのアプローチが「matplotlib」の方法よりも優れていると思います。matplotlibのカラーモジュールから:

カラーマッピングには通常、2つのステップが含まれます。データ配列は、Normalizeまたはサブクラスのインスタンスを使用して最初に範囲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()

これにより、次のものが生成されます。

ここに画像の説明を入力してください

3種類のポイントを簡単に区別できるように、「RdYlGn」カラーマップを選択しました。いくつかの変更を加えることで可能ですが、このclip機能をの一部として含めませんでした。__call__

従来、キーワードscatterを使用してメソッドの正規化をテストできますが、キーワードをテストして文字列が格納されているかどうかを確認し、格納されている場合は、文字列値として色を渡していると想定します(例:「赤」、「青」)。 、など。したがって、呼び出しは失敗します。代わりに、で「操作」を使用して、0から1の範囲の値の配列を返します。normscattercplt.scatter(iris.field(0), iris.field(1), c=iris.field(4), cmap='RdYlGn', norm=norm)TextNormiris.field(4)

リストにないスティングに対しては、-1の値が返されることに注意してくださいtextvals。これは、マスキングが役立つ場所です。

于 2012-03-16T16:55:04.877 に答える
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()

ここに画像の説明を入力

@Yann が提案したことには何の問題もありませんがscatter、継続的なデータにより適しています。

軸のカラー サイクルに依存して plot を複数回呼び出す方が簡単です (コレクションの代わりに個別のアーティストを取得することもできます。これは、このような個別のデータには適しています)。

デフォルトでは、軸のカラー サイクルは、青、緑、赤、シアン、マゼンタ、黄、黒です。

を 7 回呼び出した後plot、それらの色を循環して戻すため、さらに項目がある場合は、手動で設定するplot必要があります (または、@Yann が提案したものと同様の補間されたカラーバーを使用して、各呼び出しで色を指定するだけです)。 .

于 2012-03-17T14:51:44.407 に答える