Pythonの可視化ライブラリDashを使う　2　Callbackをみる

この記事はPythonの[可視化ライブラリDashを使う 1](https://qiita.com/OgawaHideyuki/items/6df65fbbc688f52eb82c)の続きです。

## Callbackをみる、その前に（Dashのバージョンを上げる）
Callbackの機能を見る前に、バージョン古すぎ問題を何とかします（Pythonのバージョンは上げません。Dashだけですw）。

```console
$ pip install --upgrade dash
---中略
Successfully installed dash-0.39.0 dash-core-components-0.44.0 dash-html-components-0.14.0 dash-renderer-0.20.0 dash-table-3.6.0
```

Dashをアップグレードするだけで他のものもアップグレードされました。

利用ライブラリのバージョン情報
Python 3.6.5
Dash 0.39.0
dash-core-components 0.44.0
dash-html-components 0.14.0
plotly 3.7.0
pandas 0.24.1

## Callbackをみる、その前に2（読み込むデータの形、long-form データ、整然データ）
最近の可視化ライブラリを見ていると読み込むデータの形がちょっと変わっているなと思いました。主催する[はんなりPython](https://hannari-python.connpass.com/)でも（月一回京都で行っているPythonの勉強会です！是非ご参加ください。）話題になったのですが、人間の読みやすい形と機械が読みやすい形があるとのことです。機械が読みやすいデータはlong-form データとか整然データと呼ばれ、その形のデータを使います。

私がそれを知ったのはDashのハンズオンを作っているときに、ドキュメントにあるサンプル作品のデータが、これまで私が扱ってきたのと違うなぁということを感じたときでした。その後、他の良い可視化ライブラリであるAltairのドキュメントを読んでいると、Long-form DataとWide-Form Dataという項目で、その違いが説明されていました。

https://altair-viz.github.io/user_guide/data.html#long-form-vs-wide-form-data

@ishida330 さんの記事だと整然データという言葉で説明されています。

https://qiita.com/ishida330/items/922caa7acb73c1540e28

さて実際にどんな形か、Altairのページから取ってきておきます。

<b>wide-form</b>
![wide.PNG](https://qiita-image-store.s3.amazonaws.com/0/85433/a8a0678d-3d41-a245-5355-0e659d57dc71.png)

<b>long-form</b>
![long.PNG](https://qiita-image-store.s3.amazonaws.com/0/85433/39f2a971-91b4-04b5-89bb-0568f8d804da.png)

こんな感じで使うデータの形も可視化の際はちょっと違うようになっています。

## Callbackをみる
さて、そろそろ本題に入りましょう。

前回からCallbackを連発しているけど、それは何かという疑問があると思います。Callbackはなにかの要素をアプリケーションに反映する機能です。　

ここからは下の都道府県別GDP(GDP),都道府県別一人あたりGDP(pergdp),都道府県別人口(popu)のcsvを使って、サンプルを作っていきたいと思います。

https://github.com/mazarimono/keizai-dash/blob/master/data/longform.csv

大量に要素があるとややこしいので、まずは北海道のデータだけを使うことにし、ドロップダウンでどの要素を出すか選べるグラフを作ります。

```py
import dash  
import dash_core_components as dcc   
import dash_html_components as html
import plotly.graph_objs as go  
import pandas as pd 

# ①データ読み込み
df = pd.read_csv('./data/longform.csv', index_col=0)
dfhokkaido = df[df['area']=='北海道']

app = dash.Dash(__name__)

# ②表示作成
app.layout = html.Div(children=[
    html.Div(
        html.H1('北海道のGDP、人口、一人あたりGDPの推移',
        style = {'textAlign': 'center'})
    ),
    dcc.Dropdown(
        id = 'dropdown-for-hokkaido',
        options = [{'label': i, 'value': i} for i in dfhokkaido.item.unique()],
        value = 'GDP'
    ),
    dcc.Graph(
        id="hokkaidoGraph",
    )
])

# ③コールバック作成
@app.callback(
    dash.dependencies.Output('hokkaidoGraph', 'figure'),
    [dash.dependencies.Input('dropdown-for-hokkaido', 'value')]
)
def update_graph(factor):
    dff = dfhokkaido[dfhokkaido['item'] == factor]

    return {
        'data': [go.Scatter(
            x = dff['year'],
            y = dff['value']
        )]
    }

if __name__ == '__main__':
    app.run_server(debug=True)
```

このコードで下のようなものが出来ます。

[![Image from Gyazo](https://i.gyazo.com/0f3dcd81410d73c4dfae6bc0bc530e14.gif)](https://gyazo.com/0f3dcd81410d73c4dfae6bc0bc530e14)

ドロップダウンで選択すると、線グラフが切り替わるようになりました。

それを担っているのが②の中にあるドロップダウンと、③のコールバックの部分です。

### ドロップダウン
[dash_core_components](https://dash.plot.ly/dash-core-components)には要素を選択するツールが多くあります。

ドロップダウン以外にもスライダー、ボタン、文字入力など色々です。

また、これにIDを付けておくと、コールバックでここで選択した要素への切り替えができます。ここではid="dropdown-for-hokkaido"としました。

ドロップダウンが今ひとつだなと思った場合でも、ちょっと変えるだけで、違うツールが使えます。

例えば、今回のものでも、ボタンにしてみたいなと思ったのでやってみます。

②の中のdcc.Dropdown()の部分を、dcc.RadioItems（）に変更するだけで・・・

[![Image from Gyazo](https://i.gyazo.com/6cee2cc8aeaeafe4803d3eac93a43aa5.gif)](https://gyazo.com/6cee2cc8aeaeafe4803d3eac93a43aa5)

要素を見ながらボタンで選択できるグラフに変わりました。

### Callback
さてCallbackです。デコレーションでapp.callback()と書き、その後にとってくるデータと、その後加工して、戻すデータの送り先を指示します。そして、取ってきたデータを使っての処理の関数を書きます。

app.layoutの中に、dcc.Graph(id='hokkaidoGraph')とあります。
appの中に、グラフのために書くのはこれだけです。

さてapp.layoutsの外に書いているのは下のようになっています。

```py
@app.callback(
    dash.dependencies.Output('hokkaidoGraph', 'figure'),
    [dash.dependencies.Input('dropdown-for-hokkaido', 'value')]
)
def update_graph(factor):
    dff = dfhokkaido[dfhokkaido['item'] == factor]

    return {
        'data': [go.Scatter(
            x = dff['year'],
            y = dff['value']
        )]
    }
```

まず、利用するデータ（今回の場合ドロップダウン、もしくはラジオアイテムから得られる値）をdash.dependencies.Input()で取ります。これは一つでも、リストにしていないとエラーが出るので注意しましょう。取りたいデータのあるところのIDを指定し、その後、そのデータのタイプを指定します。

そして下の「def」の中でグラフのデータを作ります。

この際に、dash.dependencies.Input()で指定したデータを引き数に出来ます。名前は何でも良いので、今回はfactorとしました。

dfhokkaidoのアイテムの部分から、ドロップダウンで指定されたデータを取り、dffというデータフレームを作成します。

そして、return {}の中で、グラフにするデータを作ります。

{}の中のデータが、dash.dependencies.Output()で指定したIDに返されます。この場合、先程appの中に作ったdcc.Graph(id='hokkaidoGraph')にデータを返したいので、dash.dependencies.Output(id='hokkaidoGraph','figure')と指定しておきます。

この際、最初にIDを指定するのはわかるのですが、２つ目に何を入れるのか？というのはちょっと難しいところです。グラフの場合'figure'を入れるとか、ちょっと分かっているところはあるのですが、全部が全部わからないので、エラーが出たら候補があげられるので、それっぽいのを入れると通るという感じで、今のところは作成しています。

## まとめ 
今回はCallbackを使って、グラフを描くサンプルを作ってみました。

次はマウスのアクションを使って、もう少しデータを詳しく見られるようなものを作ってみたいと思います。

マウスホバーを使ってちょっと複雑なデータを見てみる３回目は以下のリンク先にあります。
https://qiita.com/OgawaHideyuki/items/b4e0c4f134c94037fd4f