DashとBootstrapを組み合わせてレイアウトを作成する

ど素人の備忘録を兼ねています。ご容赦ください。

前回https://qiita.com/Naoya_Study/items/507cf063a9300e9e41f6

本日の完成形はこちらです↓↓

![3s39m-g3lc1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369285/feb5932e-5611-09ce-42d7-c7b23d1776dc.gif)


#1.Dash Bootstrap Componentsをインストール

PythonフレームワークDash内でBootstrapを使うことが出来るのライブラリがあります。
今回はそれを使用し2×2の非常にシンプルなレイアウトを作ってみます。


使用するライブラリはDash Bootstrap Componentsです。
https://dash-bootstrap-components.opensource.faculty.ai/
インストールします。

```python
pip install dash-bootstrap-components
```

基本的なテンプレートはこのようになります。
dbc.Containerに要素を追加することでレイアウトを作ります。

```python
import dash
import dash_bootstrap_components as dbc

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

app.layout = dbc.Container("""ここに色々な要素を足していく""")

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

#2.シンプルレイアウトを作る

それでは実際に2×2のレイアウトを書いていきましょう。

```Python
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html

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

app.layout = dbc.Container(
    [   dbc.Row(
            [
                dbc.Col(
                    html.H1("ここにタイトル！"),
                    style={"background-color": "pink"}
                    )
            ],
            className="h-30"
        ),
        dbc.Row(
            [
                dbc.Col(
                    html.P("世界地図！"),
                    width=7,
                    style={"height": "100%", "background-color": "red"},
                ),
                dbc.Col(
                    html.P("国別感染者数のリスト！"),
                    width=5,
                    style={"height": "100%", "background-color": "green"},
                ),
            ],
            className="h-50"
        ),
        dbc.Row(
            [
                dbc.Col(
                    html.P("日本地図！"),
                    width=7,
                    style={"height": "100%", "background-color": "blue"},
                ),
                dbc.Col(
                    html.P("国内感染者数推移の棒グラフ！"),
                    width=5,
                    style={"height": "100%", "background-color": "cyan"},
                ),
            ],
            className="h-50",
        ),
    ],
    style={"height": "90vh"},
)

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

```
<img width="959" alt="layout.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369285/e1d15d5d-9ca6-9dab-aa0d-53b1728f52e5.png">

```python
className="h-50"
```
この50は高さの50パーセントを意味します。

```python
style={"height": "90vh"}
```
vhは"viewport height"の略で、スクリーンの高さの90％にするという意味です(多分)

#3.グラフを挿入する
このレイアウトに沿って前回作成した図を挿入していきます。
基本的にhtml.P()を作成したdcc.Graph()に置き換えるだけです。

```python
#書き換える
html.P()
↓
dcc.Graph()
```

```python
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import requests, io, re
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime as dt
import dash_table
import dash_core_components as dcc
from corona_def import Get_Df, Df_Merge, Df_Count_by_Date, Df_Globe_Merge

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

