dash0.

Published by onesixx on

Dash APP = Layout(HTML:구조/배치, Core:그래프/인터액티브) + Callback (Input/Output)

https://dash.plotly.com/
https://crong-dev.tistory.com/category/Dash%20Plotly
# -*- coding: utf-8 -*-

# Run this app with `python app.py` and
# visit http://127.0.0.1:8050/ in your web browser.
from sixx import *
print("Hello dash")

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.express as px

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(
    __name__, 
    external_stylesheets=external_stylesheets
)

def generate_table(dataframe, max_rows=10): 
    return html.Table([
        html.Thead( 
            html.Tr([
                html.Th(col) for col in dataframe.columns
            ]) 
        ), 
        html.Tbody([ 
            html.Tr([ 
                html.Td(
                    dataframe.iloc[i][col]
                ) for col in dataframe.columns 
            ]) for i in range(min(len(dataframe), max_rows)) 
        ]) 
    ])

# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options
# df = pd.DataFrame({
#     "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
#     "Amount": [4, 1, 2, 2, 4, 5],
#     "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
# })
df = pd.read_csv('https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv')

fig = px.scatter(df, 
        x="gdp per capita", y="life expectancy",
        size="population", size_max=60, color="continent", 
        hover_name="country", log_x=True)

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

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

    dcc.Graph(id='example-graph',
        figure=fig
    ),
    html.H4(children='US Agriculture Exports (2011)'),
    generate_table(df)
])

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

dcc

편의를 위해 component (그래프, 슬라이더, 여러 컨트롤) 제공

import dash_core_components as dcc
help(dcc.Dropdown)

callback

사용자의 입력에 따라 반응하는 App개발을 위해

dash.dependencies.Input 객체 ==> Callback에서 사용  
cf> dash_core_components.Input 객체 ==> 실제 component

# -*- coding: utf-8 -*-
from sixx import *
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

import pandas as pd
import plotly.express as px

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(
    __name__, 
    external_stylesheets=external_stylesheets
)

app.layout = html.Div([ 
    html.Div(["Input: ", dcc.Input(id='my-input', value='initial value', type='text')]),
    html.Br(),
    # Children 없음, Children값 설정해도 callback값으로 초기화 됨
    html.Div(id='my-output'), #children='FUXXX'),
])

@app.callback(
    Output(component_id='my-output', component_property='children'),
    Input('my-input', 'value')
)
def whateverName_update_div(inputVal):
    return 'Result: {}'.format(inputVal)

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

Multi-Input

app.layout = html.Div([ 
    dcc.Input(id="my-input1", type="text", value="Seoul"),
    dcc.Input(id="my-input2", type="text", value="Canada"),
    html.Div(id="my-output"),
])

@app.callback(
    Output('my-output', 'children'),
    Input('my-input1', 'value'),
    Input('my-input2', 'value')
)
def whateverName_update_div(inputVal1,inputVal2 ):
    return 'Result: 1.{}, 2.{}'.format(inputVal1, inputVal2)

State

결과(출력)값에는 사용되지만, 값이 변할 때 자동으로 콜백함수를 호출하고 싶지 않은 경우

app.layout = html.Div([ 
    dcc.Input(id="my-input1", type="text", value="Seoul"),html.Br(),
    dcc.Input(id="my-input2", type="text", value="Canada"),
    html.Button(id="btn_submit", n_clicks=0, children='submit'),
    html.Div(id="my-output"),
])

@app.callback(
    Output('my-output', 'children'),
    Input('btn_submit', 'n_clicks'),
    State('my-input1', 'value'),
    State('my-input2', 'value')
)
def whateverName_update_div(Input_nclicks, stateVal1, stateVal2 ):
    return 'Result: From :{}  to: {}'.format(stateVal1, stateVal2)

Chained callback

한 입력 컴포넌트의 변화가 다른 입력 컴포넌트의 변화를 이끌어내는 연쇄적인 콜백을 사용가능

#------------------------------------------------------------------------------
all_options = { 'America': ['New York', 'San Francisco', 'chicago'],
                'Korea': ['Seoul', 'Busan', 'Jeju'] }
