【Python】DashとPlotlyでダッシュボードを作成する手順(2.コンポーネント、スタイル編)

Dash

前回のレイアウト編でダッシュボード全体のレイアウトを設定しました。

今回はDropdownなどのコンポーネントの設定とフォントやマージン(余白)などの細かいスタイルの整備をしていきます。

作成するダッシュボード

完成図

前回のレイアウト編でもお見せしましたが、以下のようにSidebarで特徴や相関関係などを確認したいカテゴリカル変数・連続変数をそれぞれ選択し、右側に選択した変数の分布や相関行列のヒートマップが出力されるダッシュボードの作成を目指します。

こちらもレイアウト編で紹介しましたが、上記のダッシュボードは kaggleのtabular playground series Mar 2021 のデータの一部を使用しています。 このデータは下表の通りサンプルidと19個のカテゴリカル変数(cat0 ~ cat18)と11個の連続変数(cont0 ~ cont10)、そして2値(0,1)のターゲット変数が含まれます。

前回までのダッシュボード

前回のレイアウト編では下図のようにダッシュボードのパーツ毎に画面を分割するところまで完了しましたので、次にSidebarにコンポーネントを設定していきます。

Sidebarのコンポーネントの設定

Sidebarに設定するコンポーネントは以下の6つです。

  • Settingsという見出し
  • “Categorical Variable”などの文字列の表示
  • カテゴリカル変数・連続変数を選択するドロップダウン
  • グラフを更新するためのボタン
  • Sidebarを見やすくするための水平の横線
  • ターゲット変数の割合を図示するための円グラフ

これらを前回レイアウト編のコードに追加していきますが、ここでは最後の円グラフ以外の上から5つ目までを完成させます。

最初に使用するデータを読み込みます。ドロップダウンの項目リストを作成する時に、カテゴリカル変数名と連続変数名のリストが必要になるので、それぞれvars_catとvars_contにカラム名のリストを格納します。

import pandas as pd
import numpy as np


df = pd.read_csv('data/data_sample.csv')
vars_cat = [var for var in df.columns if var.startswith('cat')]
vars_cont = [var for var in df.columns if var.startswith('cont')]

ドロップダウンの設置にはdash_core_componentsが必要なのでインポートします。

import dash_core_components as dcc

次にコンポーネントを追加するために前回のsidebar変数を次のように変更します。

sidebar = html.Div(
    [
        dbc.Row(
            [
                html.H5('Settings',
                        style={'margin-top': '12px', 'margin-left': '24px'})
                ],
            style={"height": "5vh"},
            className='bg-primary text-white font-italic'
            ),
        dbc.Row(
            [
                html.Div([
                    html.P('Categorical Variable',
                           style={'margin-top': '8px', 'margin-bottom': '4px'},
                           className='font-weight-bold'),
                    dcc.Dropdown(id='my-cat-picker', multi=False, value='cat0',
                                 options=[{'label': x, 'value': x}
                                          for x in vars_cat],
                                 style={'width': '320px'}
                                 ),
                    html.P('Continuous Variable',
                           style={'margin-top': '16px', 'margin-bottom': '4px'},
                           className='font-weight-bold'),
                    dcc.Dropdown(id='my-cont-picker', multi=False, value='cont0',
                                 options=[{'label': x, 'value': x}
                                          for x in vars_cont],
                                 style={'width': '320px'}
                                 ),
                    html.P('Continuous Variables for Correlation Matrix',
                           style={'margin-top': '16px', 'margin-bottom': '4px'},
                           className='font-weight-bold'),
                    dcc.Dropdown(id='my-corr-picker', multi=True,
                                 value=vars_cont + ['target'],
                                 options=[{'label': x, 'value': x}
                                          for x in vars_cont + ['target']],
                                 style={'width': '320px'}
                                 ),
                    html.Button(id='my-button', n_clicks=0, children='apply',
                                style={'margin-top': '16px'},
                                className='bg-dark text-white'),
                    html.Hr()
                    ]
                    )
                ],
            style={'height': '50vh', 'margin': '8px'}),
        dbc.Row(
            [
                html.P('Target Variables', className='font-weight-bold')
                ],
            style={"height": "45vh", 'margin': '8px'}
            )
        ]
    )

Sidebarは各dbc.Rowを1つのまとまりとして3つの行に分かれています。最初の行では文字列”Settings”をhtml.H5で見出し5の大きさに設定しています。

次の行では以下の項目を順番に設定しています。

  1. 文字列”Categorical Variables”を表示
  2. カテゴリカル変数のドロップダウンを設置
  3. 文字列”Continuous Variables”を表示
  4. 連続変数のドロップダウンを設置
  5. 文字列”Continuous Variables for Correlation Matrix”を表示
  6. 連続変数を複数選択するドロップダウンを設置
  7. グラフを更新するためのボタンをhtml.Buttonで設置
  8. 変数の選択と円グラフの境目を分かりやすくするために水平の横線を設置

1, 3, 5番目は1つの段落を表すhtml.Pを使って文字列を表示させます。2, 4, 6番目はdcc.Dropdownを使ってドロップダウンを表示させます。ドロップダウンの引数は以下の通りです。

  • id: 任意のidを付与することができ、コールバックにおいてコンポーネントの特定に使用
  • multi: Trueにするとドロップダウンで複数の項目を選択可能
  • value: 初期値を設定。リストを渡すと複数項目を初期値に設定可能
  • options: ドロップダウンの項目リストを辞書形式で指定

7番目はグラフを更新するためのボタンをhtml.Buttonで表示させます。引数idとn_clicksはコールバックの設定で使用します。ボタンに表示させる文字列はchildrenで指定します。最後はhtml.Hr()で水平の横線を表示させます。

