9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

python製データ可視化ツール Dashを触ってみた所感

Posted at

はじめに

データ収集をpython、pandasで行うProjectを進めているのですが、
python製のダッシュボード作成ツールを探していたところdashにたどり着いた。
以下はdash検証とサンプル作成時に得た知見のまとめと備忘録

Dashとは

plotly謹製のwebアプリケーション作成ツール
Flaskを元にしており、pythonで書くとReact.jsに変換される
https://plot.ly/dash/

データをグラフィカルに表示するコンポーネントが多数用意されており、
用意にデータが可視化できるところが特徴
例)
https://dash-gallery.plotly.host/Portal/

Html Elements

app.layout = html.Div(children=[
  html.H1(id='elm1', className='hoge' children=[]),
  #略
  html.Div(id='elm2', className='hoge' children=[]),
]

htmlコンポーネントが用意されており、
https://dash.plot.ly/dash-html-components
app.layoutに渡すことで描画される。

構造が入れ子になるとchildren=に入れた子要素のchildrenにさらに子要素を...
といった形で複雑化しそうなので部分部分でコンポーネントした方が良いかも

部分的に静的なhtmlであれば、


import dash_core_components as dcc

dcc.Markdown('''

# 見出し
## 見出し2
本文
''')  

マークダウンも記述できるのでこちらを使った方が良さそう
https://dash.plot.ly/dash-core-components/markdown

Graphs

dcc.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'},
        ],

Graphコンポーネントに値を渡すことで棒グラフを簡単に作成できる

import pandas as pd

dataframe = pd.read_csv('url')

dash_table.DataTable(
    id='table',
    columns=[ {"name": i, "id": i} for i in dataframe.columns],
    hidden_columns=[],
    row_selectable="single",
    data=dataframe.to_dict('records'),
),

dictionaryやpandasのdataframeから表を作成できる

Callback


@app.callback(
    Output('table', 'data'),
    [Input('region-dropdown', 'value')])
def update_table(value):
    return df.query('市区町村名 == @value').to_dict('records')

UIパーツのInputとOutputを紐付けすることでUIコールバックが発火できる。

UIパーツをが必要不可欠

UIパーツを紐づけるというところが肝で、


#app.layout
dcc.Location(id='location', refresh=False),
   

@app.callback(
    [Output('hoge', 'value1'),
    Input('location', 'pathname')])
def pass_change(value1, pathname):

urlパスの変化を受け取るのにもdcc.LocationというUIパーツを置いて
そのコールバックとして変化値を受け取らなければならない

Outputは1つだけの法則

Dashにおいて、callbackのoutputは一つだけに限定される


@app.callback(
    Output('hoge', 'children'),
    Input('fuga', 'value2'))
def func(value2):

@app.callback(
    Output('hoge', 'children'),
    [Input('fuga', 'value'),
     Input('hoyo', 'value')
   ])
def func(value1, value2):

上記のように、hogeをoutputとするcallbackが重複していた場合、

DuplicateCallbackOutput
You have already assigned a callback to the output
An output can only havea single callback function.

上記のように怒られてしまう。

Outputに対してInputをまとめていく必要があるが、Inputに対して別のOutputも処理したい
ような場合もあるので、設計をうまくやらないと

@app.callback(
    [Output('hoge', 'children'),
     Output('hoge', 'children'),
     Output('hoge', 'children'),
     Output('hoge', 'children'),
     Output('hoge', 'children'),
     ],
    [Input('fuga1', 'value'),
     Input('fuga2', 'value'),
     Input('fuga3', 'value'),
     Input('fuga4', 'value'),
     Input('fuga5', 'value'),
   ])

多数のInputに対して多数のOutputが集まった巨大なCallbackになってしまうので注意が必要

ButtonのCallback

buttonのclickイベントを取れないか調査したところ、
過去にはEventクラスがあったが現在はremoveされているとのこと。

buttonクラスのpropertyにはn_clicksというものがあり、
公式の例を見るとボタンを押すたびにn_clicksが増えていく
https://dash.plot.ly/dash-core-components/button

全てのボタンのn_clicksをキャッシュしないと押されたことが分からないのは辛い
ということでpropertyを探すとn_clicks_timestampというものがあったため、
以下のようにtimestampと現在の時刻を比較してclick判定を行なっている


@app.callback(
    Output('hoge', 'children'),
    Input('close-button', 'n_clicks_timestamp')])
def click(n_clicks_timestamp):
    if n_clicks_timestamp != None:
        if (time.time() * 1000 - n_clicks_timestamp) < 1000:
            return something

これが本当に正しいやり方なのかイマイチ自信が持てないので、
Dashに詳しい人教えてください

所感

使用感に多少の癖はあるが、表やグラフが非常に少ないコード量で記述できるのは魅力的
今回挙げたconsについても、解決法があれば順次追記していきたい。

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?