【Python】値の組み合わせ辞書からワイヤーフレームの三次元プロットを描画する

 Pythonは多くのライブラリを抱えている言語です。そのライブラリの中で人気の一つが matplotlib です。これはMatlabのプロット機能同然の機能を提供する描画ライブラリです。これを用いると次の様に三次元プロットを作ることができます。
 mplot3d tutorial — Matplotlib 2.0.2 documentationl#wireframe-plots

# @see https://qiita.com/sci_Haru/items/ae54f90e53ccc959d3cb [Pythonによる科学・技術計算] 3次元曲面の描画,サーフェス,ワイヤーフレーム,可視化,matplotlib

from mpl_toolkits.mplot3d import Axes3D   
import matplotlib.pyplot as plt 
import numpy as np

fig = plt.figure() #プロット領域の作成
ax = fig.gca(projection='3d') #プロット中の軸の取得。gca は"Get Current Axes" の略。

x = np.arange(-2, 2, 0.05) # x点として[-2, 2]まで0.05刻みでサンプル
y = np.arange(-2, 2, 0.05)  # y点として[-2, 2]まで0.05刻みでサンプル
x, y = np.meshgrid(x, y)  # 上述のサンプリング点(x,y)を使ったメッシュ生成

z = np.exp(-(x**2 + y**2))  #exp(-(x^2+y^2))  を計算してzz座標へ格納する。
ax.set_zlim(0.0,1.0)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

ax.plot_wireframe(x, y, z, color='blue',linewidth=0.3) # ワイヤーフレームのプロット。linewidthは曲面のメッシュの線の太さ,をそれぞれ表す。

plt.show() # 絵の出力。


 上の様なすぐに使えるサンプルコードは多く転がっているのですが、大体その場で z = f(x,y) な式を使っています。この記事ではあらかじめ外部で計算した三軸の値から三次元プロットをする方法を紹介します。
 ここで考えるデータは次の様なx, y, zについての各値の組み合わせが網羅されたデータです。

x,y,z
1,1,110
1,2,120
1,3,130
2,1,210
...
3,3,330

 これを次の関数に入れることで実現できます。重要なのはユニークな二軸を元に numpy.meshgrid 関数でメッシュを作ることとメッシュに対応する二次元データを作り numpy.array 関数で科学技術計算向けの配列にすることです。numpy は科学計算向けにPython自体や他言語ともなかなか離れたところにありますが、ドキュメントを読んでうまいこと変換をかませば案外融通がききます。

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

_data = '上のデータを二次元リスト化したもの' # Array<Array<number>>

def wireframe_plot(xidx=0, yidx=1, zidx=2, xlabel='x', ylabel='y', zlabel='z',
                   title=''):
    # x軸、y軸についてのメッシュ(平面の格子になる部分)である二次元データを生成
    xuniq = sorted(list(set(list(map(lambda x: x[xidx], _data)))))
    yuniq = sorted(list(set(list(map(lambda x: x[yidx], _data)))))
    X, Y = np.meshgrid(xuniq, yuniq)
    
    # z軸の辞書を作成。一々探索を走らせると本当に時間がかかるので全てマッピングしておく
    zDict = dict()
    for row in _data:
       # x, y の値に対応する z の値
        zDict[(row[xidx], row[yidx])] = row[zidx]
    # メッシュ中の各部分に対応する値の入った二次元データを生成
    Z = [] # Array<Array<number>>
    for yUniqIdx, y in enumerate(yuniq):
        Z.append([])
        for xUniqIdx, x in enumerate(xuniq):
            Z[yUniqIdx].append(zDict[(x, y)])
    Z = np.array(Z)
    # 描画
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.set_xlabel(xlabel, fontname="MS Gothic")
    ax.set_ylabel(ylabel, fontname="MS Gothic")
    ax.set_zlabel(zlabel, fontname="MS Gothic")
    ax.set_title(title, fontname="MS Gothic")
    ax.plot_wireframe(X, Y, Z)
    plt.show()

if __name__ == '__main__':
    wireframe_plot()

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG