Förbättra försäljningsdashboarden
E-handelsföretaget är mycket nöjda med ditt arbete och fortsätter att komma med nya kreativa idéer. Den här gången vill de ha en kraftfull dashboard som samlar allt du byggt hittills i ett interaktivt gränssnitt.
De önskar nu:
- Ett linjediagram över månadsförsäljning filtrerat efter huvud- och underkategorier.
- En rullgardinsmeny för varje kategori, där underkategorialternativen uppdateras baserat på vald huvudkategori.
- En tabell med aggregerad statistik för dessa kategorier.
- Ett stapeldiagram över total försäljning per land.
- Ytterligare ett stapeldiagram som visar försäljning per underkategori och uppdateras när du hovrar över landsdiagrammet.
Du har redan byggt alla delar – nu är det dags att sätta ihop dem!
Den här övningen är en del av kursen
Bygg dashboards med Dash och Plotly
Övningsinstruktioner
- Aktivera paginering för
gridgenom att ange parameternpaginationnedanför rad23. - Begränsa varje sida till 6 rader genom att ange parametern
paginationPageSizenedanför rad26. - Infoga
grid-objektet i listan förapp.layoutnedanför rad49.
Interaktiv övning med praktiskt arbete
Testa den här övningen genom att slutföra den här exempelkoden.
from dash import Dash, dcc, html, Input, Output, callback
import plotly.express as px
import pandas as pd
from dash_ag_grid import AgGrid
ecom_sales = pd.read_csv('/usr/local/share/datasets/ecom_sales.csv')
logo_link = 'https://assets.datacamp.com/production/repositories/5893/datasets/fdbe0accd2581a0c505dab4b29ebb66cf72a1803/e-comlogo.png'
major_categories = list(ecom_sales['Major Category'].unique())
large_tb = ecom_sales.groupby(['Major Category', 'Minor Category'])['OrderValue'].agg(['sum', 'count', 'mean']).reset_index().rename(columns={'count':'Sales Volume', 'sum':'Total Sales ($)', 'mean':'Average Order Value ($)'})
ecom_country = ecom_sales.groupby('Country')['OrderValue'].agg('sum').reset_index(name='Total Sales ($)')
bar_fig_country = px.bar(ecom_country, x='Total Sales ($)', y='Country', width=500, height=450, title='Total Sales by Country (Hover to filter the Minor Category bar chart!)', custom_data=['Country'], color='Country', color_discrete_map={'United Kingdom':'lightblue', 'Germany':'orange', 'France':'darkblue', 'Australia':'green', 'Hong Kong':'red'})
money_fmt = {"function": ("params.value.toLocaleString('en-US', {style: 'currency', currency: 'USD'})")}
column_defs = [
{"field": "Major Category"},
{"field": "Total Sales ($)", "valueFormatter": money_fmt},
{"field": "Average Order Value ($)", "valueFormatter": money_fmt},
{"field": "Sales Volume"}
]
grid = AgGrid(
columnDefs=column_defs,
rowData=large_tb.to_dict("records"),
# Turn on pagination
dashGridOptions={
"____": ____,
# Show 6 rows per page
"____": ____}
)
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':'360px', 'display':'inline-block', 'vertical-align':'top', 'border':'1px solid black', 'padding':'20px'}),
html.Div([
html.H3(id='chosen_major_cat_title'),
dcc.Graph(id='sales_line')],
style={'width':'700px', 'height':'380px','display':'inline-block', 'margin-bottom':'5px'}),
# Insert the AG Grid
____,
html.Div([
html.Div(dcc.Graph(id='major_cat', figure=bar_fig_country), style={'display':'inline-block'}),
html.Div(dcc.Graph(id='minor_cat'), style={'display':'inline-block'})],
style={'width':'1000px', 'height':'650px','display':'inline-block'})
]
@callback(
Output('minor_cat_dd', 'options'),
Output('chosen_major_cat_title', 'children'),
Input('major_cat_dd', 'value'))
def update_dd(major_cat_dd):
major_minor = ecom_sales[['Major Category', 'Minor Category']].drop_duplicates()
relevant_minor = major_minor[major_minor['Major Category'] == major_cat_dd]['Minor Category'].values.tolist()
minor_options = [dict(label=x, value=x) for x in relevant_minor]
if not major_cat_dd:
major_cat_dd = 'ALL'
major_cat_title = f'This is in the Major Category of : {major_cat_dd}'
return minor_options, major_cat_title
@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}', height=350)
return line_graph
@callback(
Output('minor_cat', 'figure'),
Input('major_cat', 'hoverData'))
def update_min_cat_hover(hoverData):
hover_country = 'Australia'
if hoverData:
hover_country = hoverData['points'][0]['customdata'][0]
minor_cat_df = ecom_sales[ecom_sales['Country'] == hover_country]
minor_cat_agg = minor_cat_df.groupby('Minor Category')['OrderValue'].agg('sum').reset_index(name='Total Sales ($)')
ecom_bar_minor_cat = px.bar(minor_cat_agg, x='Total Sales ($)', y='Minor Category', orientation='h', height=450, width=480,title=f'Sales by Minor Category for: {hover_country}')
ecom_bar_minor_cat.update_layout({'yaxis':{'dtick':1, 'categoryorder':'total ascending'}, 'title':{'x':0.5}})
return ecom_bar_minor_cat
if __name__ == '__main__':
app.run(debug=True)