개발/Dash

[Dash]Python Dash를 활용한 Dashboard 구축하기

moonzoo 2024. 1. 12. 13:30

 

 

 

1. DASH?

  • Dash는 Flask, Plotly.js  React.js 위에 작성된 Python 웹서비스 개발용 프레임워크로 Plotly에 기반하고 있음
  • Dash는 Python과 HTML을 이용하여 쉽게 웹사이트나 대시보드 같은 대화형 웹응용프로그램을 작성할 수 있음

Dash는 데이터 시각화 및 웹 애플리케이션을 구현하는데 유용하게 사용할 수 있습니다. 

출처 : http://bigdata.dongguk.ac.kr/lectures/datascience/_book/a4.-dash%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-python-dashboard.html

 

 

2. Dash 설치 (feat. anaconda)

우선 가상환경을 먼저 구축하도록 하겠습니다.

가상환경을 구축하는 방법은 아래 게시글을 참고하시면 될 것 같습니다.

https://mz-moonzoo.tistory.com/4

 

[Environment]아나콘다 가상환경 구성 및 주피터 노트북 커널 연결

INTRO 가상환경은 개발을 진행할 때 각 프로젝트 별로 요구하는 패키지가 다를 때 사용하면 유용하다. 하나의 환경으로만 작업을 진행하다보면 패키지끼리 버전이 맞지 않아서 충돌이 발생하는

mz-moonzoo.tistory.com

 

가상환경 구축이 완료됐다면,

pip install dash

Dash를 설치해주도록 합니다.

 

3. Dash 구성요소

Dash 애플리케이션은 Layout과 Callback 두 부분으로 나뉩니다.

 

1. Dash Layout

레이아웃은 Dash 애플리케이션의 사용자 인터페이스(UI)를 정의하는 부분입니다. 이는 HTML과 유사한 구조를 가지며, Dash Core Components와 HTML Components를 사용하여 구성됩니다.

 

1-1. Dash Core Components

Dash Core Components는 대부분의 대화형 컴포넌트를 제공하는 라이브러리입니다. 몇 가지 주요 컴포넌트에는 dcc.Graph, dcc.Dropdown, dcc.Input 등이 있습니다.

 

아래와 같이 그래프와 드롭다운 메뉴를 포함하는 간단한 레이아웃을 만들 수 있습니다.

import dash_core_components as dcc
import dash_html_components as html

layout = html.Div([
    html.H1("My Dash App"),
    dcc.Graph(id='my-graph'),
    dcc.Dropdown(
        id='my-dropdown',
        options=[
            {'label': 'Option 1', 'value': 'opt1'},
            {'label': 'Option 2', 'value': 'opt2'}
        ],
        value='opt1'
    )
])

 

1-2. HTML Components

HTML Components는 HTML 태그를 사용하여 추가적인 요소를 레이아웃에 포함할 수 있습니다.

 

import dash_html_components as html

layout = html.Div([
    html.H1("Hello Dash!"),
    html.P("This is a paragraph."),
    html.Button("Click me", id='my-button')
])

 

2. Dash Callback

콜백은 입력이나 상태의 변경에 따라 애플리케이션의 레이아웃을 동적으로 업데이트하는 데 사용됩니다. 콜백은 Python 함수로 정의되며, 데코레이터를 사용하여 입력 및 출력을 지정합니다.

 

@app.callback(decorator)와 callback 함수를 통해 작동

@app.callback(decorator)는 입력(input)과 출력(output)으로 구성

 

from dash.dependencies import Input, Output

@app.callback(
    Output('my-output', 'children'),
    [Input('my-input', 'value')]
)
def update_output(value):
    return f'You entered: {value}'

위의 예제에서, update_output 함수는 'my-input'이라는 입력 컴포넌트의 값이 변경될 때 호출되어 'my-output'이라는 출력 컴포넌트의 내용을 업데이트합니다.

 

3. Dash 서버 구동

Dash 애플리케이션을 실행하려면 내장된 Flask 서버를 사용하게 됩니다. 다음과 같이 애플리케이션을 실행할 수 있습니다.

 

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

 

 

4. Dash 실습

 

데이터 준비

우선 데이터를 준비하도록 하겠습니다. 아래의 링크에서 데이터를 다운해서 원하는 data 폴더에 넣어주시면 됩니다.

https://drive.google.com/file/d/19xeIpigGi9ti51_GfJuRCb9GKv4nR0dB/view

 

intro_bees.csv

 

drive.google.com

다음으로 pandas 라이브러리를 통해 다운받은 데이터를 불러오시고 간단한 데이터 전처리를 진행했습니다.

 

  1. df: 코드에서 사용되는 데이터프레임을 나타냅니다.
  2. groupby(['State', 'ANSI', 'Affected by', 'Year', 'state_code']): 데이터프레임을 'State', 'ANSI', 'Affected by', 'Year', 'state_code' 열들을 기준으로 그룹화합니다. 이는 특정 열들의 값에 따라 데이터를 그룹으로 묶는 것을 의미합니다.
  3. [['Pct of Colonies Impacted']]: 그룹화된 데이터프레임에서 'Pct of Colonies Impacted' 열만을 선택합니다. 이는 해당 열의 데이터만을 가져오기 위한 것입니다.
  4. .mean(): 선택된 'Pct of Colonies Impacted' 열에 대해 평균을 계산합니다. 그룹화된 데이터프레임에서 각 그룹의 평균 값을 계산합니다.

