본문 바로가기
데이터분석 및 데이터엔지니어/파이썬

파이썬 python plotly dash를 이용하여 대시보드 만들기 (1)

by na.__.na 2023. 7. 26.

파이썬에서 그래프를 그리는 방법은 크게 3가지인데, 

1. matplotlib

2. seaborn

3. plotly

이다. 

개인적으로 1 < 2 < 3 순서로 그래프가 이쁘게 그려지고 코드 쓰기 좀 더 복잡하다고 느낀다. 

암튼, 최근 plotly dash 만드는 법을 배웠는데 

예시 코드를 봐도 이해 안되는 점도 많고 더 공부가 필요할 것같아서 블로그에 그릴 수 있는 대시보드들을 저장해두고자 한다.

 

작업은 주피터노트북에서 하며, 패키지는 미리 불러왔다고 가정한다. 

불러온 패키지는 다음과 같다. 이는 dash만을 위한 것은 아니고 전처리와 시각화를 위한 패키지도 포함되어있다. 

import pandas as pd

import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Malgun Gothic'

import matplotlib as mpl
mpl.rcParams['axes.unicode_minus'] = False

%matplotlib inline

import seaborn as sns
import numpy as np
from scipy import stats

 

그 중 dash를 위한 패키는 아래와 같다.

from dash import Dash, html, dcc, Input, Output, callback, dash_table
import pandas as pd
import plotly.express as px

 