app.layout = dbc.Container(
    [  dbc.Row(
            [
                dbc.Col(
                    html.H1("Novel Coronavirus (COVID-19) Situation"),
                    style = {
                        "size": "30px",
                        "background-color": "#1b1935",
                        "color": "white",
                        "textAlign": "center",
                        }
                    )
            ],
            className = "h-30"
        ),
        dbc.Row(
            [
                dbc.Col(
                    html.H4("世界の感染者数"),
                    width = 7,
                    style = {
                        "height": "100%",
                        "background-color": "white",
                        "textAlign": "left",
                        "padding": "10px"
                        },
                ),
                dbc.Col(
                    html.H4(""),
                    width = 5,
                    style = {
                        "height": "100%",
                        "background-color": "white",
                        "textAlign": "center"
                        },
                ),
            ],
            className = "h-8"
        ),
        dbc.Row(
            [
                dbc.Col(
                        dcc.Graph(
                            id = 'WorldMap',
                            figure = {
                                'data' : [
                                    go.Choropleth(
                                        locations = df_globe_merge['code'],
                                        z = df_globe_merge['Confirmed'],
                                        text = df_globe_merge['COUNTRY'],
                                        colorscale = 'Plasma',
                                        marker_line_color ='darkgray',
                                        marker_line_width = 0.5,
                                        colorbar_title = '感染者数',
                                    )
                                ],
                                'layout' : go.Layout(
                                    template = "ggplot2",
                                    width = 600,
                                    height = 270,
                                    title = {
                                        'font': {'size': 25},
                                        'y': 0.9,
                                        'x': 0.5,
                                        'xanchor': 'center',
                                        'yanchor': 'top'
                                        },
                                    margin={'b': 5, 'l': 5, 'r': 5, 't': 5},
                                    geo={"projection_type": 'equirectangular'}
                                )
                            }
                        ),
                    width = 7,
                    style = {
                        "height": "100%",
                        "background-color": "white",
                        "border-color": "white",
                        "border-width":"10px"
                        },
                ),
                dbc.Col(
                    dash_table.DataTable(
                        columns = [{"name": i, "id": i} for i in df_globe.columns],
                        data = df_globe.to_dict('records'),
                        style_header = {'backgroundColor': '#eae6e8'},
                        style_cell = {
                                'backgroundColor': '#fbf9f7',
                                'color': 'black',
                                'font-size': '15px',
                                'textAlign': 'center'
                                },
                        style_table = {
                                'maxHeight': '300px',
                                'overflowY': 'scroll',
                                'overflowX': 'hidden',
                                },
                        ),
                    width = 5,
                    style = {"height": "100%"}
                ),
            ],
            className = "h-50"
        ),
        dbc.Row(
            [
                dbc.Col(
                    html.H4("国内感染者分布"),
                    width = 7,
                    style = {
                        "height": "100%",
                        "background-color": "white",
                        "textAlign": "left",
                        "padding":"10px"
                        },
                ),
                dbc.Col(
                    html.H4("国内累計感染者数"),
                    width = 5,
                    style = {
                        "height": "100%",
                        "background-color": "white",
                        "textAlign": "left",
                        "padding":"13px"
                        },
                ),
            ],
            className = "h-30"
        ),
        dbc.Row(
            [
                dbc.Col(
                        dcc.Graph(
                            id = 'JapMap',
                            figure = {
                                'data' : [
                                    go.Scattergeo(
                                        lat = df_merge["緯度"],
                                        lon = df_merge["経度"],
                                        mode = 'markers',
                                        marker = {
                                            "color": 'red',
                                            "size": df_merge['China']/5+6,
                                            "opacity": 0.8,
                                            "reversescale": True,
                                            "autocolorscale": False
                                            },
                                        hovertext = df_merge['text'],
                                        hoverinfo = "text"
                                    )
                                ],
                                'layout' : go.Layout(
                                    width = 600,
                                    height = 270,
                                    template = "ggplot2",
                                    title = {
                                        'font': {'size':25},
                                        'y': 0.9,
                                        'x': 0.5,
                                        'xanchor': 'center',
                                        'yanchor': 'top'},
                                    margin = {'b': 1, 'l': 1, 'r': 1, 't': 1},
                                    geo = dict(
                                        resolution = 50,
                                        landcolor = 'rgb(204, 204, 204)',
                                        coastlinewidth = 1,
                                        lataxis = dict(range = [28, 47]),
                                        lonaxis = dict(range = [125, 150]),
                                    )     
                                )
                            }
                        ),
                    width = 7,
                    style = {"height": "100%",},
                ),
                dbc.Col(
                    dcc.Graph(
                        id = '都道府県別感染者数',
                        figure = {
                            'data' : [
                                go.Bar(
                                    name='前日までの累積数',
                                    x=df_count_by_date.index,
                                    y=df_count_by_date['gap'],
                                    ),
                                go.Bar(
                                    name='新規数',
                                    x=df_count_by_date.index,
                                    y=df_count_by_date['China']
                                    )               
                            ],
                            'layout' : go.Layout(
                                width = 450,
                                height = 270,
                                legend = {
                                    'x': 0.05, 
                                    'y': 0.9,
                                    'bordercolor': 'black',
                                    'borderwidth': 1
                                    },
                                barmode = 'stack',
                                template = "ggplot2",
                                margin = {'b': 5, 'l': 5, 'r': 5, 't': 5},
                                xaxis_title = None,
                                yaxis_title = "感染者数"
                            )
                        }
                    ),
                    width = 5,
                    style = {"height": "100%"},
                ),
            ],
            className = "h-50",
        ),
    ],
    style = {"height": "90vh"},
)

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

とりあえずは作図した通りのグラフの挿入が出来ました。
グラフもインタラクティブに動きおもしろいです。
しかし見た目がまだまだなので次回以降はビジュアルを改善していきます。