【问题标题】:How do I take input for the same graph from either a textbox or a dropdown?如何从文本框或下拉列表中获取相同图表的输入?
【发布时间】:2019-03-09 16:24:30
【问题描述】:

我想构建一个简单的仪表板应用程序,其中输入是股票代码,输出是一段时间内的股票价格。但是,我想为用户提供两种选择输入的方式:在文本框中输入或从一些普通股票的下拉列表中选择。

这是我的代码:

import pandas_datareader.data as web
import datetime
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

app = dash.Dash()

app.layout = html.Div(children=[
    html.Div(children='Symbol to graph:'),
    dcc.Input(id='input', value='', type='text'),

    html.Div(children='Frequent options:'),
    dcc.Dropdown(
    options=[
        {'label': 'Apple (AAPL)', 'value': 'AAPL'},
        {'label': 'Microsoft (MSFT)', 'value': 'MSFT'},
        {'label': 'Amazon (AMZN)', 'value': 'AMZN'},
        {'label': 'Tesla (TSLA)', 'value': 'TSLA'}
    ],
    style={'width': '40%'},
    id='freq-inputs'
    ),

    html.Div(id='output-graph'),

    html.Div(id='freq-input-graph'),
])

@app.callback(
    Output(component_id='output-graph', component_property='children'),
    [Input(component_id='input', component_property='value')]
)
def update_value(input_data):
    start = datetime.datetime(2015, 1, 1)
    end = datetime.datetime.now()
    df = web.DataReader(input_data, 'iex', start, end)
    df.reset_index(inplace=True)
    df.set_index("date", inplace=True)

    return dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': df.index, 'y': df.close, 'type': 'line', 'name': input_data},
            ],
            'layout': {
                'title': input_data
            }
        }
    )

@app.callback(
    Output(component_id='output-graph', component_property='children'),
    [Input(component_id='freq-inputs', component_property='value')]
)
def update_value(input_data):
    start = datetime.datetime(2015, 1, 1)
    end = datetime.datetime(2018, 9, 24) #datetime.datetime.now()
    df = web.DataReader(input_data, 'iex', start, end)
    df.reset_index(inplace=True)
    df.set_index("date", inplace=True)

    return dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': df.index, 'y': df.close, 'type': 'line', 'name': input_data},
            ],
            'layout': {
                'title': input_data
            }
        }
    )

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

如您所见,我必须为每种输入(html.Div(id='output-graph')html.Div(id='freq-input-graph'))编写 2 个 div,因此除了输入和输出组件 ID 之外,还有 2 个相同的回调包装函数。那是因为当我尝试使用相同的输出组件 div 时,我得到一个错误提示:

You have already assigned a callback to the output
with ID "output-graph" and property "children". An output can only have
a single callback function. Try combining your inputs and
callback functions together into one function.

除了冗余代码之外,我还面临着这个代码的另一个问题。如果我输入一个股票代码,它会绘制图表;如果我然后从下拉列表中选择一个选项,后一个图表将绘制在与前一个相同的 div 上,因此我们在任何给定时间只能看到一个图表。但是,如果我首先从下拉列表中选择一个选项,然后输入一个符号,它会绘制 2 个不同的图表。

这是因为html.Div(id='output-graph') 在应用布局定义中的html.Div(id='freq-input-graph') 上方声明/定义。如果我颠倒顺序,则会注意到相反的行为。

我该如何解决这个问题?

【问题讨论】:

    标签: python dashboard plotly-dash


    【解决方案1】:

    最好的解决方案是使用State 而不是Input,然后你将只有一个函数回调。可以将此状态分配给提交按钮,然后当用户在下拉或文本框之间选择一个输入并单击按钮时,更新将完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-01
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      • 2019-02-27
      • 1970-01-01
      • 2015-11-03
      • 1970-01-01
      相关资源
      最近更新 更多