데이터는 케글의 데이터과학자 연봉 데이터를 사용함 (https://www.kaggle.com/datasets/iamsouravbanerjee/data-science-salaries-2023?resource=download) 


1. 기본 그래프 (히스토그램) 1개 

 

직업에 따른 급여평균을 회사 규모별로 시각화하였다. 

회사 규모가 클수록 급여가 높을 것이라 생각했는데, 의외로 중간 규모의 평균 급여가 가장 높았다.

물론 히스토그램 하나만 가지고 판단할 순 없다. 

app = Dash(__name__)

# html.Div : 구역 나누기 
app.layout = html.Div([
    html.H1(children = '제목', style = {'textAlign':'center'}), # 제목 입력
    dcc.Dropdown(df['Job Title'].unique(), 'Data Engineer', id = 'dropdown-selection'),
    # 목록에 띄울 기준의 카테고리, 그 중 처음에 보여줄 것, id 지정 
    dcc.Graph(id = 'graph')
    # 그래프 id 지정 
])

@callback(
    Output('graph', 'figure'),
    Input('dropdown-selection', 'value')
)

def update_graph(value):
    dff = df[df['Job Title'] == value]
    fig = px.histogram(dff, x='Company Size', y='Salary in USD', histfunc='avg')
    return fig

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

 

2. 그래프 아래 표가 1개씩 있는 대시보드

app = Dash(__name__)

# html.Div : 구역 나누기 
app.layout = html.Div([
    html.H1(children = '회사 규모별 급여 차이', style = {'textAlign':'center'}), # 제목 입력
    dcc.Dropdown(df['Job Title'].unique(), 'Data Engineer', id = 'dropdown-selection'),
    # 목록에 띄울 기준의 카테고리, 그 중 처음에 보여줄 것, id 지정 
    dcc.Graph(id = 'graph'),
    # 그래프 id 지정 
    dash_table.DataTable(data = df2.to_dict('records'), page_size=5)
    # 새로 추가된 코드 
    # 그래프 아래 테이블 추가 
    # page_size : 한페이지에 몇 줄을 보여줄 것인가
])

@callback(
    Output('graph', 'figure'),
    Input('dropdown-selection', 'value')
)

def update_graph(value):
    dff = df[df['Job Title'] == value]
    fig = px.histogram(dff, x='Company Size', y='Salary in USD', histfunc='avg')
    return fig

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

 

3-1. 표와 그래프가 양옆으로 보여지는 대시보드 

 

드롭다운 대신 라디오 버튼을 사용해보았다.

라디오 버튼에는 적은 그룹을 보여주는게 적합하기때문에 직업과 회사규모의 위치를 바꿨다. 

직업이 너무 많아 시각화로 보기에 적합하지 않다. 

Data Engineer(21%),Data Scientist(19%)이다. 

비슷한 직업을 묶어주거나 너무 적은 그룹 또는 유니크한 직업은 '그외'로 묶어서 가짓수를 줄인 후 시각화하는 것이 원하는 바를 더 잘 보여줄 것으로 생각된다.

# 표-그래프 

# css 
# className 변경없이 그대로 맞춰야 해당 모양이 나옴 
# className을 사용하지 않을경우 위아래로 출력됨 

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

# app = Dash(__name__)

# 구역 1
app.layout = html.Div([
    html.H3(children = '직업별 급여', style = {'textAlign':'center'}), # 제목 입력
    # 구역 2-1
    html.Div(className='row', children=[ 
        dcc.RadioItems(options=df['Company Size'].unique(),
                      value='Medium',
                      inline=True, # RadioItems 한줄로 출력. 
                      id = 'radio-buttons')
    ]),
    
    # 구역 2-2
    html.Div([
        #구역 3-1
        html.Div(className='six columns', children=[
            dash_table.DataTable(data = df2.to_dict('records'), page_size=10)
        ], style={'width': '26%', 'float': 'left', 'display': 'inline-block'}), # 가로 사이즈를 25%로 조정 
        
        #구역 3-2
        html.Div(className='six columns', children=[
            dcc.Graph(figure={}, id = 'graph')
        ], style={'width': '66%', 'float': 'right', 'display': 'inline-block'}) # 가로 사이즈를 65%로 조정 
        # 구역 3-1과 구역 3-2 가로 비율의 합이 100%면 사이즈가 좁아서 위아래 배치가 된다 
    ])
])

@callback(
    Output('graph', 'figure'),
    Input('radio-buttons', 'value')
)

def update_graph(value):
    dff = df[df['Company Size'] == value]
    fig = px.histogram(dff, x='Job Title', y='Salary in USD', histfunc='avg')
    return fig

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

 

3-2. 그래프와 그래프가 양옆으로 보여지는 대시보드

 

표와 그래프 대시보드와 구간 설정은 비슷하지만 드롭다운을 고려해주어야하기때문에 조금 더 복잡할 수 있다. 

 

plotly dash 제목 색 바꾸는 법 / 그래프 2개 그리는 법 

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

# 구역1
app.layout = html.Div([
    # 구역2
    # H가 아니라 구역 설정 후 제목을 입력할 수도 있다 
    html.Div(className='row', children='Experience와 Expertise에 따른 급여', 
             style={'textAlign': 'center', 'color': 'darkred', 'fontSize': 30}),
    
    html.Div([
        dcc.Dropdown(df['Job Title'].unique(), 'Data Engineer', id = 'dropdown-selection'),
    ]),
    
    html.Div([
        html.Div([
            dcc.Graph(figure={}, id='graph-1')
        ], style={'width': '49%', 'float': 'left', 'display': 'inline-block'}),
        html.Div([
            dcc.Graph(figure={}, id='graph-2')
        ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})
    ])
])

@callback(
    Output(component_id='graph-1', component_property='figure'),
    Input(component_id='dropdown-selection', component_property='value')
)

def update_graph(value):
    dff = df[df['Job Title'] == value]
    fig = px.histogram(dff, x='Experience Level', y='Salary in USD')
    return fig

@callback(
    Output(component_id='graph-2', component_property='figure'),
    Input(component_id='dropdown-selection', component_property='value')
)

def update_graph2(value):
    dff = df[df['Job Title'] == value]
    fig = px.histogram(dff, x='Expertise Level', y='Salary in USD')
    return fig

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

 


간단한 대시보드는 (1)에서 해보았고,

더 복잡한 대시보드 만들기는 다음 시리즈에서 이어서 계속 적어볼 예정입니다. 

 

전체 코드는 github에서 확인할 수 있습니다. 

 

https://github.com/hannah-OH/Python/blob/master/study/%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C_%EC%97%B0%EC%8A%B5.ipynb