Dash
Reactivity - How do you generate a reactive plot? Can you indicate (1) the basic way to create a reactive plot, (2) how to create a plot reactive to more than one input and, (3) how to create more than one reactive output (for example, having a plot and text to print on the screen)?
The basic way to create a reactive plot is to make a connection between input data and output data. This will be done by adding a callback function, for callback functions, they are automatically called by Dash whenever an input component’s property changes, so these will update some property in the output. We can also name the function which is written in the @app.callback decorator like a dropdown, a slider bar, and markdown text data. Then we need to move the plot function down under the app.layout and then we use the callback decorator directly on this function (worth mentioning, The Dash Core Components (dash.dcc) module includes a Graph component called dcc.Graph. dcc.Graph renders interactive data visualizations using the open source plotly.js JavaScript graphing library). After the input changes, the function wrapped by the callback decorator will get called automatically. All in all, Dash provides this callback function with the new value of the input property as its argument, and Dash updates the property of the output component with whatever was returned by the function, that is, whenever a cell changes (the input), all the cells that depend on that cell (the outputs) will get updated automatically. This is the basic way to create a reactive plot by Dash.
In Dash, the output can have multiple input components. To create a plot reactive to more than one input is basically similar to the basic reactive plot, we need to add other inputs to the callback decorator @app.callback, also update the plot function and app.layout. The input arguments of the callback are the current value of each of the input properties, in the order that they were specified. This is worth mentioning when a Input updates once (i.e. a user can only change the value of a single Dropdown in a given moment), Dash collects the current state of all specified input properties and passes them to the callback function. These callback functions are always guaranteed to receive the newest state of the application. See below for an example from 532 lecture:
cars = data.cars()
# Setup app and layout/frontend
app = Dash(__name__, external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css'])
app.layout = html.Div([
html.Iframe(
id='scatter',
style={'border-width': '0', 'width': '100%', 'height': '400px'}),
dcc.Dropdown(
id='xcol-widget',
value='Horsepower', # REQUIRED to show the plot on the first page load
options=[{'label': col, 'value': col} for col in cars.columns])])
dcc.Dropdown(
id='ycol-widget',
value='Displacement',
options=[{'label': col, 'value': col} for col in cars.columns])
@app.callback(
Output('scatter', 'srcDoc'),
Input('xcol-widget', 'value'),
Input('ycol-widget', 'value'))
def plot_altair(xcol, ycol):
chart = alt.Chart(cars).mark_point().encode(
x=xcol,
y=ycol,
tooltip='Horsepower').interactive()
return chart.to_html()
@app.callback(
Output('scatter', 'srcDoc'),
Output('mean-x-div', 'children'), # This is the ID of our new output Div
Input('xcol-widget', 'value'),
Input('ycol-widget', 'value'))
def plot_altair(xcol, ycol):
chart = alt.Chart(cars).mark_point().encode(
x=xcol,
y=ycol,
tooltip='Horsepower').interactive()
return chart.to_html(), f'The mean of {xcol} is {cars[xcol].mean().round(1)}'
Some useful links are included below if wish to learn more: * https://dash.plotly.com/basic-callbacks * https://dash.plotly.com/basic-callbacks#dash-app-layout-with-figure-and-slider * https://dash.plotly.com/basic-callbacks#dash-app-with-multiple-outputs * https://dash.plotly.com/basic-callbacks#dash-app-with-multiple-inputs * https://stackoverflow.com/questions/45837031/is-there-a-better-way-to-perform-multiple-output-with-dash-by-plotly * https://budavariam.github.io/posts/2021/04/05/plotly-dash-development-tips/