1

I am rather new to Dash (and basic skill level regarding Python) and working on a dashboard for educational purposes. Students shall be able to alter various variables via sliders. The changes on an economic model shall be visible in several plots shown. I am able to create a basic example, with one plot being fed by several sliders. However, I want some sliders to affect several plots simultaneously.

So far, I came up with the following:

import dash
from dash import dcc 
import dash_html_components as html
from dash.dependencies import Input, Output

import pandas as pd

import plotly.graph_objects as go
from jupyter_dash import JupyterDash

app = dash.Dash(__name__)

a = 1
b = 1
c = 1

d = {
    'x' : [1, 2, 3, 4],
    'y1': [i * a for i in [1, 2, 3, 4]], 
    'y2': [i * b for i in [1, 2, 3, 4]],
    'y3': [i * c for i in [1, 2, 3, 4]]
    }

df = pd.DataFrame(data = d)


fig1 = go.Figure()

    fig.add_trace(go.Line(name="y1", x=df['x'], y=df['y1']))
    fig.add_trace(go.Line(name="y2", x=df['x'], y=df['y2']))
    fig.update_layout(
        transition_duration=500,
        xaxis_title="x",
        yaxis_title="y"
        )
    fig.update_yaxes(range = [0,20])
    fig.update_xaxes(range = [0,6])

fig2 = go.Figure()

    fig.add_trace(go.Line(name="y1", x=df['x'], y=df['y1']))
    fig.update_layout(
        transition_duration=500,
        xaxis_title="x",
        yaxis_title="y"
        )
    fig.update_yaxes(range = [0,20])
    fig.update_xaxes(range = [0,6])

fig3 = go.Figure()

    fig.add_trace(go.Line(name="y2", x=df['x'], y=df['y2']))
    fig.add_trace(go.Line(name="y3", x=df['x'], y=df['y3']))
    fig.update_layout(
        transition_duration=500,
        xaxis_title="x",
        yaxis_title="y"
        )
    fig.update_yaxes(range = [0,20])
    fig.update_xaxes(range = [0,6])

app.layout = html.Div(children=[
    html.Div([
        html.Div([
            html.Div(children='''
                Market A
            '''),

            dcc.Graph(
                id='graph1',
                figure=fig1
            ),  
        ], className='col'),
        html.Div([
            html.Div(children='''
                Market B
            '''),

            dcc.Graph(
                id='graph2',
                figure=fig2
            ),  
        ], className='col'),
    ], className='row'),
    # New Div for all elements in the new 'row' of the page
    html.Div([
        html.Div(children='''
            Market C
        '''),

        dcc.Graph(
            id='graph3',
            figure=fig3
        ),
        dcc.Slider(
            0,
            10,
            step=None,
            value=a,
            id='a'
        ),
        dcc.Slider(
                0,
                10,
                step=None,
                value=b,
                id='b'
            ),
        dcc.Slider(
                0,
                10,
                step=None,
                value=c,
                id='c'
            ),
    ], className='row'),
])

@app.callback(
    [Output('graph1', 'figure'),
    Output('graph2', 'figure'),
    Output('graph3', 'figure')],
    [Input('a', 'value'),        # first slider
    Input('b', 'value')],        # second slider 
    Input('c', 'value'))         # third slider

def update_figure_money_market(a, b, c):
    a = a
    b = b
    c = c
    d = {
        'x' : [1, 2, 3, 4],
        'y1': [i * a for i in [1, 2, 3, 4]], 
        'y2': [i * b for i in [1, 2, 3, 4]],
        'y3': [i * c for i in [1, 2, 3, 4]]
        }
    df = pd.DataFrame(data = d)

if __name__ == '__main__':
    app.run_server(debug=True)

So far I have not found a proper approach to this on the internet.

Any hint would be highly appreciated.

Ralle Kalle
  • 123
  • 4
  • So, apparently I have to update the plot, not only the data frame. However, I am still struggling to return 3 different plots. I had an update function for a single plot before that worked fine for one plot. I tried to display this very plot in three subplots, but couldn't make it work. – Ralle Kalle Jun 23 '22 at 20:10

1 Answers1

0

Each graph needs its own callback, followed by an update function for the graph, for dash to produce several responsive plots.

# input and update of graph 1
@app.callback(
    Output('graph1', 'figure'),
    [Input('slider1', 'value'),
    Input('slider2', 'value')]
) 
def update_graph1(slider1, slider2):
    X = np.array(range(1,1001,1))
    Y = X * slider1
    Y2 = X * slider2
    d = {'X': X, 'Y': Y, 'Y2': Y2}
    df = pd.DataFrame(data = d)
    fig = go.Figure()
    fig.add_trace(go.Line(name="Y", x=df['X'], y=df['Y']))
    fig.add_trace(go.Line(name="Y2", x=df['X'],
        y=df['Y2']))
    fig.update_layout(
        transition_duration=500,
        xaxis_title="X",
        yaxis_title="Y"
        )
    return fig
  
# input and update of second plot
@app.callback(
    Output('graph2', 'figure'),
    Input('slider2', 'value')
) 
def update_graph2(slider2):
    X = np.array(range(1,1001,1))
    Y = X**0.5 * slider2
    d = {'X': X, 'Y': Y}
    df = pd.DataFrame(data = d)
    fig = go.Figure()
    fig.add_trace(go.Line(name="Y", x=df['X'], y=df['Y']))
    fig.update_layout(
        transition_duration=500,
        xaxis_title="X",
        yaxis_title="Y"
        )
    return fig

if __name__ == '__main__':
    app.run_server(debug=True)
Ralle Kalle
  • 123
  • 4