Dash by Plotly Tutorialメモ

Dash by Plotly とは

Dash is a Python framework for building analytical web applications. No JavaScript required.

7月に入ってから、社内のデータをpandasで前処理をしていました。
そろそろ前処理も落ち着いてきたので「ダッシュボードにして見せたいな~~」と思いまして、いろいろと調べていたところ、面白そうなflameworkがありました。
Tutorialを試してみたいと思います。ド素人でもできるのかな。。。

Prat1 Installation

pip install dash==0.22.0  # The core dash backend
pip install dash-renderer==0.13.0  # The dash front-end
pip install dash-html-components==0.11.0  # HTML components
pip install dash-core-components==0.26.0  # Supercharged components
pip install plotly --upgrade  # Plotly graphing library used in examples

これは書いてある通りに実行。

Part2 Dash Layout

Dash apps are composed of two parts. The first part is the "layout" of the app and it describes what the application looks like. The second part describes the interactivity of the application and will be covered in the next chapter.

Dashにはアプリケーションの見た目を決めるLayoutと、アプリケーションの操作を説明するCallbackで構成されている、とのことです。

ビジュアルを構成する要素には dash_core_componentsdash_html_componentsというライブラリがありますが、JavaScriptとReact.jsを操れば自作も可能みたいです。

下記のコードをapp.pyとして実行してみます。

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),

    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])

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

python app.pyで実行すると、

f:id:komepy:20180803213435p:plain

おお、、できた。

Note:

  • layoutはMarkdown要素のhtml.Divと、グラフ表示のdcc.Graphで構成される。
  • dash_html_componentsはHTMLタグを持ち合わせている。

HTMLのちょっとした工夫

app.pyをカスタマイズしてみる。

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}

app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[
    html.H1(
        children='Hello Dash',
        style={
            'textAlign': 'center',
            'color': colors['text']
        }
    ),

    html.Div(children='Dash: A web application framework for Python.', style={
        'textAlign': 'center',
        'color': colors['text']
    }),

    dcc.Graph(
        id='example-graph-2',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
            ],
            'layout': {
                'plot_bgcolor': colors['background'],
                'paper_bgcolor': colors['background'],
                'font': {
                    'color': colors['text']
                }
            }
        }
    )
])

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

f:id:komepy:20180803220058p:plain

こういうの初めてなので楽しくなってきました。

Note:

  • dash_html_componentsstyleプロパティでスタイルを帰ることができる。
  • dash_html_componentsはHTMLとは書式がちょっと異なる。
  • styleプロパティはセミコロンで区切る。
  • styleプロパティのkeyはキャメル型で書く。text-aligntextAlign
  • HTMLでやりたいことがPythonの中で書ける。すげぇ。

Tableもかける

PandasのDateFrameからTableがかける。強い。

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd


df = pd.read_csv('titanic_train.csv')


def generate_table(dataframe, max_rows=10):
    return html.Table(
        # Header
        [html.Tr([html.Th(col) for col in dataframe.columns])] +

        # Body
        [html.Tr([
            html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
        ]) for i in range(min(len(dataframe), max_rows))]
    )


app = dash.Dash()

#Tutorialと同じような表記にするために追加しています。
app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})

app.layout = html.Div(children=[
    html.H4(children='Titanic_train.csv'),
    generate_table(df)
])

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

f:id:komepy:20180803223259p:plain

できました。
def generate_tableを定義して、表示させたいDateFrameを投げればできますね。

Graph

dash_core_componentsライブラリにはGraphと呼ばれるコンポーネントがあります。
Graphはplotly.jsライブラリを使ってインタラクティブなデータ表示を可能にしているとのこと。
JavaScriptはド素人なのでとりあえずコピペしてみます。

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

app = dash.Dash()

df = pd.read_csv(
    'https://gist.githubusercontent.com/chriddyp/' +
    '5d1ea79569ed194d432e56108a04d188/raw/' +
    'a9f9e8076b837d541398e999dcbac2b2826a81f8/'+
    'gdp-life-exp-2007.csv')


app.layout = html.Div([
    dcc.Graph(
        id='life-exp-vs-gdp',
        figure={
            'data': [
                go.Scatter(
                    x=df[df['continent'] == i]['gdp per capita'],
                    y=df[df['continent'] == i]['life expectancy'],
                    text=df[df['continent'] == i]['country'],
                    mode='markers',
                    opacity=0.7,
                    marker={
                        'size': 15,
                        'line': {'width': 0.5, 'color': 'white'}
                    },
                    name=i
                ) for i in df.continent.unique()
            ],
            'layout': go.Layout(
                xaxis={'type': 'log', 'title': 'GDP Per Capita'},
                yaxis={'title': 'Life Expectancy'},
                margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
                legend={'x': 0, 'y': 1},
                hovermode='closest'
            )
        }
    )
])

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

f:id:komepy:20180803235201p:plain

Markdownも書ける

dash_html_componentsライブラリを使ってHTMLを書くのが面倒なときはdash_core_componentsライブラリのMarkdownを使ってサッと書いてしまうことも可能。

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

markdown_text = '''
### Dash and Markdown

Dash apps can be written in Markdown.
Dash uses the [CommonMark](http://commonmark.org/)
specification of Markdown.
Check out their [60 Second Markdown Tutorial](http://commonmark.org/help/)
if this is your first introduction to Markdown!
'''

app.layout = html.Div([
    dcc.Markdown(children=markdown_text)
])

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

その他

dash_html_componentsにはドロップダウンやグラフ、Markdown blocksなどの高機能なライブラリがあります。
詳しくはこちらDash User Guide and Documentation - Dash by Plotly

とりあえずコピペして確認してみる。

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

app.layout = html.Div([
    html.Label('Dropdown'),
    dcc.Dropdown(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),

    html.Label('Multi-Select Dropdown'),
    dcc.Dropdown(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value=['MTL', 'SF'],
        multi=True
    ),

    html.Label('Radio Items'),
    dcc.RadioItems(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),

    html.Label('Checkboxes'),
    dcc.Checklist(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        values=['MTL', 'SF']
    ),

    html.Label('Text Input'),
    dcc.Input(value='MTL', type='text'),

    html.Label('Slider'),
    dcc.Slider(
        min=0,
        max=9,
        marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)},
        value=5,
    ),
], style={'columnCount': 2})

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

f:id:komepy:20180803235529p:plain

すげぇ。でもドロップダウンさせた値ってどうやって拾ってくるんだ??

まとめ

  • Dashは大きくlayoutcallbackで構成される。
  • layoutにはdash_html_componentsdash_core_componentsのライブラリで構成される。
  • dash_html_componentsはHTMLのタグやキーを説明する。
  • dash_core_componentsはグラフやドロップダウンなどの高機能な要素を持つ。

以上。メモでした。。。