Options conditionnelles dans un menu déroulant
Un responsable des achats senior de l’entreprise e-commerce a posé un problème intéressant. Leur tableau de bord actuel, qui affiche les ventes par mois pour des sous-catégories d’articles, comporte un menu déroulant à deux niveaux (catégorie principale et sous-catégorie) avec bien trop d’options. On vous signale en particulier qu’il est agaçant de voir apparaître, dans le second menu, des options qui ne sont pas sélectionnables.
Vous rassurez la partie prenante : vous pouvez aider — c’est une excellente occasion d’utiliser des callbacks chaînés pour créer un menu déroulant conditionnel.
Cet exercice fait partie du cours
<cours>Créer des tableaux de bord avec Dash et Plotly</cours>Instructions de l’exercice
- Créez un callback sous la ligne
31pour mettre à jour lesoptionsdu menu déroulantminor_cat_dden fonction de la valeur du menu déroulantmajor_cat_dd. - Reformatez la variable
relevant_minor_options(sous la ligne39) en une liste de dictionnaires avec des cléslabeletvalueidentiques. - Créez un autre callback sous la ligne
43qui met à jour lafiguredu graphesales_lineen fonction de la valeur du menu déroulantminor_cat_dd.
Exercice interactif pratique
Essayez cet exercice en complétant ce code d’exemple.
from dash import Dash, dcc, html, Input, Output, callback
import plotly.express as px
import pandas as pd
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'}),
dcc.Graph(id='sales_line',style={'width':'700px', 'height':'650px','display':'inline-block'})
]
# Create a callback from the Major Category dropdown to the Minor Category Dropdown
@callback(
Output('____', '____'),
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()
# Set up the Major Category options with the same label and value
formatted_relevant_minor_options = [{'label':____, 'value':____} for ____ in ____]
return formatted_relevant_minor_options
# Create a callback for the Minor Category dropdown to update the line plot
@callback(
Output('____', '____'),
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)