Hover to update another plot

The global e-commerce company is loving the innovation and new life your work is breathing into their tired old reports. A new challenge has been sent your way by the manager you recently built the key-stats hover dashboard for. While those words provided a great snapshot, a picture is worth a thousand words! The manager has asked if you could produce graphs that would show different subsets depending on what is being hovered over.

Your previous experience with using callbacks to filter data and regenerate figures, in combination with your recent work on hover triggering callbacks, should be just the perfect combination.

Este exercício faz parte do curso

Building Dashboards with Dash and Plotly

Ver Curso

Instruções de exercício

  • Add two components to the layout, which will render Plotly figures below line 30.
  • Create a callback that will update the minor category plot when hovering over the scatter plot below line 39.
  • Create a callback that will update the major category plot when hovering over the scatter plot below line 57.
  • Extract the country from the point that a user will hover over below line 65.

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')
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 ($)'})
ecom_scatter = px.scatter(ecom_country, x='Total Sales ($)', y='Sales Volume', color='Country', width=350, height=550, custom_data=['Country'])
ecom_scatter.update_layout({'legend':dict(orientation='h', y=-0.7,x=1, yanchor='bottom', xanchor='right')})

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.H3('Sales Volume vs Sales Amount by Country'),
          dcc.Graph(id='scatter', figure=ecom_scatter),
        ],
        style={'width':'350px', 'height':'650px', 'display':'inline-block', 
               'vertical-align':'top', 'border':'1px solid black', 'padding':'20px'}),
    html.Div(
      children=[
        # Add two plot types to the layout
        ____.____(id='major_cat'),
        ____.____(id='minor_cat'),
      ],
      style={'width':'700px', 'height':'650px','display':'inline-block'})
    ]),], 
  style={'text-align':'center', 'display':'inline-block', 'width':'100%'}
  )

# Create a callback to update the minor category plot
____.____(
    ____('minor_cat', 'figure'),
    ____('scatter', '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, 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

# Create a callback to update the major category plot
____.____(
    ____('____', 'figure'),
    ____('____', '____'))

def update_major_cat_hover(hoverData):
    hover_country = 'Australia'
    
    # Conditionally select the country from the hover data
    ____
        hover_country = ____['points'][0]['customdata'][0]

    major_cat_df = ecom_sales[ecom_sales['Country'] == hover_country]
    major_cat_agg = major_cat_df.groupby('Major Category')['OrderValue'].agg('sum').reset_index(name='Total Sales ($)')

    ecom_bar_major_cat = px.bar(major_cat_agg, x='Total Sales ($)', 
                                y='Major Category', height=300, 
                                title=f'Sales by Major Category for: {hover_country}', color='Major Category',
            color_discrete_map={'Clothes':'blue','Kitchen':'red', 'Garden':'green', 'Household':'yellow'})
    ecom_bar_major_cat.update_layout({'margin':dict(l=10,r=15,t=40,b=0), 'title':{'x':0.5}})

    return ecom_bar_major_cat

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