Conditional dropdown options
A senior purchasing officer in the e-commerce company has posed an interesting problem. Their existing dashboard, showing sales by month for minor categories of items, has a two-level dropdown (major category and minor category) with way too many options in it. It is especially annoying, you are told, that some options appear in the second dropdown that can not be selected.
You assure the stakeholder you can assist - it is a great opportunity for you to use chained callbacks to produce a conditional dropdown.
Este exercício faz parte do curso
Building Dashboards with Dash and Plotly
Instruções de exercício
- Use the
major_categories
list created for you on line8
to set up the Major Category options for that dropdown below line28
with the same value and label for each option. - Create a callback triggered by the major category dropdown (
major_cat_dd
) that updates the minor category dropdown (minor_cat_dd
) options to be only those relevant below line47
. - Reformat
relevant_minor_options
(created on line55
) into a list of dictionaries below line57
so it can be used in the Dash dropdown. - Create a callback triggered by the minor category dropdown that will update the line figure (
sales_line
) upon selection of an option below line61
.
Exercício interativo prático
Experimente este exercício preenchendo este código de exemplo.
import dash
from dash import dcc, html
import plotly.express as px
import pandas as pd
from dash.dependencies import Input, Output
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.Dash(__name__)
app.layout = html.Div([
html.Img(src=logo_link,
style={'margin':'30px 0px 0px 0px' }),
html.H1('Sales breakdowns'),
html.Div(
children=[
html.Div(
children=[
html.H2('Controls'),
html.Br(),
html.H3('Major Category Select'),
dcc.Dropdown(
id='major_cat_dd',
# Set up the Major Category options with the same label and value
options=[{'label':____, 'value':____} for category in ____],
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(
children=[
dcc.Graph(id='sales_line')],
style={'width':'700px', 'height':'650px','display':'inline-block'})
]),],
style={'text-align':'center', 'display':'inline-block', 'width':'100%'})
# Create a callback from the Major Category dropdown to the Minor Category Dropdown
@app.callback(
Output('____', '____'),
Input('____', '____'))
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()
# Create and return formatted relevant options with the same label and value
formatted_relevant_minor_options = [{'label':x, 'value':x} for x in ____]
return ____
# Create a callback for the Minor Category dropdown to update the line plot
@app.callback(
Output('____', '____'),
Input('____', '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_server(debug=True)