如何为下拉菜单修复 plotly-dash 中的“回调错误”

Posted

技术标签:

【中文标题】如何为下拉菜单修复 plotly-dash 中的“回调错误”【英文标题】:How to fix 'Callback Error' in plotly-dash for a Dropdown Menu 【发布时间】:2019-10-06 12:30:49 【问题描述】:

我已尝试重新创建网络上显示的以下示例 Towards Data Science Example

我编写了以下代码并对此进行了修改:

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)

它运行并初始化一切正常,直到我更改下拉菜单中的输入。产生了一个回调错误,我不知道它来自哪里。

应用程序在本地运行并在所有列中正常显示下拉菜单,更改下拉菜单的输入会出现问题。

错误如下:

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

【问题讨论】:

请发布回调错误,例如 Key Error or Value Error 以及在使用的库的一堆代码行中引用文件中的行的行。那我就可以帮忙了。 :) 第一个猜测:回调返回错误。给我几分钟,我会找出问题并回复你! 我添加了我得到的错误 【参考方案1】:

工作代码

您的错误在第 85 行。您只能将字符串或数字传递给 name 属性。我刚刚添加了 pythons str() 函数将input1 传输到字符串。 :)

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)

【讨论】:

谢谢,解决了回调错误。不幸的是,我遇到了一个新问题。当我添加几列时,它不会使用新数据更新绘图,因为它将数据作为字符串读取。 “几列”是什么意思?您的意思是您要向dates 列表添加新日期? :) 我在下拉菜单中添加了一些“功能”。它不会绘制它们 将第 22 行更改为 features = st.columns 显然,除了“name=str”问题之外,现在还有一个不同的问题。似乎它没有正确更新添加的功能。更改第 22 行并不能解决问题。【参考方案2】:

回调错误快速修复

callback 出现类似错误。简单的dash 更新就解决了。

pip install dash --upgrade

【讨论】:

为什么它修复了你的项目?

以上是关于如何为下拉菜单修复 plotly-dash 中的“回调错误”的主要内容,如果未能解决你的问题,请参考以下文章

如何为下拉菜单制作 CSS 边框?

如何为 kendo ui 下拉菜单设置默认值?

如何为多个下拉菜单设置 jquery select2 的选定值?

Plotly-Dash:反应迟钝的情节

如何为移动屏幕的导航栏项目添加切换按钮,并使用 HTML、CSS 和 Bootstrap v4 将它们切换为下拉菜单

如何为简单的 Region > Country > State > City 下拉菜单设计 Jhipster JDL 关系