こんにちは!最近絶賛社内ニート中のあしぺんです。
今回は前回に続きpythonで3Dグラフ書いたときのメモ書きです。今回使ったのはPlotlyという可視化ライブラリで、htmlも作れちゃうのでWEBで見られるのが魅力的です。RとかJuliaでもあるみたいなので、幅広く使えそうです。
3Dグラフのhtml出力
いろんなサイト(参考サイトに記載しておきます)に情報があるのですが、自分の表現したいグラフにするのに時間かかっちゃいましたので、コードをどどんと記載しておきます。正直まだまだ詳細は理解していない部分も多いです。同じようなグラフが書きたい人の参考になれば嬉しいです。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
#jupyter lab Python3.8.11 import pandas as pd import plotly import plotly.graph_objs as go import plotly.figure_factory as ff import plotly.offline as offline import numpy as np # パラメータ分割数 n = 128 # パラメータtを作成 t = np.linspace(-6*np.pi, 6*np.pi, n)#等差数列 # 螺旋構造の座標 x1 = (0.05*(t+6*np.pi)+1.)*np.cos(t) y1 = (0.05*(t+6*np.pi)+1.)*np.sin(t) z1 = t x2 = (0.05*(t+6*np.pi)+1.)*np.cos(t+np.pi*0.5) y2 = (0.05*(t+6*np.pi)+1.)*np.sin(t+np.pi*0.5) z2 = t x3 = (0.05*(t+6*np.pi)+1.)*np.cos(t+np.pi) y3 = (0.05*(t+6*np.pi)+1.)*np.sin(t+np.pi) z3 = t x4 = (0.05*(t+6*np.pi)+1.)*np.cos(t+np.pi*1.5) y4 = (0.05*(t+6*np.pi)+1.)*np.sin(t+np.pi*1.5) z4 = t x5 = np.cos(t) y5 = np.sin(t) z5 = -6*np.pi + t*0. # ラベル d_time = np.array([str(x)+"step" for x in range(n)], dtype='O') #スライダーの設定 sliders = [dict( steps = [dict( method = 'animate' , args = [ [ risk_rate ] , dict( mode = 'immediate' , frame = dict( duration=10 ,redraw=True ) , transition = dict( duration=0 ) ) ] , label= risk_rate ) for risk_rate in d_time ]#ラベルを設定 , transition = dict( duration = 0 ) , x = 0 , y = 0 , currentvalue = dict( font = dict(size=12) , prefix = '' , visible = True , xanchor = 'center' ) , len=1.0 )] #アップデートの設定 updatemenus = [dict( type = 'buttons' , showactive = False , y = 1 , x = -0.05 , xanchor = 'right' , yanchor = 'top' , pad = dict( t=0, r=10 ) , buttons = [dict( label = 'Play'# 再生ボタン , method = 'animate' , args = [ None , dict( frame = dict( duration=10 , redraw=True ) #再生の速度 , transition = dict( duration=0 ) #このdurationはよくわからない , fromcurrent = True , mode = 'immediate' )] ) , dict(args=[[None],dict(mode="immediate",frame=dict(redraw=True))], label = "Pause", method = "animate") ] )] #レイアウトの設定 layout = go.Layout( title = 'テストグラフ'#タイトル , template = 'ggplot2' , autosize = False , width = 1000 , height = 800 , scene = dict( aspectmode = "manual" , aspectratio = dict(x=1 ,y=1 ,z=1) #アスペクト比 , xaxis = dict(range=[-4, 4] ,title="x方向") #x軸の範囲 , yaxis = dict(range=[-4, 4] ,title="y方向") #y軸の範囲 , zaxis = dict(range=[-20, 20] ,title="z方向") #z軸の範囲 , camera = dict(eye=dict(x=1.5 ,y=.9 ,z=.7)) ) #カメラの角度 #, font = dict(color="#fff") , updatemenus = updatemenus #上で設定したアップデートを設置 , sliders = sliders #上で設定したスライダーを設置 ) #data(初期) scatter1_0 = go.Scatter3d(x=[x1[0],x2[0],x3[0],x4[0],x1[0]], y=[y1[0],y2[0],y3[0],y4[0],y1[0]], z=[z1[0],z2[0],z3[0],z4[0],z1[0]], mode='lines', line=dict(color="red", width=2), name="赤") scatter2_0 = go.Scatter3d(x=[x1[0],x2[0],x3[0],x4[0],x1[0]], y=[y1[0],y2[0],y3[0],y4[0],y1[0]], z=[z1[0],z2[0],z3[0],z4[0],z1[0]], mode='lines', line=dict(color="green", width=2), name="緑") line_0_0 = go.Scatter3d(x=[x1[0],x2[0],x3[0],x4[0],x1[0]], y=[y1[0],y2[0],y3[0],y4[0],y1[0]], z=[z1[0],z2[0],z3[0],z4[0],z1[0]], mode='lines', line=dict(color="blue", width=2), name="螺旋") line_0 = go.Scatter3d(x=x5, y=y5, z=z5, mode='lines', line=dict(color="blue", width=2), name="初期円") #!!!!!!!!!上記のうち上3つはのちのちframesで上書きされるので初期条件残したい場合はframesのデータ数プラスαで記述しておく・・・たぶん data = [scatter1_0,scatter2_0,line_0_0,line_0] #frame(時刻で変化するもの) frames = [] for k in range(len(x1)): scatter1 = go.Scatter3d(x=x1[:k], y=y1[:k], z=z1[:k], mode='lines+markers', marker=dict(size=2.5, color='red'), line=dict(color="red", width=2), text =d_time[k] ) scatter2 = go.Scatter3d(x=x3[:k], y=y3[:k], z=z3[:k], mode='lines+markers', marker=dict(size=2.5, color='green'), line=dict(color="green", width=2), text =d_time[k] ) line_k = go.Surface(x=[x1[:k],x3[:k]], y=[y1[:k],y3[:k]], z=[z1[:k],z3[:k]],cmin=-20,cmax=20,showscale=False) data_k = [scatter1,scatter2,line_k] frames.append( dict( data = data_k , name = d_time[k] ) ) fig = dict( data=data ,layout=layout ,frames=frames ) offline.plot(fig, filename='Tornado.html') |
一番悩んだのはデータを更新する部分とずっと残しておきたい部分があったことです。frameで時刻変化するデータが3データあるので、初期段階でその3データ+残しておきたいデータを作っておけば、前の3データだけ更新されることに気づきました。あってるのか?まあ思ったとおりに動いたので良いとしよう!できたのを以下に載せておきます。グラフのサイズが合ってないのが気になる。
まとめ
今回はPlotlyを使ってグラフを可視化しました!めっちゃ苦労したので、残しておきたいという気持ちで記載しました。もうちょっと見栄え良くしたいですね。
コメント