Grisuu
Grisuu

Reputation: 109

How to fix 'Callback Error' in plotly-dash for a Dropdown Menu

I have tried to re-create the following example Towards Data Science Example shown on the web

I have written the following code which I modified to this:

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

import pandas as pd
import plotly.graph_objs as go

# Step 1. Launch the application
app = dash.Dash()

# Step 2. Import the dataset
filepath = 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
st = pd.read_csv(filepath)


# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2015-02-17', '2015-05-17', '2015-08-17', '2015-11-17',
         '2016-02-17', '2016-05-17', '2016-08-17', '2016-11-17', '2017-02-17']

features = st.columns[1:-1]
opts = [{'label' : i, 'value' : i} for i in features]

# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['AAPL.High'],
                    name = 'AAPL HIGH',
                    line = dict(width = 2,
                                color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Time Series Plot',
                   hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)


# Step 4. Create a Dash layout
app.layout = html.Div([
                # a header and a paragraph
                html.Div([
                    html.H1("This is a Test Dashboard"),
                    html.P("Dash is great!!")
                         ],
                     style = {'padding' : '50px' ,
                              'backgroundColor' : '#3aaab2'}),
                # adding a plot
                dcc.Graph(id = 'plot', figure = fig),
                # dropdown
                html.P([
                    html.Label("Choose a feature"),
                        dcc.Dropdown(
                                id='opt',                              
                                options=opts,
                                value=features[0],
                                multi=True

                                ),
                # range slider
                html.P([
                    html.Label("Time Period"),
                    dcc.RangeSlider(id = 'slider',
                                    marks = {i : dates[i] for i in range(0, 9)},
                                    min = 0,
                                    max = 8,
                                    value = [1, 7])
                        ], style = {'width' : '80%',
                                    'fontSize' : '20px',
                                    'padding-left' : '100px',
                                    'display': 'inline-block'})
                      ])
                        ])


# Step 5. Add callback functions
@app.callback(Output('plot', 'figure'),
             [Input('opt', 'value'),
             Input('slider', 'value')])
def update_figure(input1, input2):
    # filtering the data
    st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
    # updating the plot
    trace_1 = go.Scatter(x = st2.Date, y = st2['AAPL.High'],
                        name = 'AAPL HIGH',
                        line = dict(width = 2,
                                    color = 'rgb(229, 151, 50)'))
    trace_2 = go.Scatter(x = st2.Date, y = st2[input1],
                        name = input1,
                        line = dict(width = 2,
                                    color = 'rgb(106, 181, 135)'))
    fig = go.Figure(data = [trace_1, trace_2], layout = layout)
    return fig

# Step 6. Add the server clause
if __name__ == '__main__':
    app.run_server(debug = True)

It runs and initializes all fine, until I change an input in the dropdown menu. There is a callback error generated, and I can't figure out where it comes from.

The app runs locally and displays the drop down menu fine with all the column, changing the input for the dropdown gives the issue.

The error is as follows:

ValueError: 
    Invalid value of type 'builtins.list' received for the 'name' property of scatter
        Received value: ['AAPL.Open', 'AAPL.Close']

    The 'name' property is a string and must be specified as:
      - A string
      - A number that will be converted to a string

