【Python】JupyterDashでコールバックを使ったグラフを作成する方法

Dash

Dashではコールバックという機能を使うことでインタラクティブなグラフを作成することができます。今回はDashの機能を手軽に使用できるJupyterDashを使ってGapminderの人口データをインタラクティブにプロットしたいと思います。JupyterDashをJupyterLab上で動かすためのセットアップ手順はこちらの記事をご覧ください。

使用するデータとゴールイメージ

Gapminderのデータは以下のようにcountry列を指定してyear毎のpop列(population: 人口)を抽出することで国別の人口推移を見ることができます。

例えば以下のコードで日本の人口推移をプロットすることができます。

import plotly.express as px

gapminder = px.data.gapminder()
gapminder_Japan = gapminder.loc[gapminder['country']=='Japan']
px.bar(gapminder_Japan,
       x='year',
       y='pop',
       title='Japan').show()

次節以降でドロップダウンからcountryを選択し、その選択した国の人口推移をインタラクティブに表示する機能をJupyterDashで実装します。

コールバックの基礎

JupyterDashでインタラクティブにプロットをするためにコールバックという機能を使います。まずは簡単にドロップダウンで任意の項目を選択し、画面に”I selected item1″のように表示させる機能を実装します。
JupyterDashの他、基本的なhtml、ドロップダウン、コールバックに必要なモジュールをインポートします。

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

最初に慣例的にappという名前でJupyterDashのインスタンスを作成し、以下のようにレイアウトを設定します。

app = JupyterDash(__name__)

app.layout = html.Div([
    dcc.Dropdown(id='item_dropdown',
                options=[{'label': item, 'value': item}
                         for item in ['item1', 'item2', 'item3']]),
    html.Br(),
    html.Div(id='item_output')
])

上記ではDivで囲ったブロックの中に、ドロップダウン(dcc.Dropdown)、改行(html.Br())、アウトプットを表示するためのブロックの3つのコンポーネント設定しました。各コンポーネントには任意のIDを付与することができ、これらはコールバックにおいてコンポーネントの特定に使います。ドロップダウンの項目リストはoptions引数に辞書の形で指定します。

コールバックの機能はインプットを引数に取ってアウトプットを返す関数にデコレータを付けることで実装できます。今回の場合はインプットがドロップダウンで選んだ項目で、アウトプットが”I selected item1″のような文字列になるので、関数とデコレータは以下のようになります(選択していない状態ではnothingを返す)。

@app.callback(Output('item_output', 'children'),
              Input('item_dropdown', 'value'))
def display_selected_item(item):
    if item is None:
        item = 'nothing'
    return 'I selected ' + item

デコレータ@app.callbackの中のOutputクラスとInputクラスの第1引数はコンポーネントのIDで第2引数はコンポーネントの属性を渡します。インプットはドロップダウンで選択した項目なので、第1引数がitem_dropdownで値が入る場合は第2引数でvalueを指定します。アウトプットを表示する箇所は3つ目のコンポーネントなので第1引数がitem_outputでブロックに表示するだけの場合は第2引数にchildrenを指定します。

最後にappを実行します。JupyterLabのinline上に表示する場合はmode=’inline’と指定します。

if __name__ == '__main__':
    app.run_server(mode='inline')

項目を選択すると以下のようになります。

インタラクティブなプロット

ここまでのコードを以下のように応用することでGapminderデータのインタラクティブな作図をすることができます。

  • インプット
    ドロップダウンのopitonsにGapmiderのcountry列のユニークな値を指定します。またdcc.Dropdownのvalue引数に初期値United Statesを指定します。
  • アウトプット
    グラフを表示するためにdcc.Graphコンポーネントを設定します。デコレータのOutputクラスの第2引数はグラフ属性にするためfigureを指定します。
  • 関数
    ドロップダウンで指定された国のデータのみ抽出されたdataframeで作成された棒グラフを返します。

全体のコードは以下の通りです。

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


gapminder = px.data.gapminder()

app = JupyterDash(__name__)

app.layout = html.Div([
    dcc.Dropdown(id='country_dropdown', value='United States',
                options=[{'label': color, 'value': color}
                         for color in gapminder['country'].unique()]),
    html.Br(),
    dcc.Graph(id='country-population', figure={})
])


@app.callback(Output('country-population', 'figure'),
              Input('country_dropdown', 'value'))
def display_selected_color(country):
    gapminder_country = gapminder.loc[gapminder['country']==country]
    fig = px.bar(gapminder_country,
                 x='year',
                 y='pop',
                 title=country)
    return fig

if __name__ == '__main__':
    app.run_server(mode='inline')

実行すると以下のように表示されます。

ドロップダウンでトルコに変更すると以下のようにグラフが変わります。

以上で、JupyterDashを使ってGapminderデータのインタラクティブな人口推移グラフを作成することができました。

コメント

タイトルとURLをコピーしました