#------------------------------------------------------------------------------
app.layout = html.Div([
    dcc.RadioItems(id='rdo_countries',
        options=[{'label':k, 'value':k} for k in all_options.keys()],
        value='Korea'), html.Hr(),
    dcc.RadioItems(id='rdo_cities'), html.Hr(),
    html.Div(id="my-output_selectedVal"),
])

@app.callback(
    Output('rdo_cities',    'options'),
    Input( 'rdo_countries', 'value')
)
def set_cities_options(selected_country):
    return [{'label': i, 'value': i} for i in all_options[selected_country]]

@app.callback( 
    Output('rdo_cities', 'value'),
    Input('rdo_cities',  'options')
) 
def set_cities_value(available_options): 
     return available_options[0]['value'] 

@app.callback( 
    Output('my-output_selectedVal', 'children'), 
    Input('rdo_countries', 'value'), 
    Input('rdo_cities',    'value')
) 
def set_display_children(selected_country, selected_city): 
    return '{} is a city in {}'.format( selected_city, selected_country)

Dash Plotly 콜백함수 간 데이터 공유

콜백함수 간 데이터 공유

State를 sharing

여러 Callback이 큰 비용의 데이터 처리 작업(SQL 쿼리작성, 시뮬레이션실행 또는 데이터 다운로드…)에 의존할 때,
하나의 콜백이 해당 작업을 실행하도록 한 다음, 나머지 콜백과 결과만 공유 가능하다.

cf.> Callback함수 내에서 외부Scope에 선언되어 있는 변수의 값을 바꾸지 못한다
==> 아무 전역 변수의 값을 바꾸는 건 안전하지 않다.

.

콜백간에 데이터 공유

여러 파이썬 프로세스에서 데이터를 안전하게 공유하려면, 각 프로세스에서 액세스 할 수 있는 어딘가에 데이터를 저장해야한다. 이 데이터를 저장하는 세 가지 주요 위치는 다음과 같다.

  1. 사용자의 브라우저 세션 
  2. 디스크 (예 : 파일 또는 새 데이터베이스)
  3. Redis와 같은 공유 메모리 공간

Dash Enterprise

최적의 User-Interaction과 차트 로딩 성능을 위해, dash 앱 Production버전은 아래 사항을 고려해야 한다.

Job Queue Queueing 은 ML/AI apps의 확장성의 가장 중요한 요소이다.
Background jobs은 Dash app의 확장성를 크게 개선시킨다.
callback loops에서 느리고, cpu를 많이사용하는 task의 부하를 줄임으로써,
이에 따라 Dash 프론트앤드는 request가 밀리게 되었을 때
발생할 수 있는 성능이슈를 줄여줌으로써, incoming web requests를 바로바로 처리가능하다.
HPCHPC(High-Performance Computing, 고성능 컴퓨팅) – Hardware Acceleration
puts Python’s most popular HPC stack in the hands of business users.


Over the past 2 years, Dask and NVIDIA RAPIDS have changed the Python HPC landscape.
Heavy, expensive Spark clusters are no longer necessary for terabyte-scale work in Python.
Dash Enterprise ships with turnkey support for horizontally scalable Dask clusters and GPU computing.
DatashaderBig Data Pipelines
Dash Enterprise is your front end for horizontally scalable, big data computation in Python.

Python이 어떤 DB에 접속하면, 사용자는 DB에 연결된 dash app을 통해 쉽게 일처리할 수 있다.
모든 DB벤더가 python connector library (sqlalchemy, pymongo, pyscopg2… )제공하고 있기 때문에
예를 들어, 개발한 Dash App(Sentiment analysis app)은 python’s Snowflake connector를 통해 Snowflake DB에 접속해서, 고객데이터를 읽고, NLP sentiment analysis(자연어 처리를 통한 감정분석)을 수행하고,  Snapshot Engine을 통해 pdf로만들어진 보고서를 email로 전송한다.
horizontal scalingKubernetes Scaling
the only analytic app deployment platform that can scale to New York Times levels of traffic.

Dash applications are stateless by design – no information about the state of the client is stored on the Dash server. Instead, the client state (which users are logged in or which radio button is selected, etc) is bundled into each request to the Dash server.
Why is this important? With stateless design, Dash application servers can scale horizontally on modern infrastructure like Kubernetes.
Categories: dash

onesixx

Blog Owner

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x