I am trying to update a plotly graph dash with two different dropdowns as inputs.
This is my sample dataframe:
import pandas as pd
df1 = {'category' : ['A','A','A','B','B','B'],'subcategory' : ['x', 'y', 'z', 'x1','y1','z1'],
'x_coord' : [1, 2,3,2,2,2],'y_coord' : [1,3,2,1,3,2]}
df_test = pd.DataFrame(df1)
df_test
And what I pretend to do is if I select category A, that plots in a scatter all the correspondent points to the category, but If Also I select a subcategory that modifies the graph plotting only the correspondent category-subcategory point of the dataframe.
The code is below, and it works if I only add the callback of the first dropdown, but when I add the second callback to the subcategory it doesn't work. I am following the suggestions in the dash plotly tutorial where it says:
A word of caution: it's not always a good idea to combine Outputs, even if you can: If the Outputs depend on some but not all of the same Inputs, keeping them separate can avoid unnecessary updates. If they have the same Inputs but do independent computations with these inputs, keeping the callbacks separate can allow them to run in parallel.
But anyway if I put the output in separate callbacks or in the same I cannot make it work, here is the code that I am trying (using jupyter notebook):
import dash
import plotly as py
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
from jupyter_plotly_dash import JupyterDash
py.offline.init_notebook_mode(connected = True)
app = JupyterDash('Test')
app.layout = html.Div([
dcc.Dropdown(id='dropdown1',
options=[{'label':i, 'value':i} for i in df_test['category'].unique()]),
dcc.Dropdown(id='dropdown2',
options=[{'label':i, 'value':i} for i in df_test['subcategory'].unique()]),
dcc.Graph(id='graphic')
])
@app.callback(
Output('dropdown2', 'options'),
[Input('dropdown1', 'value')])
def update_drop2(selected_drop):
filtered_df = df_test[(df_test.category == selected_drop)]
return [{'label':i, 'value':i} for i in filtered_df['subcategory'].unique()]
@app.callback(
Output('graphic', 'figure'),
[Input('dropdown1', 'value')])
def update_figure(selected_drop):
filtered_df = df_test[(df_test.category == selected_drop)]
fig = go.Figure()
fig.add_trace(go.Scatter(x=filtered_df.x_coord,y=filtered_df.y_coord, marker = dict(size=15, color='green'), mode='markers'))
return fig
@app.callback(
Output('graphic', 'figure'),
[Input('dropdown2', 'value')])
def update_figure(selected_drop):
filtered_df = df_test[(df_test.subcategory == selected_drop)]
fig = go.Figure()
fig.add_trace(go.Scatter(x=filtered_df.x_coord,y=filtered_df.y_coord, marker = dict(size=15, color='green'), mode='markers'))
return fig
app
If I use multiple inputs on the callback like this:
@app.callback(
Output('graphic', 'figure'),
[Input('dropdown1', 'value'), Input('dropdown2', 'value')])
def update_figure(selected_drop1, selected_drop2):
if not selected_drop2:
filtered_df = df_test[(df_test.category == selected_drop1)]
else:
filtered_df = df_test[(df_test.category == selected_drop1) &
(df_test.subcategory == selected_drop2)]
fig = go.Figure()
fig.add_trace(go.Scatter(x=filtered_df.x_coord,y=filtered_df.y_coord,
marker = dict(size=15, color='green'), mode='markers'))
return fig
It works better (or more near what I pretend), but however when I switch between categories I see no data.
Thanks in advance for your help and reccomendations.
