手元のデータを3次元グラフにして、マウスでグリグリと色んな方向から見たい時ってありませんか?
C#とかVB.NETなどで同じことをする場合は結構ハードルが高く、有料のライブラリを購入するか、あるいは単体の3Dグラフ表示ツールにCSV経由でデータを流し込むくらいしか方法がありません。
しかし、Pythonのmatplotlib を使うと、これが簡単にできてしまいます。
今回は、その方法について解説したいと思います。
matplotlib による3Dグラフの表示
pythonでは、matplotlib と mpl_toolkits というライブラリを組み合わせることで、下記のような3Dグラフを簡単に描くことが出来ます。
ちなみに、左ボタンを押しながらマウスを移動すると図形を見る角度が変化し、右ボタンを押しながらマウスを移動すると図を拡大/縮小することが出来ます。
matplotについて詳細が知りたい方は、こちらの記事をご覧ください。
今回は Visual Studio Code とAnaconda Prompt 、Juypter Notebook で動作を確認しております。
一番簡単な3Dグラフの描き方
まず最初に、matplotlib からは plt を、mpl_toolkits からは Axes3D をインポートする必要があるので、次の2行を記述しておきます。
1 2 |
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D |
実際に3Dグラフを描くための手順は次のようになります。
add_subplot メソッドの引数で projection='3d' を指定するところがポイントです。
下記フローは散布図の例ですが、scatter メソッド以外にも局面を描画する plot_surface メソッドや、ワイヤーフレームを描画する plot_wireframe などが用意されています。
一番簡単な3Dプロットのサンプルは次の様になります。
ちなみに、3Dプロットを計算するために numpy を使っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np #描画エリアの作成 fig = plt.figure() ax = fig.add_subplot(projection='3d') #numpyを使ってXYZの値を設定 x = np.random.rand(200,1) y = np.random.rand(200,1) z = np.random.rand(200,1) #散布図の作成 ax.scatter(x,y,z,s=40,c="red") #描画 plt.show() |
上記プログラムを実行すると、下記の3Dプロットが表示されます。
jupyter Notebook でグリグリ回したい場合は、プログラムの先頭に次の1行を追加して下さい。
1 |
%matplotlib notebook |
3Dグラフに日本語タイトルを表示する
日本語タイトルを表示するには、matplotlib が対応している日本語フォントを指定する必要があります。
下記の1行を記述することで、matplotlibの初期フォントを変更することが出来ます。
今回は、'Meiryo'を指定しました。
1 2 |
#タイトルで漢字が使えるようフォントを設定 plt.rcParams['font.family'] = 'Meiryo' |
グラフ全体のタイトルは set_title メソッド、X,Y,Z軸のタイトルはそれぞれ set_xlabel、set_ylabel、set_zlabelを使いますが、この辺の設定は2Dグラフと同様です。
これらを含めて散布図の3Dグラフを描き直すと次の様になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np #タイトルで漢字が使えるようフォントを設定 plt.rcParams['font.family'] = 'Meiryo' #描画エリアの作成 fig = plt.figure() ax = fig.add_subplot(projection='3d') #グラフタイトルを設定 ax.set_title("3D散布図",size=20) #軸ラベルのサイズと色を設定 ax.set_xlabel("x軸",size=15,color="black") ax.set_ylabel("y軸",size=15,color="black") ax.set_zlabel("z軸",size=15,color="black") #numpyを使ってXYZの値を設定 x = np.random.rand(200,1) y = np.random.rand(200,1) z = np.random.rand(200,1) #散布図の作成 ax.scatter(x,y,z,s=40,c="red") #描画 plt.show() |
実行した結果、次のグラフが表示されます。
ドットで3Dグラフを描く(scatter)
これは散布図を描く方法と同じで scatter メソッドに渡す値を変えただけです。
プログラムは次の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np #タイトルで漢字が使えるようフォントを設定 plt.rcParams['font.family'] = 'Meiryo' #描画エリアの作成 fig = plt.figure() ax = fig.add_subplot(projection='3d') #グラフタイトルを設定 ax.set_title("3D散布図",size=20) #軸ラベルのサイズと色を設定 ax.set_xlabel("x軸",size=15,color="black") ax.set_ylabel("y軸",size=15,color="black") ax.set_zlabel("z軸",size=15,color="black") #x,yデータの作成 data = np.linspace(-3*np.pi,3*np.pi,50) x, y = np.meshgrid(data,data) # zデータの作成 z = np.cos(x/np.pi)*np.sin(y/np.pi) #散布図の作成 ax.scatter(x,y,z,s=1,c="red") #描画 plt.show() |
ワイヤーフレームで3Dグラフを描く(plot_wireframe)
ワイヤーフレームでグラフを描くには plot_wireframe メソッドを使います。
先ほどの「 ドットで3Dグラフを描く 」の scatter の行を次の様に書き換える事でワイヤーフレームでの描画が可能です。
1 2 |
#ワイヤーフレームを描く ax.plot_wireframe(x,y,z,color="darkblue") |
曲面で3Dブラフを描く(plot_surface)
曲面でグラフを描く場合は、 plot_surface メソッドを使います。
「 ドットで3Dグラフを描く 」の scatter の行を次の様に書き換える事で、曲面を使った滑らかな描画が可能です。
1 2 |
#曲面を描画 ax.plot_surface(x,y,z,cmap="winter") |
底面に等高線を描く(contour)
グラフの底面に等高線を引くことも可能で、 contour メソッドを使います。
「 ドットで3Dグラフを描く 」の scatter の行を次の様に書き換える事で、底面に等高線を引くことが出来ます。
1 2 |
#底面に等高線を描画 ax.contour(x,y,z,colors="black",offset=-1) |
ドットと局面と等高線を組み合わせる
曲面の頂点にドットを描いて、且つ等高線を引いてみます。
グラフは順番に描画されますので、曲面を描いてから散布図を描くようにします。
もし逆にすると曲面で散布図がかき消されてしまいます。
「 ドットで3Dグラフを描く 」の scatter の行を次の様に書き換える事で、曲面とドットと等高線を同時に描くことが出来ます。
1 2 3 4 5 6 7 8 |
#曲面を描画 ax.plot_surface(X, Y, Z, cmap = "winter") #散布図の作成 ax.scatter(X, Y, Z, s=5, c = "red") #底面に等高線を描画 ax.contour(X, Y, Z, colors = "black", offset = -1) |
3D空間に線を描く(plot)
3Dグラフにもplot メソッドが用意されており、x,y,z の値を使って3次元空間に線を引くことが出来ます。
これ個までに紹介したグラフのデータをplot に渡しても線が引けないので、データ作成部分も変更しています。
下記を丸ごとコピーして実行すると、上記のグラフが表示できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np #タイトルで漢字が使えるようフォントを設定 plt.rcParams['font.family'] = 'Meiryo' #描画エリアの作成 fig = plt.figure() ax = fig.add_subplot(projection='3d') #グラフタイトルを設定 ax.set_title("3D散布図",size=20) #軸ラベルのサイズと色を設定 ax.set_xlabel("x軸",size=15,color="black") ax.set_ylabel("y軸",size=15,color="black") ax.set_zlabel("z軸",size=15,color="black") #x,y,z のデータを作成 z = np.linspace(-3*np.pi, 3*np.pi, 100) x = np.sin(z) y = x ** 2 #散布図の作成 ax.plot(x,y,z,c="red") #描画 plt.show() |
まとめ
今回は matplotlib を使って3Dグラフを描画する方法を解説しました。
python のグラフ描画機能は非常に強力で、マウスでグリグリ回せる3Dグラフを簡単に作成することが出来ます。
ドットでの描画、曲面での描画、ワイヤーフレーム、折れ線、等高線を引くことが可能で、それらを同時に重ね合わせることも出来ます。
もし3Dグラフでグリグリしたくなったら、是非この記事を活用して下さい。
コメント