Hello community,
Recently I was looking into adding drill down capabilities in my Dash App.
For those unaware about drill down analysis, it enables the user to have a deeper look into the data.
I found some similar questions posted online before
Some were still unanswered:
Then I found this old thread on the forum - Drill down function for graphs embedded in Dash app
You’ll find some smart ideas discussed here with a few examples to achieve drill down. But the thread is old and the examples were a bit complex.
So I thought about sharing a MWE for others looking into it in future.
In this example I am showcasing just a single level drill down to keep it simple but with few modifications multi -level drill down can be achieved.
There’s a back button for going back to the original figure. The back button is shown only on the level two of the drill down and hides on the original bottom level.
Code:
import dash
import dash_core_components as dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
# creating a dummy sales dataframe
product_sales = {'vendors':['VANS','VANS','VANS','VANS','NIKE','NIKE','NIKE','ADIDAS','ADIDAS','CONVERSE','CONVERSE','CONVERSE'],
'products': ['Tshirts','Sneakers','Caps','Clothing','Sports Outfit','Sneakers','Caps','Accessories','Bags','Sneakers','Accessories','Tshirts'],
'units sold': [2,15,3,8,37,13,7,4,12,7,8,2]
}
product_sales_df = pd.DataFrame(product_sales)
# all vendors sales pie chart
def sales_pie():
df = product_sales_df.groupby('vendors').sum().reset_index()
fig = px.pie(df, names='vendors',
values='units sold', hole=0.4)
fig.update_layout(template='presentation', title='Sales distribution per Vendor')
return fig
# creating app layout
app.layout = dbc.Container([
dbc.Card([
dbc.Button('🡠', id='back-button', outline=True, size="sm",
className='mt-2 ml-2 col-1', style={'display': 'none'}),
dbc.Row(
dcc.Graph(
id='graph',
figure=sales_pie()
), justify='center'
)
], className='mt-3')
])
#Callback
@app.callback(
Output('graph', 'figure'),
Output('back-button', 'style'), #to hide/unhide the back button
Input('graph', 'clickData'), #for getting the vendor name from graph
Input('back-button', 'n_clicks')
)
def drilldown(click_data,n_clicks):
# using callback context to check which input was fired
ctx = dash.callback_context
trigger_id = ctx.triggered[0]["prop_id"].split(".")[0]
if trigger_id == 'graph':
# get vendor name from clickData
if click_data is not None:
vendor = click_data['points'][0]['label']
if vendor in product_sales_df.vendors.unique():
# creating df for clicked vendor
vendor_sales_df = product_sales_df[product_sales_df['vendors'] == vendor]
# generating product sales bar graph
fig = px.bar(vendor_sales_df, x='products',
y='units sold', color='products')
fig.update_layout(title='<b>{} product sales<b>'.format(vendor),
showlegend=False, template='presentation')
return fig, {'display':'block'} #returning the fig and unhiding the back button
else:
return sales_pie(), {'display': 'none'} #hiding the back button
else:
return sales_pie(), {'display':'none'}
if __name__ == '__main__':
app.run_server(debug=True)
Thank you