今回はmatplotlibで等高線グラフを描画する方法を紹介します。等高線は地図ではお馴染みですが、グラフとしてデータの可視化にも使えます。
今回はデータの可視化における等高線の持つ意味についてと、Pythonのmatplotlibで等高線グラフを描画する方法を紹介していきます。
等高線グラフについて
等高線グラフは3次元のデータを可視化することができます。等高線とは文字通り、同じ値の箇所を線で結んだものになります。
X軸の情報、Y軸の情報および高さの情報(Z軸)を保持します。高さは、上の図の場合は円の内側に行けば行くほど値が大きくなっています。今回matplotlibで描画する等高線グラフは2次元のグラフですが、3次元で表現した等高線グラフも存在します(Excelとかだと一般的?)。
Pythonで等高線グラフを描画する
それでは、実際にPythonで等高線グラフを描画していきます。
データの用意
まずはグラフを描画するためのサンプルデータを用意していきます。
x, y
きれいな楕円の等高線を描画するために、等差数列の格子列を生成します。
import numpy as np
#等差数列を作成
x_base = np.linspace(-3,3,3)
y_base = np.linspace(-3,3,3)
格子列を作成
x, y = np.meshgrid(x_base, y_base)
ここで、xとyは以下のような値です。
print(x)
#array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
print(y)
#array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
z
zには以下の値を設定することとします。きれいな楕円のグラフを描画するためのおまじないです。
z = x ** 2 + y ** 2 + x * y
値は以下のようになりました。
print(z)
#array([[27. , 20.8125, 15.75 , 11.8125, 9. , 7.3125, 6.75 ,
7.3125, 9. ],
[20.8125, 15.1875, 10.6875, 7.3125, 5.0625, 3.9375, 3.9375,
5.0625, 7.3125],
[15.75 , 10.6875, 6.75 , 3.9375, 2.25 , 1.6875, 2.25 ,
3.9375, 6.75 ],
[11.8125, 7.3125, 3.9375, 1.6875, 0.5625, 0.5625, 1.6875,
3.9375, 7.3125],
[ 9. , 5.0625, 2.25 , 0.5625, 0. , 0.5625, 2.25 ,
5.0625, 9. ],
[ 7.3125, 3.9375, 1.6875, 0.5625, 0.5625, 1.6875, 3.9375,
7.3125, 11.8125],
[ 6.75 , 3.9375, 2.25 , 1.6875, 2.25 , 3.9375, 6.75 ,
10.6875, 15.75 ],
[ 7.3125, 5.0625, 3.9375, 3.9375, 5.0625, 7.3125, 10.6875,
15.1875, 20.8125],
[ 9. , 7.3125, 6.75 , 7.3125, 9. , 11.8125, 15.75 ,
20.8125, 27. ]])
グラフの描画
データを準備したところで、等高線グラフを描画していきます。描画にはmatplotlibのcontour()を用います。
contour(x, y, z, levels)
x、y、zは各軸のデータ、levelsは等高線の数と位置を指定します(後述)。コードは以下の通りになります。
fig, ax = plt.subplots()
ax.contour(x, y, z, levels=5)
plt.show()
これで次のようなグラフが出力されます。
あれ、等高線のわりになんかカクカクしてるな?と思いますよね。これは、x、yの要素数が少ないためです。上図はx、yが3×3の配列ですが、200×200に増やすと以下のように滑らかになります。
levelsについて
levelsには等高線の数および等高線を引く値を指定します。公式によると、levelsの説明および指定方法は次の通りです。
Determines the number and positions of the contour lines / regions.
If an int n, use
MaxNLocator
, which tries to automatically choose no more than n+1 “nice” contour levels between vmin and vmax.If array-like, draw contour lines at the specified levels. The values must be in increasing order.
整数を指定すると、指定した数+1までのなかでイケてる等高線を引いてくれるみたいです(笑)上の例ではlevelsに5に設定したので、線の数は5になっています(図では切れてますが色で判断)。
配列を指定すると、配列の要素数の数だけ線が引かれ、各要素の値のところに線が引かれます。また、配列の要素の値は後ろにいくほど大きくなくてはいけません。
例えば、levelsを以下のように指定してみます。
levels = np.linspace(np.min(z), np.max(z), 10)
print(levels)
#[2.27266988e-04 3.00020202e+00 6.00017676e+00 9.00015151e+00
1.20001263e+01 1.50001010e+01 1.80000758e+01 2.10000505e+01
2.40000253e+01 2.70000000e+01]
この場合、zの最小値と最大値の間を10等分したときの値を配列で保持しています。これを使って等高線を書いてみます。
先ほどの例よりも線の数が増えました。8本しか描かれていませんが、あとの2本は描画範囲外にいるのでしょうか?
Pythonでデータサイエンスするなら
Pythonでデータサイエンスをするなら、以下の書籍がおすすめです。Pandas、matplotlib、Numpy、scikit-learnといったデータサイエンスに必要なライブラリを、体系立てて一通り学ぶことができます。
ややお値段高めですが、これ1冊で十分という内容・ボリュームなので、損はしないと思います^^
まとめ
Pythonで等高線グラフを描画する方法を紹介しました。描画に必要なデータの形が若干ややこしいですが、データのピークを見つけたりするのに適しています。
可視化方法として等高線グラフを使えるようになれば中~上級者ですね?!
ではでは👋