Traceback (most recent call last):
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\test\Anaconda\lib\site-packages\flask\_compat.py", line 35, in reraise
    raise value
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\test\Anaconda\lib\site-packages\flask\_compat.py", line 35, in reraise
    raise value
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\test\Anaconda\lib\site-packages\dash\dash.py", line 1152, in dispatch
    response.set_data(self.callback_map[output]['callback'](*args))
  File "C:\test\Anaconda\lib\site-packages\dash\dash.py", line 1038, in add_context
    output_value = func(*args, **kwargs)
  File "C:\Users\Dash\Dash\test.py", line 87, in update_figure
    color = 'rgb(106, 181, 135)'))
  File "C:\test\Anaconda\lib\site-packages\plotly\graph_objs\__init__.py", line 37455, in __init__
    self['name'] = name if name is not None else _v
  File "C:\test\Anaconda\lib\site-packages\plotly\basedatatypes.py", line 3166, in __setitem__
    self._set_prop(prop, value)
  File "C:\test\Anaconda\lib\site-packages\plotly\basedatatypes.py", line 3407, in _set_prop
    raise err
  File "C:\test\Anaconda\lib\site-packages\plotly\basedatatypes.py", line 3402, in _set_prop
    val = validator.validate_coerce(val)
  File "C:\test\Anaconda\lib\site-packages\_plotly_utils\basevalidators.py", line 1005, in validate_coerce
    self.raise_invalid_val(v)
  File "C:\test\Anaconda\lib\site-packages\_plotly_utils\basevalidators.py", line 277, in raise_invalid_val
    valid_clr_desc=self.description()))
ValueError: 
    Invalid value of type 'builtins.list' received for the 'name' property of scatter
        Received value: ['AAPL.Open', 'AAPL.Close']

    The 'name' property is a string and must be specified as:
      - A string
      - A number that will be converted to a string

Upvotes: 2

Views: 8966

Answers (2)

DataFramed
DataFramed

Reputation: 1631

Callback error quick fix

Got similar error on callback. Simple dash update resolved it.

pip install dash --upgrade

Upvotes: 0

Mike_H
Mike_H

Reputation: 1455

Working Code

Your error was in line 85. You can only pass strings or numbers to the name attribute. I just added pythons str() function to transfer input1 to a string. :)

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

import pandas as pd
import plotly.graph_objs as go

# Step 1. Launch the application
app = dash.Dash()

# Step 2. Import the dataset
filepath = 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
st = pd.read_csv(filepath)


# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2015-02-17', '2015-05-17', '2015-08-17', '2015-11-17',
         '2016-02-17', '2016-05-17', '2016-08-17', '2016-11-17', '2017-02-17']

features = st.columns[1:-1]
opts = [{'label' : i, 'value' : i} for i in features]

# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['AAPL.High'],
                    name = 'AAPL HIGH',
                    line = dict(width = 2,
                                color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Time Series Plot',
                   hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)


# Step 4. Create a Dash layout
app.layout = html.Div([
                # a header and a paragraph
                html.Div([
                    html.H1("This is a Test Dashboard"),
                    html.P("Dash is great!!")
                         ],
                     style = {'padding' : '50px' ,
                              'backgroundColor' : '#3aaab2'}),
                # adding a plot
                dcc.Graph(id = 'plot', figure = fig),
                # dropdown
                html.P([
                    html.Label("Choose a feature"),
                        dcc.Dropdown(
                                id='opt',
                                options=opts,
                                value=features[0],
                                multi=True

                                ),
                # range slider
                html.P([
                    html.Label("Time Period"),
                    dcc.RangeSlider(id = 'slider',
                                    marks = {i : dates[i] for i in range(0, 9)},
                                    min = 0,
                                    max = 8,
                                    value = [1, 7])
                        ], style = {'width' : '80%',
                                    'fontSize' : '20px',
                                    'padding-left' : '100px',
                                    'display': 'inline-block'})
                      ])
                        ])


# Step 5. Add callback functions
@app.callback(Output('plot', 'figure'),
             [Input('opt', 'value'),
             Input('slider', 'value')])
def update_figure(input1, input2):
    # filtering the data
    st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
    # updating the plot
    trace_1 = go.Scatter(x = st2.Date, y = st2['AAPL.High'],
                        name = 'AAPL HIGH',
                        line = dict(width = 2,
                                    color = 'rgb(229, 151, 50)'))
    trace_2 = go.Scatter(x = st2.Date, y = st2[input1],
                        name = str(input1),
                        line = dict(width = 2,
                                    color = 'rgb(106, 181, 135)'))
    fig = go.Figure(data = [trace_1, trace_2], layout = layout)
    return fig

# Step 6. Add the server clause
if __name__ == '__main__':
    app.run_server(debug = True)

Upvotes: 3

Related Questions