Bắt đầu ngayBắt đầu miễn phí

Nâng cấp bảng điều khiển doanh số

Công ty thương mại điện tử rất ấn tượng với công việc của bạn và liên tục đưa ra những ý tưởng sáng tạo mới. Lần này, họ muốn một bảng điều khiển mạnh mẽ kết hợp mọi thứ bạn đã xây dựng cho đến nay vào một giao diện tương tác duy nhất.

Hiện họ muốn có:

  • Biểu đồ đường doanh số theo tháng được lọc theo danh mục chính và phụ.
  • Một hộp chọn cho mỗi danh mục, trong đó các lựa chọn danh mục phụ sẽ cập nhật dựa trên danh mục chính được chọn.
  • Một bảng hiển thị các số liệu tổng hợp cho các danh mục đó.
  • Biểu đồ cột tổng doanh số theo quốc gia.
  • Một biểu đồ cột khác hiển thị doanh số theo danh mục phụ và cập nhật khi bạn hover lên biểu đồ quốc gia.

Bạn đã xây xong tất cả các phần — giờ là lúc ghép chúng lại!

Bài tập này là một phần của khóa học

Xây dựng Dashboard với Dash và Plotly

Xem khóa học

Hướng dẫn bài tập

  • Bật phân trang cho grid bằng cách đặt tham số pagination bên dưới dòng 23.
  • Giới hạn mỗi trang hiển thị 6 hàng bằng cách đặt tham số paginationPageSize bên dưới dòng 26.
  • Chèn đối tượng grid vào danh sách app.layout bên dưới dòng 49.

Bài tập tương tác thực hành trực tiếp

Hãy thử làm bài tập này bằng cách hoàn thành đoạn mã mẫu này.

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)
Chỉnh sửa và Chạy Mã