Issue
I would like to generate a graph and table from a dash callback, but the code outputs one or the other.
Below is the final part of the code. The data is filtered by chained callbacks (two drop-downs - LGA and SMA) and a radio button (standard deviation picker).
Is there a simple way to generate the two outputs or do I need to add in another callback and define additional functions?
html.Div(
id='graph-container',
children=[]),
dash_table.DataTable(
id='table-container',
columns = [{"name": i, "id": i} for i in df],
data=df.to_dict('records'),
),
])
Populate the SMA's dropdown with options and values
@app.callback(
Output('SMA-dpdn', 'options'),
Output('SMA-dpdn', 'value'),
Input('LGA-dpdn', 'value'),
)
def set_LGA_options(chosen_LGA):
dff = df[df.LGA==chosen_LGA]
SMAs_of_LGAs = [{'label': c, 'value': c} for c in sorted(dff.SMA.unique())]
values_selected = [x['value'] for x in SMAs_of_LGAs]
return SMAs_of_LGAs, values_selected
@app.callback(
Output('graph-container', 'children'),
Output('table-container', 'data'),
Input('radio_items', 'value'),
Input('SMA-dpdn', 'value'),
Input('LGA-dpdn', 'value'),
prevent_initial_call=True
)
Create graph/table component and populate
def graph(max_deviations, selected_SMA, selected_LGA):
if len(selected_SMA) == 0:
return dash.no_update
else:
dff = df[(df.LGA==selected_LGA) & (df.SMA.isin(selected_SMA))]
data = pd.DataFrame(data=dff)
x = dff.TIME
y = dff.CHANGE
mean = np.mean(y)
standard_deviation = np.std(y)
distance_from_mean = abs(y - mean)
not_outlier = distance_from_mean < max_deviations * standard_deviation
no_outliers = y[not_outlier]
trim_outliers = pd.DataFrame(data=no_outliers)
dfd = pd.merge(trim_outliers, dff, left_index=True, right_index=True)
dfd['CHANGE'] = dfd['CHANGE_x']
fig = px.scatter(dfd, x='TIME', y='CHANGE', color ='SMA', trendline='ols', size='PV', height=500, width=800, hover_name='SMA')
return dfd.to_dict('records')
return dcc.Graph(id='display-map', figure=fig)
if __name__ == '__main__':
app.run_server(debug=False)
Solution
Your have correctly defined two Outputs on your callback, but then you are only returning a single value which is incorrect.
The code below is your example stripped down and demonstrates the correct way to return multiple values. I have also switched the no_update
logic around to demonstrate a cleaner way to structure the code which reduces the risk of introducing a bug on return:
@app.callback(
Output('graph-container', 'children'),
Output('table-container', 'data'),
Input('radio_items', 'value'),
Input('SMA-dpdn', 'value'),
Input('LGA-dpdn', 'value'),
prevent_initial_call=True
)
def graph(max_deviations, selected_SMA, selected_LGA):
if len(selected_SMA) > 0:
# Do processing to create a dfd record and the figure for the Graph
return dcc.Graph(id='display-map', figure=fig), dfd.to_dict('records')
# No update if length was zero.
return dash.no_update, dash.no_update
Answered By - Ian Ash
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.