Yonko
Yonko

Reputation: 63

Pandas Dash - How could i bind two different inputs to one output?

I have a code for showing two graphs with two options to choose. Now, i binded first selection option to both graphs, and as it changes the graphs also will change. But what i need is to make second option to affect graphs too - but on the condition that at the moment only one option should be displayed on graph - only from first or from second selected one. If it won't work i will need to create two additional graphs and bing them to the second selection option, but it would be bad.

P.S. If you tell me how to show selected label on Dropdown menu in running app i'll be even more grateful..

import dash
from dash import dcc
from dash import html
from dash.dependencies import Output, Input
import plotly.express as px
import pandas as pd
import numpy as np
import dash_bootstrap_components as dbc

ds=pd.DataFrame(data=(np.random.randn(10,20)))
ds.iloc[:, 0]=np.arange(0,10)


app = dash.Dash(__name__,
                external_stylesheets=[dbc.themes.BOOTSTRAP],
                meta_tags=[
                        {'name': 'viewport', 'content': 'width=device-width, initial-scale=1.0'}
                    ]
                )

app.layout = html.Div([
    dbc.Accordion(
        [
            dbc.AccordionItem(
                [
                    dcc.Dropdown(id='select',
                                 options=[{'label': 'Options 0-5', 'value': ds.columns[:6]},
                                          {'label': 'Options 6-10', 'value': ds.columns[6:11]}],
                                 searchable=True
                                 ),
                ],
                title="Individual Options",
            ),
            dbc.AccordionItem(
                [
                    dcc.Dropdown(id='select2',
                                 options=[{'label': 'Options 11-16', 'value': ds.columns[11:17]},
                                          {'label': 'Options 16+', 'value': ds.columns[16:]}],
                                 searchable=True
                                 ),
                ],
                title="Range of Options 2",
            ),
        ],
    ),
    html.Div([
        dcc.Graph(id='graph_a', figure={}),
        dcc.Graph(id='graph_b', figure={})
    ]),
])

@app.callback(Output('graph_a', 'figure'),
              Input('select', 'value'))
def update_graph_a(val):
    fig = px.line(ds,
                  x=0,
                  y=val)
    return fig


@app.callback(Output('graph_b', 'figure'),
              Input('select', 'value'))
def update_graph_b(val):
    fig = px.bar(ds,
                  x=0,
                  y=val)
    return fig


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

Upvotes: 1

Views: 553

Answers (1)

bas
bas

Reputation: 15722

But what i need is to make second option to affect graphs too - but on the condition that at the moment only one option should be displayed on graph - only from first or from second selected one.

I'm assuming that the dropdown from which an option is selected most recently should determine which option is used.

You could add an Input for your second select to your callbacks and use callback_context to determine which dropdown value change triggered the callback

# ...
from dash.exceptions import PreventUpdate

@app.callback(
    Output('graph_a', 'figure'),
    Input('select', 'value'),
    Input('select2', 'value')
)
def update_graph_a(val1, val2):
    ctx = dash.callback_context

    select_values = {"select": val1, "select2": val2}
    select_id = ctx.triggered[0]['prop_id'].split('.')[0]

    if not select_id:
        raise PreventUpdate

    fig = px.line(ds, x=0, y=select_values[select_id])

    return fig

So the idea here is to see which dropdown triggered the callback. If the callback wasn't triggered by the two dropdowns we prevent updating the callback output using PreventUpdate so the figure stays empty.

You could apply the same idea for the other callback. Or you could merge the callbacks together to one callback that returns the line chart and the bar chart. I would go with the latter.

If you want to show the active filter option you could add an Output and return select_id

Upvotes: 1

Related Questions