1

I am using Dash by Plotly with python to create a web application. I have been struggling with having multiple values being displayed correctly on a dropdown element. Starting from a pandas dataframe I am extracting a column 1, then selecting values in another column 2 corresponding to values in column 1. Multiple values are to be displayed in the dropdown. Attached is a GIF of what the app is doing. I want the values on dropdown 2 to be independent values on separate lines, i.e distinct values and not concatenated together.

I think the problem is how I am returning the values in

 def update_dropdown2(wdg):
 wdgarray=df[ df['wdg'] == wdg ]['id'],
 return [{'label':i,'value':i} for i in wdgarray]

Here is a gif file showing the problem of the second dropdown element display on each line

Here is the code:

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    import plotly.graph_objs as go
    from dash.dependencies import Input, Output

#create a dataframe with random data

df = pd.DataFrame(
    {'wdg': [10,10,10,20,20,20,30,30,30,40],
     'id': np.arange(0,100,10),
     'b': np.random.rand(10)*100,
     'c': np.random.rand(10)*100,
     'd': np.random.rand(10)*100,
     'e': np.random.rand(10)*100,
     'f': np.random.rand(10)*100,
     'g': np.random.rand(10)*100,
     'h': np.random.rand(10)*100,
     'k': np.random.rand(10)*100},

    columns=['wdg','id','b','c','d','e','f','g','h','k'])


app = dash.Dash()

#html layout
app.layout = html.Div([
    html.H1(
        children='Perfomance database web app',
        style={
            'textAlign': 'center',
            'color': colors['text']}
    ),

    html.Div([
        dcc.Dropdown(
            id='dropdown1',
            options=[{'label': i, 'value': i} for i in df.wdg.unique()],
            value='10'
        ),
        dcc.Dropdown(
            id='dropdown2',
            #options=[{'label': i, 'value': i} for i in mtrid_indicators],
            #value='1'
        ),
    ],
    style={'width': '49%', 'display': 'inline-block'}
    ),

    html.Div(id='tablecontainer'),

    html.Div(
        dcc.Graph(
            id='graph',

            style={'width':'600','height':'500'}
        ),
        style={'display':'inline-block'}
    ),

    ],
style={'width': '100%', 'display': 'inline-block'}
)

#callback to update dropdown 2
@app.callback(
    Output(component_id='dropdown2',component_property='options'),
    [Input(component_id='dropdown1',component_property='value')]
)

#function to that will update values in dropdown 2
def update_dropdown2(wdg):
    wdgarray=df[ df['wdg'] == wdg ]['id'],
    return [{'label':i,'value':i} for i in wdgarray]

#callback to update graph with values of dropdown 1 selecting pandas row
@app.callback(
    Output('graph', 'figure'), 
    [Input('dropdown1', 'value')]
)

#graph plot and styling
def update_graph(row):
    dff = df.iloc[int(row/10)].values # update with your own logic
    return {
        'data': [
                    go.Scatter(
                        x=np.arange(0,80,10),
                        y=dff,
                        mode='lines+markers',
                        line = dict(width = 5,color = 'rgb(200, 0, 0)'),
                        name='Torque curve',
                        marker = dict(
                        size = 10,
                        color = 'rgba(200, 0, 0, .9)',
                        line = dict(width = 2,color='rgb(0, 0, 0)')
                        )
                    ),
                ],
        'layout': go.Layout(
                    title='Torque Speed curve',

                    xaxis=dict(
        #               type='line',
                        title='Speed - (RPM)',
                        showgrid=True,
                        #zeroline=True,
                        showline=True,
                        gridcolor='#bdbdbd',
                        mirror="ticks",
                        ticks="inside",
                        tickwidth=1,
                        linewidth=2,
                        range=[0,100]
                    ),
                    yaxis=dict(
                        title= 'Torque - (lb-ft)',
                        titlefont=dict( color='rgb(200, 0, 0)' ),
                        tickfont=dict( color='rgb(200, 0, 0)' ),
                        range=[0, 120],
                        showgrid=True,
                        #zeroline=True,
                        showline=True,
                        gridcolor='#bdbdbd',
                        mirror="ticks",
                        ticks="inside",
                        tickwidth=1,
                        linewidth=2
                    ),
                    margin={'l': 60, 'b': 40, 't': 30, 'r': 60},
                    #legend={'x': 0.5, 'y': 1},
                    hovermode='closest',
                    showlegend=False,
                )
        }

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

