週末はいつも晴れ

社会人3年目の日記です。プログラミングとか旅行とかラーメン。

matplotlibカラープロット

gnuplotは止めました。
Pythonをメインで使ってるのにmatplotlibを使わないのが
そもそも不自然だったんですけどね。


仕事で3次元のデータ(x, y, zの組)をプロットする機会が多いので、
得たポイントをまとめておきます。

環境はAnacondaです。
外部にネットワークが接続してない環境なので、一発でインストールできるのは助かります。
DOSLINUX両方で使ってますが、今のところ大きな差異は感じません。

自分に必要なことしか調べてないので
網羅的な内容にはなりませんのであしからず。

matplotlibのカラープロット

matplotlibで3次元のデータをカラープロット(コンター図?)にする方法は
おそらく2つあります。

plt.pcolor

※2017.6.18注
plt.pcolormeshまたはpcolorfastまたはplt.imshowでも同様のプロットが可能です。
それぞれ返すオブジェクトが異なるようですが、出来上がるイメージはすべて同じだと思います。
pcolorfastが最も描画速度が速いようです。
pylab_examples example code: pcolor_demo.py — Matplotlib 2.0.2 documentation
f:id:ikarino99:20160706201755p:plain

plt.contour(+plt.contourf)

下の例にもありますが、plt.contourfが塗りつぶし、plt.contourが等高線になります。
pylab_examples example code: contour_demo.py — Matplotlib 2.0.2 documentation
f:id:ikarino99:20160706201801p:plain

#!/usr/bin/env python3
import matplotlib.pyplot as plt
import numpy as np

xs = np.arange(-5, 5, 0.1)
z = np.array([x**2 + y**2 for x in xs for y in xs]).reshape((len(xs), len(xs)))
plt.contourf(xs, xs, z)
# plt.pcolor(xs, xs, z)
plt.colorbar()
plt.show()
# plt.savefig("contouf.png")

plt.pcolorは実直にz軸データを色に変換してプロットする方法。
plt.contour(f)はz軸の値の範囲毎に色を割り当ててプロットする方法。

3次元プロットを利用する場面の多くは
視覚的なイメージを相手に植え付けることが目的で、
具体的な値を示す場面で使うことは無いと思います。

そのため、私は細かい値を気にしないplt.contour(f)をよく使います。
データ数が多いとplt.pcolorはコストがかかることも理由の一つです。


それでは以下でポイントをまとめていきます。

x軸とy軸のスケールを一致させる

横縦軸共に長さのことが多いです。
軸の単位が縦横で違っても、アスペクト比で印象が変わってきますよね。

plt.axes().set_aspect('equal')

アスペクト比を変えるとsavefigのときに白いとこが増えちゃいます。
その解決策

plt.savefig("contouf.png", bbox_inches='tight')

表示するz値の目盛り値を変える

plt.contourfの場合かなり重要。
どこを境目にするかで、印象がぜんぜん違う。
(x, y, )zの次の引数です。

levels = [0, 2, 3, 10, 56]
plt.contourf(xs, xs, z, levels)

f:id:ikarino99:20160706203551p:plain
さっきと同じデータなのに、どうしても中心部分だけに目が行きますよね。
簡単に印象操作できちゃう。これがあるからカラープロットは信頼出来ない。

表示するx,y値の目盛り値を変える(表示の角度を変える)

x軸の目盛りが多すぎて表示できなかったので、90度に変更しました。

z軸の目盛り値をログスケールにする

from matplotlib.color import LogNorm
z = z + 1
plt.contourf(xs, xs, z, norm=LogNorm())

f:id:ikarino99:20160708021927p:plain

番外編:numpy2次元配列(行列)のあれこれ

カラー表示するZ軸の値はnumpy.ndarrayの2次元配列とすると思います。
私がよく使う関数のメモ。

import numpy as np
# 回転系
z = z.T # 転置したい場合
z = np.rot90(z) # 行列を90度回転したい場合
z = np.flipud(z) # 上下逆さま
z = np.fliplr(z) # 左右逆さま
# 数値計算系
z = np.log(z) # ログスケールしたい場合
z = z * 100 # 定数倍したい場合
z = M.dot(z) # 行列Mとの積を計算したい場合