체인 확장하기
조건부 드롭다운이 대성공이었어요! 대시보드가 깔끔해졌고 사용자 경험도 훨씬 좋아졌죠. 제품을 시연하는 동안 이해관계자가 몇 가지 업데이트를 요청했어요.
첫째, 그래프에 항상 무언가가 표시되도록 minor category의 기본값을 선택할 수 있게 해 달라고 했어요. 이를 위해 처음 만든 두 콜백 사이에 추가로 연결된(chained) 콜백을 하나 더 넣으면 될 것 같다고 생각했어요.
둘째, 그래프 아래에 제목을 넣어 사용자가 선택한 minor category가 어떤 major category에 속하는지 상기시켜 주고 싶다고 했어요. 별도의 콜백을 만드는 대신, 선택한 major category를 추가 출력으로 보내면 구현할 수 있다고 보았어요.
이 연습은 강의의 일부입니다
Dash와 Plotly로 대시보드 만들기
연습 안내
37번째 줄 아래에major_cat_dd드롭다운의 value에 의해 트리거되고,minor_cat_dd드롭다운의options와chosen_major_cat_title요소 모두로 출력하는 콜백을 만드세요.52번째 줄 아래에,minor_cat_dd드롭다운의options속성이 업데이트될 때 기본value를 설정하는 또 다른 콜백을 만드세요.
실습형 인터랙티브 연습
이 예제를 이 샘플 코드를 완성하여 풀어보세요.
from dash import Dash, dcc, html, Input, Output, callback
import plotly.express as px
import pandas as pd
import random
ecom_sales = pd.read_csv('/usr/local/share/datasets/ecom_sales.csv')
major_categories = list(ecom_sales['Major Category'].unique())
minor_categories = list(ecom_sales['Minor Category'].unique())
logo_link = 'https://assets.datacamp.com/production/repositories/5893/datasets/fdbe0accd2581a0c505dab4b29ebb66cf72a1803/e-comlogo.png'
ecom_country = ecom_sales.groupby('Country')['OrderValue'].agg(['sum', 'count']).reset_index().rename(columns={'count':'Sales Volume', 'sum':'Total Sales ($)'})
app = Dash()
app.layout = [
html.Img(src=logo_link, style={'margin':'30px 0px 0px 0px'}),
html.H1('Sales breakdowns'),
html.Div([
html.H2('Controls'),
html.Br(),
html.H3('Major Category Select'),
dcc.Dropdown(
id='major_cat_dd',
options=[{'label':category, 'value':category} for category in major_categories],
style={'width':'200px', 'margin':'0 auto'}),
html.Br(),
html.H3('Minor Category Select'),
dcc.Dropdown(
id='minor_cat_dd',
style={'width':'200px', 'margin':'0 auto'})],
style={'width':'350px', 'height':'350px', 'display':'inline-block',
'vertical-align':'top', 'border':'1px solid black', 'padding':'20px'}),
html.Div([
dcc.Graph(id='sales_line'),
html.H3(id='chosen_major_cat_title')],
style={'width':'700px', 'height':'650px','display':'inline-block'})
]
# Create a callback to set minor values and HTML output
@callback(
Output('____', '____'),
Output('____', 'children'),
Input('major_cat_dd', 'value'))
def update_minor_dd(major_cat_dd):
major_minor = ecom_sales[['Major Category', 'Minor Category']].drop_duplicates()
relevant_minor_options = major_minor[major_minor['Major Category'] == major_cat_dd]['Minor Category'].values.tolist()
minor_options = [{'label':x, 'value':x} for x in relevant_minor_options]
if not major_cat_dd:
major_cat_dd = 'None Selected'
major_cat_title = f'This is in the Major Category of: {major_cat_dd}'
return minor_options, major_cat_title
# Create a callback to set a default minor category value
@callback(
Output('____', '____'),
Input('____', '____'))
def select_minor_cat(options):
chosen_val = 'None'
if options:
vals = [x['value'] for x in options]
chosen_val = random.choice(vals)
return chosen_val
@callback(
Output('sales_line', 'figure'),
Input('minor_cat_dd', 'value'))
def update_line(minor_cat):
minor_cat_title = 'All'
ecom_line = ecom_sales.copy()
if minor_cat:
minor_cat_title = minor_cat
ecom_line = ecom_line[ecom_line['Minor Category'] == minor_cat]
ecom_line = ecom_line.groupby('Year-Month')['OrderValue'].agg('sum').reset_index(name='Total Sales ($)')
line_graph = px.line(ecom_line, x='Year-Month', y='Total Sales ($)', title=f'Total Sales by Month for Minor Category: {minor_cat_title}')
return line_graph
if __name__ == '__main__':
app.run(debug=True)