Reputation: 113
I'm new to Dash and I'm trying to connect dcc.Dropdown
and dcc.RadioItems
component.
For this purpose I have created this very simplyfied Dash app example in which I want to allow user to select chart (dropdown menu) based on previous input selection (RadioItems).
My code works fine in terms of functionality but I'm not sure if this is the proper way to use a callback function in this case.
Please find the code below:
import pandas as pd
import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.express as px
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
data = {'date': [10, 5, 7, 11], 'column1': [15, 4, 8, 5], 'column2': [1, 2, 3, 9], 'column3': [1.5, 2.5, 3.5, 0.5]}
df = pd.DataFrame(data)
app = dash.Dash(__name__)
show_columns = ['column1', 'column2', 'column3']
app.layout = html.Div(children=[
html.H1(children='Columns visualisation'),
html.Div([
html.Div(
dcc.RadioItems(
id='radio_items',
options=[{'label': i, 'value': i} for i in show_columns],
value='column1',
labelStyle={'display': 'inline-block'}
),
),
dcc.Dropdown(
id='dropdown',
options=[
{'label': 'Line Chart', 'value': 'v1'},
{'label': 'Bar Chart', 'value': 'v2'}
],
value='v1',
),
html.Div(dcc.Graph(id='graph')),
]),
])
@app.callback(
Output('graph', 'figure'),
Input('radio_items', 'value'),
Input('dropdown', 'value')
)
def update_output(item, value):
if item == 'column1':
try:
if value is None:
raise PreventUpdate
elif value == 'v1':
fig = px.line(df, x=df.date, y=df.column1)
return fig
elif value == 'v2':
fig1 = px.bar(df, x=df.date, y=df.column1)
return fig1
except ValueError:
return None
if item == 'column2':
try:
if value is None:
raise PreventUpdate
elif value == 'v1':
fig = px.line(df, x=df.date, y=df.column2)
return fig
elif value == 'v2':
fig1 = px.bar(df, x=df.date, y=df.column2)
return fig1
except ValueError:
return None
else:
try:
if value is None:
raise PreventUpdate
elif value == 'v1':
fig = px.line(df, x=df.date, y=df.column3)
return fig
elif value == 'v2':
fig1 = px.bar(df, x=df.date, y=df.column3)
return fig1
except ValueError:
return None
if __name__ == '__main__':
app.run_server(debug=True)
I would like to know if there is more elegant way to set up my update_output
function?
Is this done this way at all?
I would appreciate any help. Thanks in advance
Upvotes: 0
Views: 1585
Reputation: 15462
I think the checks in your example are unnecessary.
You can directly select parts of your data using the values you receive from the callback.
You could create a chart type dictionary which has "v1"
, "v2"
as keys. The values in the dictionary could correspond to a plot function to be used for a given key:
charts = {"v1": px.line, "v2": px.bar}
Then you could change your callback to this:
@app.callback(
Output("graph", "figure"), Input("radio_items", "value"), Input("dropdown", "value")
)
def update_output(item, chart_type):
if chart_type is None:
raise PreventUpdate
return charts[chart_type](df, x=df.date, y=df[item])
You actually also don't need the if statement that checks if the chart type picked is None
, because you already have set a default value in your layout
so the dropdown value will never be None
:
@app.callback(
Output("graph", "figure"), Input("radio_items", "value"), Input("dropdown", "value")
)
def update_output(item, chart_type):
return charts[chart_type](df, x=df.date, y=df[item])
Upvotes: 1