결과적으로, 코드는 'State', 'ANSI', 'Affected by', 'Year', 'state_code' 열들을 기준으로 그룹화된 데이터프레임에서 'Pct of Colonies Impacted' 열의 평균 값을 계산합니다.

 

Dash Layout

해당 코드는 Dash 라이브러리를 사용하여 웹 애플리케이션의 레이아웃을 정의하는 파트입니다. 아래는 코드의 각 부분에 대한 설명입니다.

  1. app.layout : 이 코드는 Dash 애플리케이션의 전체 레이아웃을 정의합니다. html.Div를 사용하여 여러 HTML 요소들을 포함한 전체 레이아웃을 생성합니다.
  2. html.H1("Web Application Dashboards with Dash", style={'text-align': 'center'}) : 이 부분은 웹 애플리케이션의 제목을 설정합니다. "Web Application Dashboards with Dash"라는 텍스트를 H1(제목) 태그로 표시하고, 이를 페이지 중앙에 정렬하기 위해 style 속성을 사용합니다.
  3. dcc.Dropdown : 이 부분은 드롭다운 메뉴를 정의합니다. 사용자가 선택할 수 있는 옵션은 2015, 2016, 2017, 2018로 구성되어 있습니다. 이 드롭다운 메뉴의 현재 선택된 값을 나타내는 변수로 slct_year를 사용하며, options 인자를 사용하여 사용자에게 보여질 옵션을 설정합니다.
  4. html.Div(id='output_container', children=[]) : 이 부분은 애플리케이션에서 사용되지 않고 있습니다. 하지만 일반적으로는 여러 결과를 표시하기 위해 사용됩니다. 이 예제에서는 해당 부분이 비어있습니다.
  5. html.Br() : 이 부분은 빈 줄을 만들어 주는 <br>(줄 바꿈) 태그를 추가합니다. 이를 통해 드롭다운 메뉴와 그래프 사이에 공백을 만듭니다.
  6. dcc.Graph(id='my_bee_map', figure={}) : 이 부분은 Dash에서 그래프를 표시하기 위한 부분입니다. id 속성으로 그래프를 식별하고, 초기에는 빈 그래프를 표시하기 위해 figure 속성에 빈 딕셔너리를 전달합니다. 이후 콜백 함수를 통해 그래프가 업데이트될 것입니다.

Dash Callback

이 코드는 Dash 애플리케이션에서 사용되는 콜백을 정의하는 부분입니다. 이 콜백은 드롭다운 메뉴에서 선택된 연도에 따라 그래프를 업데이트하는 역할을 합니다. 여러 개의 입력과 출력을 사용하여 다양한 작업을 수행합니다.

  1. @app.callback : 이 부분은 데코레이터를 사용하여 콜백 함수를 정의하는데, 이 함수는 입력이 변경될 때마다 호출됩니다.
  2. Output(component_id='output_container', component_property='children') : 이 부분은 콜백 함수의 첫 번째 출력을 정의합니다. output_container이라는 ID를 가진 HTML Div 요소의 children 속성에 대한 출력입니다.
  3. Output(component_id='my_bee_map', component_property='figure') : 이 부분은 콜백 함수의 두 번째 출력을 정의합니다. my_bee_map이라는 ID를 가진 Plotly 그래프의 figure 속성에 대한 출력입니다.
  4. Input(component_id='slct_year', component_property='value') : 이 부분은 콜백 함수의 입력을 정의합니다. slct_year이라는 ID를 가진 드롭다운 메뉴의 value 속성에 대한 입력입니다.
  5. def update_graph(option_slctd) : 이 부분은 콜백 함수를 정의합니다. 함수의 입력 option_slctd는 드롭다운 메뉴에서 선택된 연도의 값입니다.
  6. container = "The year chosen by user was: {}".format(option_slctd) : 이 부분은 출력 컨테이너의 내용을 설정합니다. 사용자가 선택한 연도에 대한 정보를 문자열로 포맷하여 컨테이너에 저장합니다.
  7. dff = df.copy() : 원본 데이터프레임을 복사하여 새로운 데이터프레임 dff를 생성합니다.
  8. dff = dff[dff["Year"] == option_slctd] : 선택된 연도에 해당하는 데이터만을 필터링하여 dff를 업데이트합니다.
  9. dff = dff[dff["Affected by"] == "Varroa_mites"] : "Varroa_mites"에 영향을 받는 데이터만을 선택하여 dff를 다시 업데이트합니다.
  10. fig = px.choropleth(...) : Plotly Express를 사용하여 등치 맵을 생성합니다. 선택된 연도와 영향을 받는 요인에 따라 색상이 지정된 미국 지도를 생성합니다.
  11. return container, fig : 콜백 함수는 두 개의 출력을 반환합니다. 첫 번째는 출력 컨테이너의 내용을, 두 번째는 생성된 그래프를 나타냅니다. 이 두 개의 출력은 콜백 데코레이터에서 정의한 순서대로 반환되어야 합니다.

 

Dash 서버 구동

드롭다운의 slct_year에 따라 그래프를 업데이트하며 확인할 수 있습니다.

 

 

5. 마치며

Dash 라이브러리를 활용하여 데이터 시각화부터 웹 애플리케이션 구현까지. 그리고 머신러닝, 딥러닝 모델의 인퍼런스 대시보드까지 구축할 수 있습니다. 앞으로 다양한 Dash 기능을 사용해 여러가지 대시보드를 구현해보도록 하겠습니다.