データ分析といえば可視化が大事です。Pythonで可視化ツールというとmatplotlibとかseabornとかbokehとかありますが、ねりんぷろさんの書かれた記事でDash凄いと思ったんで、紹介がてらに発表を作ってみました。 発表は最近もっぱらgitpatchで発表資料作っててテキストしかなくて味気ないんですが、これはgitpitchのせいではなく、私が作りこみが面倒なせいで、gitpitchは実は画像も貼れるしなんでもできます(埋め込んだらでかいな…)。
Dashについて
DashはFlaskとPlotly.jsとReact.jsで動く可視化ツールで、Pythonで書けます。
Plotlyはpythonのライブラリにもあるのですが、IDがいたり、api制限があったりして、書くのが簡単なのですが使うのがめんどくさかったのですが、Dashには多分それがないということで便利です。あと最近のブームなのか、ウェブブラウザで見られる。jupyterなんかで書いていると、別画面で開くのめんどくさいなってなるけど、アプリとして作れるのはめちゃくちゃ良いと思います。
凄みはサンプル見たらわかるということで、勉強会でもサンプルを見せようとしたのだけれど、テザリング環境が悪くて見せることができませんでした。
下のリンクだと脳みそがぐるぐる動いたり(下のリンクはサンプルコード)、 http://brain-surface-viewer.herokuapp.com/
https://github.com/plotly/dash-brain-surface-viewer
この下のやつだったら化学式が見られたり、何かとDashの凄みが感じられます。
https://dash-drug-explorer.plot.ly/
https://github.com/plotly/dash-drug-discovery-demo/
使い方
Dashではdash、dash_core_components、dash_html_componentsの3つを使います。
それぞれの役割は、
dash / 箱作り。
dash_core_components / グラフを作る。
dash_html_components / html部分を作る。
という感じになっております。Getting Startedの最初の例を見ると
# -*- coding: utf-8 -*- import dash import dash_core_components as dcc import dash_html_components as html external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] # appを作る app = dash.Dash(__name__, external_stylesheets=external_stylesheets) # appのレイアウトを作る。 app.layout = html.Div(children=[ html.H1(children='Hello Dash'), html.Div(children=''' Dash: A web application framework for Python. '''), dcc.Graph( id='example-graph', figure={ 'data': [ {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'}, {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}, ], 'layout': { 'title': 'Dash Data Visualization' } } ) ]) # アプリを動かす。 if __name__ == '__main__': app.run_server(debug=True)
てな感じです。すると下のページの最初のグラフができます。
リアルタイムグラフ
コールバックのところは相変わらずよく分からないですが、とりあえずidを指定して、component_propertyのところにvalueかfigureかchildrenを入れて動いたら良し、間違っていたら間違っているとエラーを吐いてくれるので、それに合わせるという感じで動かしています。
ちょっと調べたところ、プロパティってのはjsっぽい概念らしいがjsは全く分からないので引き返しました。
で、今回はリアルタイムのグラフを動かしてみることにしました。Dashのサイトにもリアルタイムのグラフがあるので、それを見本に、時間を使って動くようなものを作りました。
お手本にしたのは下のリンク先にあるものです。dcc.Intervalというモジュールを使って、何秒おきに動くという設定を行うと、その設定毎にグラフをアップデートしてくれます。
ここの事例では、現在の時間から前のデータを作って返すということをやっていました。 下の部分ですね。
# Collect some data for i in range(180): time = datetime.datetime.now() - datetime.timedelta(seconds=i*20) lon, lat, alt = satellite.get_lonlatalt( time ) data['Longitude'].append(lon) data['Latitude'].append(lat) data['Altitude'].append(alt) data['time'].append(time)
こんな感じでリアルタイムのデータは最初の一個で、その前のデータは前の時間を作ってデータを作ってってことをやっています。
これはいろんなところから見られる場合、データを蓄積する形で作っていると、安定したデータが作れないから表示したいグラフが出ないみたいなことが起こるからです。
データの呼び出しの説明みたいなところでもそんな話があったのですが、「コールバックを使うと時にデータを呼び出す場合、グローバルで呼び出してね。でないと、他の人が呼び出している状態でほかの人の表示が行われるんでねー」みたいなことが書いています。
複数人で使うことが前提の場合、そんなことも考えないとだめですねー。
しかし、今回はとりあえずリアルタイムでグラフが動くということを見せたかったので、関数の中でcsvを読み込んで、リアルタイムのデータを足して、それをグラフにするというものを作りました。最初に見せたときはcsvがからの状態でなかったので、変なグラフになっていたのですが、csv消したらいいよと突っ込みを入れてもらってあっそうだったという感じで消したらちゃんと動いた。発表慣れしてて、予行演習しててもそれが足を引っ張ってちょっとてんぱる場合もあるのだなぁと、今は反省しており今後に生かせればと思います。
コードはgithubのtest3-5.pyにあります。 当日の朝、頑張ってとにかく動くように作ったので、ちょっと駄目なところも多いと思いますが・・・
終わりに
でかいデータでも一気に読み込まないといけないのかって質問があったけど、どうなのかなぁ。でかいsqlのデータがあってここからここまで見たいなことはできると思うのだけど、そういうデータを扱ったことがないので、ちょっと調べてみたい。というか、いつもpandasで全部読み込んでみたいな感じで操作しているので、あまり考えの中に入っていなかった。勉強会で発表すると考えても見ないことが質問されて面白いなーと思うと同時に、そんな感じのデータをどう弄るかもちょっと試してみたい。
はんなりPythonは毎月第三金曜日に京都で開催されています。内容は発表があったり、問題を解いたり、色々です。次回は何をやるんだろうなー。