Learn how to use Dash Bio for next-gen sequencing & quality control. 🧬Register for the Oct 27 webinar.

Plot multiples graphs with dropdown values

Hi everyone!
I’m new on dash and I have some questions.
I want to plot curves that the user can chose by dropdowns (one for x axis and one for y axis).

I succeeded to plot a line for one value of the dropdown with the code below:

“”"

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px

app = dash.Dash(name)

df=pd.read_csv(“data.csv”,sep=",",decimal=".",header=9)
print(df[:5])

#layout
app.layout=html.Div([
html.H1("results: ",
style={‘text_align’:‘center’}),
html.Label(‘Dropdown y axis’),
dcc.Dropdown(id=‘axe_y’,
options=[{‘label’:x,‘value’:x} for x in df.columns],
multi=False,
clearable=False,
value=‘Wind speed (m/s)’,
style={‘width’:‘40%’}
),
html.Label(‘Dropdown x axis’),
dcc.Dropdown(id=‘axe_x’,
options=[{‘label’:x,‘value’:x} for x in df.columns],
multi=False,
clearable=False,
value=’# Date and time’,
style={‘width’:‘40%’}
),
#html.Div(id=‘output_container’),
html.Br(),
dcc.Graph(id=‘graph_som’)
])

#callback
@app.callback(
Output(component_id=‘graph_som’,component_property=‘figure’),
[Input(component_id=‘axe_y’,component_property=‘value’),
Input(component_id=‘axe_x’,component_property=‘value’)]
)

def update_graph(axe_y_select,axe_x_select):
print(axe_y_select)
print(type(axe_y_select))
print(axe_x_select)
print(type(axe_x_select))

#remove some values
dff=df.copy()
dff=dff.dropna()

fig=px.line(data_frame=dff,x=dff[axe_x_select],y=dff[axe_y_select],template='plotly_dark')

return fig

if name == ‘main’:
app.run_server(debug=True)

“”"
I want to change my dropdowns to ‘multi’ and be able to have the different graphs represented.
Actually when I’m trying to have a multiple dropdown, I don’t succeed to plot the different values I select with the dropdown (especially different ‘y’ axis).
If somedody has an idea how it can be done, it would be useful!

Thanks!

Hi, looking at your code I don’t see a problem. May be is just in the callback function. You said that you need multi in dropdown menu, but I don’t see a logic to handle multiple values in the callback function:

I think should be something like this:

@app.callback(
Output(component_id=‘graph_som’,component_property=‘figure’),
[Input(component_id=‘axe_y’,component_property=‘value’),
Input(component_id=‘axe_x’,component_property=‘value’)]
)

def update_graph(axe_y_select,axe_x_select):
print(axe_y_select)
print(type(axe_y_select))
print(axe_x_select)
print(type(axe_x_select))

#remove some values
dff=df.copy()
dff=dff.dropna()

if len(axe_y_select) > 1:
     for new_val in axe_y_select:
            fig=px.line(data_frame=dff,x=dff[axe_x_select],y=dff[new_val],template='plotly_dark')
else:
     fig=px.line(data_frame=dff,x=dff[axe_x_select],y=dff[axe_y_select],template='plotly_dark')

return fig

Now, I don’t use plotly express so I don’t know if the code before will append 2 traces in the same graph. I think is better if you use the standard go. Figure object. With that, you can add traces. And then, define a logic to append multiple traces. Once is done, you can update with different values from the dropdown menu

See this example in the documentation: Line Plot Modes
line-charts-plotly

Hi Daniel,
Thanks for your answer really useful!
With plotly express, I didn’t succeed to have 2 traces on the same graph (maybe someone else know how to do it), but by using your advice with go.Figure, it’s ok to have as much trace as we want depending of user choice on dropdown.
Below I share the code if some have the same question:
<
import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly

import plotly.graph_objects as go

#in the app
app = dash.Dash(name)

#csv in dataframe
df=pd.read_csv(“data.csv”,sep=",",decimal=".",header=9)