最後の行は”Target Varialbes”と表示させるだけのままにして、グラフは後程作成します。

この時点で一度実行すると下図のようになります。

ドロップダウンリストなど設定したものは表示されましたが、各コンポーネントの縦横の幅や文字のフォントや色などイメージ通りになっていないので次にスタイルを整えていきます。

スタイルの調整

マージン

マージン(余白)が無いと各コンポーネントがスクリーンの上部や左側にぴったりとくっついてしまい窮屈な印象を受けます。まずはSettingsの上部と左側に余白を作ります。マージンはstyleで上部の余白ならmargin-top、左側ならmargin-leftとし、px単位で指定できます。dbc.Row全体ではなく、Settingsに余白を作りたいので次のようにhtml.H4の中でstyleを設定します(dbc.Row単位で表示します)。

dbc.Row(
            [
                html.H5('Settings',
                        style={'margin-top': '12px', 'margin-left': '24px'})
                ],
            style={"height": "5vh"}
            )

実行すると次のようになり、Settingsの上部と左側に余白ができました。

フォント、配色

DashではclassNameを設定することでフォントや文字色、背景色など様々なbootstrapクラスを使用できます。bootstrapクラスの詳細はこちらのチートシートをご覧ください。一部を下表に表示します。

赤枠で囲ったbootstrapクラスを使用します。

  • bg-primary: 背景色は前回レイアウト編で設定したFLATLYテーマのprimaryカラー(ネイビー)。FLATLYの詳細はこちら
  • text-white: 文字の色は白色
  • font-italic:文字のフォントはイタリック

bootstrapクラスを複数指定する場合は次のように半角スペースを空けて記述します。

dbc.Row(
            [
                html.H5('Settings',
                        style={'margin-top': '12px', 'margin-left': '24px'})
                ],
            style={"height": "5vh"},
            className='bg-primary text-white font-italic',
            )

再度実行すると、白文字でイタリック、背景色はネイビーになっていることが確認できます。

コンポーネントの幅

ドロップダウンの幅を調整します。コンポ-ネントの幅はstyleでwidthをpx単位で指定できます(1つ目のドロップダウンを例に表示します)。

dcc.Dropdown(id='my-cat-picker', multi=False, value='cat0',
                             options=[{'label': x, 'value': x}
                                      for x in vars_cat],
                             style={'width': '320px'}
                             )

再度実行すると幅が広がっているのが確認できます。

スタイル調整後の全体像

以上の知識を応用してコンポーネント間の余白の調整や文字列のフォントを設定したコードは次の通りです。Contentの文字列のフォントや余白もSidebarに合わせて設定しています。

import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import numpy as np


df = pd.read_csv('data/data_sample.csv')
vars_cat = [var for var in df.columns if var.startswith('cat')]
vars_cont = [var for var in df.columns if var.startswith('cont')]

app = dash.Dash(external_stylesheets=[dbc.themes.FLATLY])

sidebar = html.Div(
    [
        dbc.Row(
            [
                html.H5('Settings',
                        style={'margin-top': '12px', 'margin-left': '24px'})
                ],
            style={"height": "5vh"},
            className='bg-primary text-white font-italic'
            ),
        dbc.Row(
            [
                html.Div([
                    html.P('Categorical Variable',
                           style={'margin-top': '8px', 'margin-bottom': '4px'},
                           className='font-weight-bold'),
                    dcc.Dropdown(id='my-cat-picker', multi=False, value='cat0',
                                 options=[{'label': x, 'value': x}
                                          for x in vars_cat],
                                 style={'width': '320px'}
                                 ),
                    html.P('Continuous Variable',
                           style={'margin-top': '16px', 'margin-bottom': '4px'},
                           className='font-weight-bold'),
                    dcc.Dropdown(id='my-cont-picker', multi=False, value='cont0',
                                 options=[{'label': x, 'value': x}
                                          for x in vars_cont],
                                 style={'width': '320px'}
                                 ),
                    html.P('Continuous Variables for Correlation Matrix',
                           style={'margin-top': '16px', 'margin-bottom': '4px'},
                           className='font-weight-bold'),
                    dcc.Dropdown(id='my-corr-picker', multi=True,
                                 value=vars_cont + ['target'],
                                 options=[{'label': x, 'value': x}
                                          for x in vars_cont + ['target']],
                                 style={'width': '320px'}
                                 ),
                    html.Button(id='my-button', n_clicks=0, children='apply',
                                style={'margin-top': '16px'},
                                className='bg-dark text-white'),
                    html.Hr()
                    ]
                    )
                ],
            style={'height': '50vh', 'margin': '8px'}),
        dbc.Row(
            [
                html.P('Target Variables', className='font-weight-bold')
                ],
            style={"height": "45vh", 'margin': '8px'}
            )
        ]
    )

content = html.Div(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.P('Distribution of Categorical Variable',
                               className='font-weight-bold'),
                        ]),
                dbc.Col(
                    [
                        html.P('Distribution of Continuous Variable',
                               className='font-weight-bold')
                    ])
            ],
            style={'height': '50vh',
                   'margin-top': '16px', 'margin-left': '8px',
                   'margin-bottom': '8px', 'margin-right': '8px'}),
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.P('Correlation Matrix Heatmap',
                               className='font-weight-bold')
                    ])
            ],
            style={'height': '50vh', 'margin': '8px'}
            )
        ]
    )

app.layout = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(sidebar, width=3, className='bg-light'),
                dbc.Col(content, width=9)
                ]
            ),
        ],
    fluid=True
    )


if __name__ == "__main__":
    app.run_server(debug=True, port=1234)

最後にもう1度実行します。

完成図に近づいてきました。次の記事ではグラフの作成とインタラクティブにグラフを更新するためのコールバックを設定します。

コメント

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