LoginSignup
32
36

More than 3 years have passed since last update.

Jupyter上でDashを使えるjupyter_dash

Last updated at Posted at 2020-09-07

Dashは可視化をインタラクティブに行えるウェブフレームワークです。そしてDashにはJupyter上でアプリケーションを動作させるjupyter_dashというパッケージが存在しています。そして最近、Google Colab上でjupyter_dashが動作するようになりました。

今回はjupyter_dashの使い方に加えて、Jupyter上でDashが使えるメリットを紹介したいと思います。

今回はグーグルコラボ上で全ての作業を行います。サンプルのノートは次のリンク先にあります。

準備

jupyter_dashはコラボにインストールされていません。あと可視化に使うplotlyのバージョンが古いものになっているので、更新します。

!pip install jupyter_dash
!pip install --upgrade plotly

次に今回利用するライブラリをインポートします。

import dash 
from jupyter_dash import JupyterDash 
import dash_core_components as dcc 
import dash_html_components as html 
import plotly.express as px
from dash.dependencies import Input, Output

jupyter_dashはJupyter上でDashを使うためのパッケージです。dash_core_componentsは様々なツール、dash_html_componentsはHTMLコンポーネントを提供するパッケージです。plotly.expressはグラフ作成のパッケージです。

実践

ここからはPlotly ExpressのGapminderデータを使って進めます。Gapminderデータは1952年から2007年までの世界の国々の平均寿命、人口、1人当たりGDPを持つデータセットです。

gapminder = px.data.gapminder()
gapminder.head()

Image from Gyazo

平均寿命を線グラフで可視化(1つの国)

まずは、国ごとの平均寿命を観察したいとします。Plotly Expressのグラフの書き方は、次のようになります。

  • 描きたいグラフ種類の関数を使う
  • グラフに描画したいデータフレームを渡す
  • 各要素に利用する要素を引数に渡す

まずは日本の平均寿命の推移を可視化します。

# コード1
jp_gapminder = gapminder[gapminder["country"] == "Japan"] # Japanのデータフレーム作成
px.line(jp_gapminder, x='year', y="lifeExp") # グラフ描画

Image from Gyazo

次に中国の平均寿命を観察したい場合だと、たいていの場合中国のデータフレームを作成し、同じように関数の引数にデータを渡し、シフト+エンターという感じで実行すると思います。

しかし、jupyter_dashを使うとドロップダウンを選択するだけで、グラフを切り替えられ、良い感じにシフトとエンターの摩耗を防げます。

# コード2
# JupyterDashインスタンスの作成
app = JupyterDash(__name__)

# layout属性にレイアウトを渡す(ドロップダウンとグラフ)
app.layout = html.Div([
                       dcc.Dropdown(id="my_dropdown",
                                    options=[{"value": cnt, "label": cnt} for cnt in gapminder.country.unique()],
                                    value="Japan"
                                    ),
                       dcc.Graph(id="my_graph")
])

# ドロップダウンの選択値をグラフに反映するためのコールバック関数
@app.callback(Output("my_graph", "figure"), Input("my_dropdown", "value"))
def update_graph(selected_country):
  selected_gapminder = gapminder[gapminder["country"] == selected_country]
  return px.line(selected_gapminder, x="year", y="lifeExp")

# ノート上で実行
app.run_server(mode="inline")

上のようなコードでドロップダウンの選択が反映されたグラフが描画されます。

Image from Gyazo

平均寿命を線グラフで作成(複数国)

複数国を描画する場合、Plotly Expressでは色(引数color)で国を分けます。

# コード3
country_list = ["China", "Korea, Rep.", "Japan"]
selected_gapminder = gapminder[gapminder["country"].isin(country_list)]
px.line(selected_gapminder, x='year', y="lifeExp", color="country")

Image from Gyazo

これを国を入れ替えながら詳細に見るのは結構手間です。しかし、jupyter_dashを使うと先ほどのコードを少し変えるだけで、次のような感じで簡単に複数国の表示を切り替えられるアプリケーションが作成できます。

