開始使用免費開始

點擊以更新另一個圖表

「滑過更新圖表」的功能大受好評。太神奇了!你的作品把原本乏味、靜態的視覺化,變成了有互動的體驗。

現在有個需求要調整你在上一節課建立的儀表板。這家電商公司的報表層級是:國家 → 大分類(major category)→ 小分類(minor category)。因此,他們希望滑過動作不要再更新底部的長條圖。

相反地,他們想要改成點擊「大分類」長條圖,來更新下方的長條圖。提出這個需求,是因為他們想比較不同國家之間,各大分類銷售占比的差異。

基於你剛完成的點擊與滑過互動功能,你完全知道該怎麼實作!

本練習屬於課程

使用 Dash 與 Plotly 建立儀表板

檢視課程

練習說明

  • 為了讓點擊資料中能取得 'Major Category',請在第 37 行下方的大分類長條圖中,將它加入 custom_data 參數。
  • 在第 45 行下方設定一個回呼:當點擊 major_cat 圖表中的任一長條時,更新 minor_cat 圖表。

動手互動練習

試著完成這個範例程式碼,體驗一下這個練習。

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')
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()

app.layout = [
  html.Img(src=logo_link, style={'margin':'30px 0px 0px 0px'}),
  html.H1('Sales breakdowns'),
  html.Div([
    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([
    dcc.Graph(id='major_cat'),
    dcc.Graph(id='minor_cat')],
    style={'width':'700px', 'height':'650px','display':'inline-block'})
]

@callback(
    Output('major_cat', 'figure'),
    Input('scatter', 'hoverData'))

def update_major_cat_hover(hoverData):
    hover_country = 'Australia'
    if hoverData:
        hover_country = hoverData['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 ($)',
                                # Ensure the Major Category will be available
                                ____=['Major Category'],
                                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

# Set up a callback for click data
@callback(
    Output('minor_cat', 'figure'),
    Input('____', '____'))

def update_major_cat_click(clickData):
    click_cat = 'All'
    major_cat_df = ecom_sales.copy()
    total_sales = major_cat_df.groupby('Country')['OrderValue'].agg('sum').reset_index(name='Total Sales ($)')
    if clickData:
        click_cat = clickData['points'][0]['customdata'][0]
    major_cat_df = ecom_sales[ecom_sales['Major Category'] == click_cat]
    country_mj_cat_agg = major_cat_df.groupby('Country')['OrderValue'].agg('sum').reset_index(name='Total Sales ($)')
    country_mj_cat_agg['Sales %'] = (country_mj_cat_agg['Total Sales ($)'] / total_sales['Total Sales ($)'] * 100).round(1)
    ecom_bar_country_mj_cat = px.bar(country_mj_cat_agg, x='Sales %', y='Country', 
                                     orientation='h', height=450, range_x = [0,100], text='Sales %', 
                                     title=f'Global Sales % by Country for Major Category: {click_cat}')
    ecom_bar_country_mj_cat.update_layout({'yaxis':{'dtick':1, 'categoryorder':'total ascending'}, 'title':{'x':0.5}})
    return ecom_bar_country_mj_cat  

if __name__ == '__main__':
    app.run(debug=True)
編輯並執行程式碼