0

I am attempting to create a plotly dash drop-down whose selection is used to filter a dataframe and generate a pie chart from the filtered dataframe. I started with the working code from plotly interactive visualizations documentation and as carefully as possible went through and deleted all the extra. (all I want is one drop-down and one output graph as per similar stack question).

For now I will stick with the first question that has come to mind relating to the logic of the @app.callback section of the code.

@app.callback(
Output('indicator-graphic', 'figure'),
[Input('choose_species', 'value')])

The input tag makes sense, as there is a dropdown above with id and value equal to the arguments of Input:

html.Div([
        dcc.Dropdown(
            id='choose_species',
            options=[{'label': i, 'value': i} for i in available_indicators],
            value='Pacific Water Shrew'
        )

However, while the out put has a related id:

dcc.Graph(id='indicator-graphic')

there is nothing else in the code with the text figure which I would assume would have to come from the output of a function update_graph as it is called in the example code. There is no other mention of figure in my own code (which doesnt work obviously) nor in the example code (which does work to my surprise, given that I can't figure out how).

Question:

Given the above, how do I tie by @app_callback to my update-graph function. Please keep in mind I am quite new to all coding languages involved.

Alejandro
  • 7,290
  • 4
  • 34
  • 59
Max Duso
  • 305
  • 1
  • 4
  • 15
  • maybe first assing function and use `print()` to see if it work - `figure` doesn't have to be visible in Graph arguments but it may have this variable (as class variable which is created automatically). – furas Mar 24 '22 at 02:03
  • simply put `def update_graph(argument): ... code...` directly below `@app.callback()` - `@` means it is decoreator and it will get first function below and use it. – furas Mar 24 '22 at 02:07
  • Please refer to the SO for the answer to a [similar question](https://stackoverflow.com/questions/61042682/plotly-dash-update-graph-with-dropdown-input). – r-beginners Mar 24 '22 at 02:29

2 Answers2

1

figure is part of Graph and you can assing value to figure at start - like this

import dash
from dash import html, dcc

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Graph(figure={
                  'data': [{
                        'x': [1,2,3],
                        'y': [1,7,4],
                  }],
              }
    ),
])        

app.run_server()

but you can also define Graph with empty figure

import dash
from dash import html, dcc

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Graph(),
])        

app.run_server()

and you may later try to assign some values to figure.

And this is what code with callback is doing.

It uses id to access Graph and it assigns to figure value returned from callback.

When page is loaded then it creates Dropdown (with id='choose_species') and it assigns 'Pacific Water Shrew' to value and this executes callback with [Input('choose_species', 'value')] which returns dictionary and callback assigns it to figure in Graph with id='indicator-graphic'


@ in @app.callback means it is decorator and you have to put your function directly below decorat to assign it to this decorator - or rather to execute this decorator with this function as argument.

import dash
from dash import html, dcc, Output, Input

# --- data ---

my_data = {
    'Hello': {'x':[1,2,3], 'y': [1,7,4]},
    'World': {'x':[1,2,3], 'y': [7,1,4]},
    'Pacific Water Shrew': {'x':[1,2,3], 'y': [7,4,1]}
}

available_indicators = list(my_data.keys())

# --- HTML ---

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Dropdown(
        id='choose_species',
        options=[{'label': i, 'value': i} for i in available_indicators],
        value='Pacific Water Shrew'
    ),

    dcc.Graph(id='indicator-graphic'),
])        

# --- code ---

@app.callback(
Output('indicator-graphic', 'figure'),
[Input('choose_species', 'value')])
def update_graph(arg):
    print('value from dropdown:', arg)
    
    my_x = my_data[arg]['x']
    my_y = my_data[arg]['y']
    
    return {
        'data': [dict(
            x=my_x,
            y=my_y,
        )],
    }

app.run_server()
furas
  • 134,197
  • 12
  • 106
  • 148
  • Thank you so much for responding! This answer totally worked too! Roughly th same except I suppose that the `figure{}` argument is not necessary in the HTML section as you said. – Max Duso Mar 24 '22 at 17:52
  • I suppose I should compose a new question, but: I am tyring to embed this into an html document. I am assuming that this solution can mostly be directly written to the document with exception to the graph building function `update_graph` in this case, which would have to be in a python script which is referred to by the html? Sorry if this is completely ignorant as an assumption. – Max Duso Mar 25 '22 at 18:48
  • Ah nevermind. The ` – Max Duso Mar 25 '22 at 19:15
1

Based on my experience you can do something like below:

app = dash.Dash(__name__,external_stylesheets=[dbc.themes.LUX])

app.layout = html.Div([html.H5('Drop Down',className='text-center'),
            dcc.Dropdown(
            id='choose_species',
            options=[{'label': i, 'value': i} for i in available_indicators],
                value='Pacific Water Shrew',
                multi=True,
                disabled=False,
                clearable=True,
                searchable=True),
            dcc.Graph(id='indicator-graphic',figure={},style={'height':300,'width':'auto'})
])

@app.callback(Output('indicator-graphic', 'figure'),
             [Input('choose_species', 'value')])

def build_graph(species): 
    fig = px.line(df,x='',y='',color='')
    return fig

if __name__ == "__main__":
    app.run_server(debug=False

)

You need to add dcc.Graph and figure={} in your layout, and under @app.callback you have to add a function to return figure after filtering by dropdown.

hoa tran
  • 1,391
  • 1
  • 5
  • 14
  • ahah! it is running! just had to change the input of the `build_graph` to be `value` instead of `species` and the output of the same funciton to be `figure` to match the layout and callback sections. Thanks for your help! – Max Duso Mar 24 '22 at 17:38