#layout
app.layout=html.Div([
html.H1("results: ",
style={‘text_align’:‘center’}),
html.Label(‘Dropdown y axis’),
dcc.Dropdown(id=‘axe_y’,
options=[{‘label’:x,‘value’:x,‘disabled’:False} for x in df.columns],
multi=True,
clearable=False,
value=None,
searchable=True,
search_value=’’,
style={‘width’:‘40%’},

            ),
    html.Label('Dropdown x axis'),
    dcc.Dropdown(id='axe_x',
                 options=[{'label':x,'value':x} for x in df.columns],
                 multi=False,
                 clearable=False,
                 value='# Date and time',
                 searchable=True,
                 search_value='',
                 style={'width':'40%'},
                 #persistence=True,
                 #persistence_type='memory'
            ),
    #html.Div(id='output_container'),
    html.Br(),
    dcc.Graph(id='graph_som')
    ])

@app.callback(
Output(component_id=‘graph_som’,component_property=‘figure’),
[Input(component_id=‘axe_y’,component_property=‘value’),
Input(component_id=‘axe_x’,component_property=‘value’)]
)

def update_graph(axe_y_select,axe_x_select):
print(axe_y_select)
print(type(axe_y_select))
print(axe_x_select)
print(type(axe_x_select))

#remove some values
dff=df.copy()
dff=dff.dropna()

fig=go.Figure()
for val in axe_y_select:
         fig.add_trace(go.Scatter(
                                 x=dff[axe_x_select],
                                 y=dff[val],
                                 mode='lines',
                                 name=val,
                                 #connectgaps=True,
                                 ))
return fig

if name == ‘main’:
app.run_server(debug=True)

It works and I obtain curves, I just have an error :“Callback error updating graph_som.figure” if you know from where it comes from and how can I resolve it.

Now I need to find a way to have different y axis on the graph, with names and everything related :wink:

Hi, if you share your .csv file i could try to replicate the error to see what is happening.

Hi, i tried with random csv file. The problem is because you have not define a logic to handle the dropdown menu when there is nothing happening.

Run this code:

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
import plotly

import plotly.graph_objects as go

#in the app
app = dash.Dash(__name__)

#csv in dataframe
df=pd.read_csv("data.csv",sep=",",decimal=".",header=9)

#layout
app.layout=html.Div([
html.H1("results: ",
style={'text_align':'center'}),
html.Label('Dropdown y axis'),
dcc.Dropdown(id='axe_y',
options=[{'label':x,'value':x,'disabled':False} for x in df.columns],
multi=True,
clearable=False,
value=None,
searchable=True,
search_value='',
style={'width':'40%'},

            ),
    html.Label('Dropdown x axis'),
    dcc.Dropdown(id='axe_x',
                 options=[{'label':x,'value':x} for x in df.columns],
                 multi=False,
                 clearable=False,
                 value='# Date and time',
                 searchable=True,
                 search_value='',
                 style={'width':'40%'},
                 #persistence=True,
                 #persistence_type='memory'
            ),
    #html.Div(id='output_container'),
    html.Br(),
    dcc.Graph(id='graph_som')
    ])
@app.callback(
Output(component_id='graph_som',component_property='figure'),
[Input(component_id='axe_y',component_property='value'),
Input(component_id='axe_x',component_property='value')]
)

def update_graph(axe_y_select,axe_x_select):
    if axe_y_select is not None:
        print(axe_y_select)
        # print(type(axe_y_select))
        print(axe_x_select)
        print(type(axe_x_select))

        #remove some values
        dff=df.copy()
        dff=dff.dropna()

        fig=go.Figure()
        for val in axe_y_select:
                 fig.add_trace(go.Scatter(
                                         x=dff[axe_x_select],
                                         y=dff[val],
                                         mode='lines',
                                         name=val,
                                         #connectgaps=True,
                                         ))
        return fig
    else:
        raise PreventUpdate

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

Hi,
Perfect with this code to resolve my problem!