# コード4
app = JupyterDash(__name__)

app.layout = html.Div([
                       dcc.Dropdown(id="my_dropdown",
                                    options=[{"value": cnt, "label": cnt} for cnt in gapminder.country.unique()],
                                    value=["Japan", "China", "Korea, Rep."], # ➊
                                    multi=True # ➋
                                    ), 
                       dcc.Graph(id="my_graph")
])

@app.callback(Output("my_graph", "figure"), Input("my_dropdown", "value"))
def update_graph(selected_country):
  selected_gapminder = gapminder[gapminder["country"].isin(selected_country)] # ➌
  return px.line(selected_gapminder, x="year", y="lifeExp", color="country") # ➍

app.run_server(mode="inline")

変更点は番号を振ったところです。➊ではドロップダウンで複数国が最初から選ばれるように、リストに入れて国名を渡します。➋では引数multiにTrueを渡しドロップダウンで複数国を選択できるようにします。➌では複数国が選択されたデータフレームが作成されます。➍では引数colorに"country"を渡し、線の色が国名ごとに変更されるよう指定します。

作成したアプリケーションは次のように動作します。

Image from Gyazo

ツリーマップを使って可視化

最後にツリーマップを使った可視化を作成します。ツリーマップを文字で解説する文章力がないので、まず作成してみます。

# コード5
gapminder['board'] = 'world' # "board"列を追加し、'world'という文字列を追加する
px.treemap(gapminder, path=['board', 'year', 'country'], values='pop')

Image from Gyazo

今回は人口のみを可視化してみました。ツリーマップは次のように動的に数値を確認できます。ツリーマップはデータを入れ子にしてみることができるため、その順番を変えるだけでもデータとして新たな発見があります。

次に、ラジオボタンで人口、1人当たりGDPの表示を切り替えながら、ドロップダウンでツリーマップの表示順を切り替えられるツールを作成します。

# コード6
app = JupyterDash(__name__)

app.layout = html.Div([
                       html.H1(id="title"), # ラジオボタンの選択を表示する
                       dcc.RadioItems(
                           id="my_radio",
                           options=[{"label": i, "value": i} for i in ["pop", "gdpPercap"]],
                           value = "pop"
                       ),
                       dcc.Dropdown(
                           id="my_drop",
                           options=[{"label": i, "value": i} for i in ['board', 'year', 'continent', 'country']],
                           value = ['board', 'year', 'continent', 'country'],
                           multi=True
                       ),
                       dcc.Graph(id="my_graph")
])

@app.callback([Output('title', 'children'),Output('my_graph', "figure")], 
              [Input("my_radio", "value"), Input("my_drop", "value")])
def update_tree(radio_select, drop_select):
# ドロップダウンで3つ以上の要素が選択されている場合のみグラフを描画
  if len(drop_select) >= 3: 
    return radio_select, px.treemap(gapminder, path=drop_select, values=radio_select)
  else:
    return dash.no_update
app.run_server(mode="inline")

30行に満たないコードですが、次のように結構複雑な動作をしてくれます。

Image from Gyazo

まとめ

以上のようにjupyter_dashを使うことにより、グラフ描画でのちょっとした面倒を削減することができます(そして多分キーボードも長持ちします)。

もうちょっとDashを詳しく知りたいと思われた方は、過去の記事をご参照ください。

もうちょっと実際のデータを使った事例を知りたいという方は、WEB+DB PRESS VOL118に記事を書かせていただいたので、手に取っていただけますと幸いです。

また、PyConJP2020で行ったTutorialの資料を公開しているので、これも参考になるかと思います。こちらはデータの前処理、可視化、機械学習との流れとなっています。スターをつけてもらえると嬉しいです。

もっと詳しく知りたいという方は、本家のドキュメントを参照していただくか、11月ごろに出る本を購入していただけますと幸いです。宣伝です。

あと、PyCon mini Hiroshima2020で話す機会をいただいたので、アイデアを練っています。イベントに参加いただき、当日のトークを聞いていただけると嬉しいです!

32
36
1

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
32
36