1 Answer 1

1

Solution coming from pdh in the amazing plotly community is to remove the comma which is turning what should be a pandas series into a tuple. Link to solution from Plotly community

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from dash.dependencies import Input, Output

#create a dataframe with random data

df = pd.DataFrame(
{'wdg': [10,10,10,20,20,20,30,30,30,40],
 'id': np.arange(0,100,10),
 'b': np.random.rand(10)*100,
 'c': np.random.rand(10)*100,
 'd': np.random.rand(10)*100,
 'e': np.random.rand(10)*100,
 'f': np.random.rand(10)*100,
 'g': np.random.rand(10)*100,
 'h': np.random.rand(10)*100,
 'k': np.random.rand(10)*100},

columns=['wdg','id','b','c','d','e','f','g','h','k'])


app = dash.Dash()

#html layout
app.layout = html.Div([
html.H1(
    children='Perfomance database web app',
    style={
        'textAlign': 'center',
        'color': colors['text']}
),

html.Div([
    dcc.Dropdown(
        id='dropdown1',
        options=[{'label': i, 'value': i} for i in df.wdg.unique()],
        value='10'
    ),
    dcc.Dropdown(
        id='dropdown2',
        #options=[{'label': i, 'value': i} for i in mtrid_indicators],
        #value='1'
    ),
],
style={'width': '49%', 'display': 'inline-block'}
),

html.Div(id='tablecontainer'),

html.Div(
    dcc.Graph(
        id='graph',

        style={'width':'600','height':'500'}
    ),
    style={'display':'inline-block'}
),

],
style={'width': '100%', 'display': 'inline-block'}
)

#callback to update dropdown 2
@app.callback(
Output(component_id='dropdown2',component_property='options'),
[Input(component_id='dropdown1',component_property='value')]
)

#function to that will update values in dropdown 2
def update_dropdown2(wdg):
wdgarray=df[ df['wdg'] == wdg ]['id'] # removed problematic comma
return [{'label':i,'value':i} for i in wdgarray]

#callback to update graph with values of dropdown 1 selecting pandas row
@app.callback(
Output('graph', 'figure'), 
[Input('dropdown1', 'value')]
)

#graph plot and styling
def update_graph(row):
dff = df.iloc[int(row/10)].values # update with your own logic
return {
    'data': [
                go.Scatter(
                    x=np.arange(0,80,10),
                    y=dff,
                    mode='lines+markers',
                    line = dict(width = 5,color = 'rgb(200, 0, 0)'),
                    name='Torque curve',
                    marker = dict(
                    size = 10,
                    color = 'rgba(200, 0, 0, .9)',
                    line = dict(width = 2,color='rgb(0, 0, 0)')
                    )
                ),
            ],
    'layout': go.Layout(
                title='Torque Speed curve',

                xaxis=dict(
    #               type='line',
                    title='Speed - (RPM)',
                    showgrid=True,
                    #zeroline=True,
                    showline=True,
                    gridcolor='#bdbdbd',
                    mirror="ticks",
                    ticks="inside",
                    tickwidth=1,
                    linewidth=2,
                    range=[0,100]
                ),
                yaxis=dict(
                    title= 'Torque - (lb-ft)',
                    titlefont=dict( color='rgb(200, 0, 0)' ),
                    tickfont=dict( color='rgb(200, 0, 0)' ),
                    range=[0, 120],
                    showgrid=True,
                    #zeroline=True,
                    showline=True,
                    gridcolor='#bdbdbd',
                    mirror="ticks",
                    ticks="inside",
                    tickwidth=1,
                    linewidth=2
                ),
                margin={'l': 60, 'b': 40, 't': 30, 'r': 60},
                #legend={'x': 0.5, 'y': 1},
                hovermode='closest',
                showlegend=False,
            )
    }

if __name__ == '__main__':
app.run_server()
Sign up to request clarification or add additional context in comments.

1 Comment

I would add the code to your answer in addition to the link, as the link may not work in the future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.