データの準備
これまでmatplotlibでは2次元データを扱ってきました。
しかし時には3次元データを使うなんてこともあるでしょう。
今回は簡単にですが、3次元データのプロットの仕方を解説していきます。
まずは3次元データの準備をしましょう。
とりあえず、X軸5つ、Y軸5つでZ軸を0−9の値で適当に作ってみました。
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
分かりやすく書くと下のような2次元リストになっています。
1, 2, 3, 4, 5
9, 8, 7, 6, 5
4, 7, 3, 8, 2
1, 9, 4, 6, 3
3, 7, 2, 6, 5
横方向がX軸方向、縦方向がY軸方向、そして数値自体がZ軸方向なります。
これでデータの準備ができました。
それでは3Dプロットしていきましょう!
インポート
今回、インポートするライブラリはいくつかあるので、順に見ていきましょう。
まずはnumpyです。
import numpy as np
いつも通り、numpyをnpとして使えるようにインポートします。
次にmatplotlibです。
from matplotlib import pyplot as plt
こちらもmatplotlibのpyplotをpltとして使えるようにインポートします。
最後に3Dプロット用のライブラリです。
from mpl_toolkits.mplot3d import Axes3D
mpl_toolkits.mplot3dからAxes3Dをインポートします。
さらにマジックコマンドを入れておきましょう。
%matplotlib notebook
これでjupyter notebook上で拡大縮小などできるようになります。
まとめるとこんな感じです。
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib notebook
座標点用の格子列の作成
3Dプロットをするには、格子列というのが必要になります。
3Dプロットなので、X軸、Y軸の場所を決めて、Z軸方向に数値をプロットすることになります。
そこで先ほどのリストのそれぞれの要素が、X軸、Y軸のどこに当たるか決めてやる必要があるということです。
X軸の要素数はリストの中のさらにリストの中の要素数に当たります。
1, 2, 3, 4, 5 ←この要素数(この場合は5)
9, 8, 7, 6, 5
4, 7, 3, 8, 2
1, 9, 4, 6, 3
3, 7, 2, 6, 5
この要素数を取得するには、test_data内のリストのうち、一つのリストを取り、その要素数を取得します。
つまりこんな感じになります。
len(test_data[0])
Y軸の要素数を取得するには、test_dataのリスト内の要素数を取得します。
この要素数を取得
↓
1, 2, 3, 4, 5
9, 8, 7, 6, 5
4, 7, 3, 8, 2
1, 9, 4, 6, 3
3, 7, 2, 6, 5
こちらの方がシンプルで、こんな感じになります。
len(test_data)
その要素数に対し、番号を振るため、np.arange関数を使って、リストを作ります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
print(x)
print(y)
実行結果
[0 1 2 3 4]
[0 1 2 3 4]
それぞれ0から4まで番号を振ることができました。
これを格子列化します。
その場合、np.meshgrid(Xのリスト、Yのリスト)を使います。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
print(X)
print(Y)
実行結果
[[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]]
[[0 0 0 0 0]
[1 1 1 1 1]
[2 2 2 2 2]
[3 3 3 3 3]
[4 4 4 4 4]]
これでそれぞれの座標点を作ることができました。
つまり座標点としては、こんな感じになるわけです。
0-0, 1-0, 2-0, 3-0, 4-0
0-1, 1-1, 2-1, 3-1, 4-1
0-2, 1-2, 2-2, 3-2, 4-2
0-3, 1-3, 2-3, 3-3, 4-3
0-4, 1-4, 2-4, 3-4, 4-4
次はとうとうプロットしていきますよ!
3Dプロットの種類
3Dプロットの方法はいくつかあり、ここでは使いそうなものを紹介していきます。
まず基本的にプロットするには、次の2行が必要です。
fig = plt.figure()
ax = Axes3D(fig)
1行目で図を作り、2行目で3次元グラフであることを指定します。
その後、プロット方法によって、少しずつコマンドが変わってきます。
まずは表面プロット(surface)です。
表面プロットの場合、plot_surface(X軸の格子列, Y軸の格子列, データ)となります。
また図は上の2行のコマンドで、axに渡されているため、ax.plot_surface(X軸の格子列, Y軸の格子列, データ)となります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data))
実行結果
次は散布図モデル。
散布図モデルの場合は、ax.scatter(X軸の格子列, Y軸の格子列, データ)となります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
scat = ax.scatter(X, Y, np.array(test_data))
実行結果
もう一つはワイヤーフレームです。
ワイヤーフレームの場合は、ax.plot_wireframe(X軸の格子列, Y軸の格子列, データ)になります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
wire = ax.plot_wireframe(X, Y, np.array(test_data))
実行結果
タイトル、軸の名称の追加
タイトルを追加するには、ax.set_title(“タイトル”, fontsize=フォントサイズ)となります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data))
ax.set_title("Title", fontsize=25)
実行結果
次は軸の名称を追加します。
それぞれ軸の名称を追加するには、
X軸の名称には、ax.set_xlabel(“X軸の名前”, fontsize=フォントサイズ)
Y軸の名称には、ax.set_ylabel(“Y軸の名前”, fontsize=フォントサイズ)
Z軸の名称には、ax.set_zlabel(“Z軸の名前”, fontsize=フォントサイズ)
となります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data))
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
実行結果
軸の数値のフォントサイズを変更
軸の数値のフォントサイズを変更するには、plt.tick_params(fontsize = フォントサイズ)を追加します。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data))
plt.tick_params(labelsize=20)
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
実行結果
今回はちょっと数値が切れてしまっているので、元のサイズで続けていきます。
カラーバーを追加
Z軸の数値の変化がわかりやすいように、Z軸の数値によって色分けし、横にカラーバーを追加しましょう。
色分けするには、色分け用の色のセット(colormap)を使います。
どんな色があるかというのは、こちらのサイトを見ると分かりやすいです。
今回は”Blues”を用いてみます。
まずはax.plot_surface()の中に、cmap=”Blues”を追加します。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data), cmap="Blues")
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
実行結果
ちょっと回転させていますが、確かに色が変わっています。
あまり綺麗に分かれていないのは、データ量が少ないからでしょう。
今回はこれで勘弁してもらいつつ、カラーバーの表示をしてみましょう。
カラーバーを表示するには、プログラムにfig.colorbar(カラーバーを追加するグラフ)を追加します。
今回、「カラーバーを追加するグラフ」というのは、surfになります。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data), cmap="Blues")
cbar = fig.colorbar(surf)
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
実行結果
このままではカラーバーが上下を突き破ってしまっているので、サイズを調整しましょう。
カラーバーの長さを調節
カラーバーの長さを調節するには、fig.colorbar()にshrink = 比率 を追加します。
この比率というのは、縦の長さを1とした時の長さになります。
個人的には、0.75 (75%)程度がいいんじゃないかなと思います。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data), cmap="Blues")
cbar = fig.colorbar(surf, shrink = 0.75)
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
実行結果
カラーバーの名称を追加
カラーバーの名称を追加するには、カラーバーをcbarに格納しているので、cbar.set_label(“カラーバーの名称”, fontsize=フォントサイズ)とします。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data), cmap="Blues")
cbar = fig.colorbar(surf, shrink = 0.75)
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
cbar.set_label("Color Bar", fontsize=20)
実行結果
カラーバーの数値のサイズを変更
カラーバーの数値のサイズを変更するには、cbar.ax.tick_params(labelsize=フォントサイズ)を追加します。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data), cmap="Blues")
cbar = fig.colorbar(surf, shrink = 0.75)
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
cbar.set_label("Color Bar", fontsize=20)
cbar.ax.tick_params(labelsize=15)
実行結果
カラーバーを水平に変更
最後にカラーバーを3Dプロットの横ではなく、下に移動し、水平にするには、fig.colorbar()にorientation=”horizontal”を追加します。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
%matplotlib notebook
test_data = [[1, 2, 3, 4, 5], [9, 8, 7, 6, 5], [4, 7, 3, 8, 2], [1, 9, 4, 6, 3], [3, 7, 2, 6, 5]]
x = np.arange(len(test_data[0]))
y = np.arange(len(test_data))
X, Y = np.meshgrid(x, y)
fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_surface(X, Y, np.array(test_data), cmap="Blues")
cbar = fig.colorbar(surf, shrink = 0.75, orientation="horizontal")
ax.set_title("Title", fontsize=25)
ax.set_xlabel("X", fontsize=20)
ax.set_ylabel("Y", fontsize=20)
ax.set_zlabel("Z", fontsize=20)
cbar.set_label("Color Bar", fontsize=15)
cbar.ax.tick_params(labelsize=15)
実行結果
見切れていますが、とりあえずこんな感じでカラーバーの方向を変更することができます。
これで3Dグラフも大体のことができるようになったと思います。
是非使ってみてください!
次回は自分で関数を作成するための関数、def関数に関して解説をしていきます。
ということで今回はこんな感じで。
コメント