2012年4月7日土曜日

matplotlib の散布図でグラデーションをかける方法

よく使われている Python の数式処理用ライブラリに NumPy, SciPy があります。そして、これらを使って得た結果をプロットするのに matplotlib が利用されます。これらはどれもフリーかつ多機能ので色々便利です(しかも Python らしからぬ速さ)。グラフを描画するのには gnuplot を使う人も多いと思いますが、今回は matplotlib に話を限ります。

統計をやっていたりすると散布図を描く必要が出てくるのですが、その中でも特にデータの順番をグラフィカルに表すため各データ点の色にグラデーションをかけてプロットしたくなることがあります。matplotlib を使ってこれを達成するにはどうすればいいか、というのが本エントリのお題です。まずは以下のスクリプトをご覧ください。
# colordemo.py by hidehideta
# -*- coding: utf-8 -*-

from pylab import *
import numpy as np

N = 100
theta =  2 * np.pi * np.linspace(0, 1, N)
figure(figsize=(6, 6))
xlabel("x"); ylabel("y")

x1 = 0.5 * np.cos(theta) ** 3
y1 = 0.5 * np.sin(theta) ** 3
color1 = np.linspace(0, 1, N)
scatter(x1, y1, c=color1)

x2 = 2 * np.cos(theta) ** 3
y2 = 2 * np.sin(theta) ** 3
M = (np.array([1, -1, 1, 1]) / np.sqrt(2)).reshape((2, 2))
x2, y2 = M.dot([x2, y2])

color2 = np.zeros((N, 4))
#color2[::, 0] = [i / float(N) for i in range(N)] # R
color2[::, 1] = [i / float(N) for i in range(N)] # G
color2[::, 2] = [i / float(N) for i in range(N)] # B
color2[::, 3] = [1 for i in range(N)] # A: 0...1 <-> 透明...不透明
scatter(x2, y2, c=color2)

savefig("colordemo.png")
scatter() は c= の形で色を指定する文字もしくは array を受けとることができます。特に array を与える場合はプロットするデータと同じ長さにしておく必要があって、しかも各要素の値は 0 から 1 までの範囲に限られています(255 とか入れるとエラーになる)。
上のスクリプトでいうと color1 が 0 から 1 までの N 点であり、図の内側のアステロイドに対応します。この場合は青から赤に向かって自動的にグラデーションをかけてくれます。
color2 は (N, 4) 行列で、各行が RGBA を指定しています。つまり、長さが N で各要素が RGBA の4成分に対応するリストということです。上の例だと G と B を同時に 0 から 1 まで増やし、かつ α 値を 1 に保っているので徐々にシアンが鮮やかになっていきます(こちらは反時計回りに 45 度回転したアステロイドで、右上の頂点がスタート)。

特にグラデーションにこだわりがないのなら上の color1 を使えばいいでしょうし、好みの配色にしたいのなら color2 を使って RGBA を自分で決めれば OK です。同じく頻繁に使う plot メソッドで color=array とするとエラーが出るので、またこっちの場合についても分かったら記事にするかもしれません。

参考 URL: http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.scatter

0 件のコメント:

コメントを投稿