首页 > 解决方案 > 我的简单 Dash 应用程序有什么问题导致我的绘图无法正常工作?

问题描述

我制作了一个 Dash 应用程序,它从我的 SQL 数据库中绘制股票市场数据。该应用程序使用一个可以有多个值的输入。就我而言,此输入仅指股票。因此,用户可以在一个输入中链接多个股票,以创建一个带有它们的价格的图,相互叠加。使用 Flask @callback 方法,我可以做到这一点。

这就是仪表板的样子

图表不工作,输入栏效果很好,用户可以选择多只股票。当然,它与正在传递的数据有关,但我找不到在哪里,而且我似乎修复得越多,它就越坏......

在下面查看我的代码:

import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import plotly.graph_objects as go


import dash_html_components as html

from dash.exceptions import PreventUpdate



#PostgreSQL Connection
from connect import *

# CSS
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']



# Pre-load:
stock_ids = execute_query(conn, "SELECT DISTINCT id FROM security_price;")
stock_ids = [i[0] for i in stock_ids]
options = [{'label': i, 'value': i} for i in stock_ids]


# Create Dash app
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)





# Create app layout
app.layout = html.Div(
                   [    html.Div(className='row',  # Define the row element
                                children=[
                                # left element
                                  html.Div(className='eight columns div-user-controls', 
                                    children = [
                                    html.H2('SP500 Equity Analyzer'),
                                    html.P(''' Compare stocks on your watchlist.'''),
                                    dcc.Dropdown(id="my-multi-dynamic-dropdown", options=options, multi=True, placeholder="Select a Symbol"),
                                    dcc.Graph(id='timeseries', config={'displayModeBar': False}),

                                    ]
                                    ),
                                 
                                  










                                  # right element
                                  html.Div(className='four columns div-for-charts bg-grey'),
                                 





                                 ]),
                   ])


# User callbacks

#user input
@app.callback(
    dash.dependencies.Output("my-multi-dynamic-dropdown", "options"),
    [dash.dependencies.Input("my-multi-dynamic-dropdown", "search_value")],
    [dash.dependencies.State("my-multi-dynamic-dropdown", "value")],
)
def update_multi_options(search_value, value):
    if not search_value:
        raise PreventUpdate
    else:
        return [
            o for o in options if search_value in o["label"] or o["value"] in (value or [])
        ]

# timeseries graph
@app.callback(Output('timeseries', 'figure'),
              [Input("my-multi-dynamic-dropdown", 'search_value')],
              [State("my-multi-dynamic-dropdown", "value")],
)


def update_timeseries(input_data, state): 
    if input_data == None:
        raise PreventUpdate
    if state == None:
        raise PreventUpdate
  


    # Draw and append traces for each stock
    trace = []  


    for stock in input_data:  
        stock_info = execute_query(conn, f"SELECT date, close FROM security_price WHERE security_price.id  = '{stock}' ;") 
        for row in stock_info:
            date = []
            adj_close = []

            date.append(row[0])
            adj_close.append(row[1])
        # STEP 2
            trace.append(go.Scatter(x=date,
                                     y=adj_close,
                                     mode='lines',
                                     opacity=0.7,
                                     name=stock,
                                     textposition='bottom center'))  
    # STEP 3
    traces = [trace]
    data = [val for sublist in traces for val in sublist]
    # Define Figure
    # STEP 4
    figure = {'data': traces,
              'layout': go.Layout(
                  colorway=["#5E0DAC", '#FF4F00', '#375CB1', '#FF7400', '#FFF400', '#FF0056'],
                  template='plotly_dark',
                  paper_bgcolor='rgba(0, 0, 0, 0)',
                  plot_bgcolor='rgba(0, 0, 0, 0)',
                  margin={'b': 15},
                  hovermode='x',
                  autosize=True,
                  title={'text': 'Stock Prices', 'font': {'color': 'white'}, 'x': 0.5},   
              ),

              }

    return figure

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

这是我得到的错误:

Invalid argument `figure.data[0]` passed into Graph with ID "timeseries".
Expected `object`.
Was supplied type `array`.

除了 Dash 的这个 Javascript 错误:

Error: Invalid argument `figure.data[0]` passed into Graph with ID "timeseries".

Expected `object`.

Was supplied type `array`.

    at propTypeErrorHandler (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.v1_8_0m1599348644.dev.js:90547:9)

    at CheckedComponent (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/dash_renderer.v1_8_0m1599348644.dev.js:84930:77)

    at renderWithHooks (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:14960:20)

    at updateFunctionComponent (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:17193:22)

    at beginWork (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:18778:18)

    at HTMLUnknownElement.callCallback (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:182:16)

    at Object.invokeGuardedCallbackDev (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:231:18)

    at invokeGuardedCallback (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:286:33)

    at beginWork$1 (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:23369:9)

    at performUnitOfWork (http://127.0.0.1:8050/_dash-component-suites/dash_renderer/react-dom@16.v1_8_0m1599348644.13.0.js:22323:14)

非常感谢我的程序出错的地方。

标签: pythonflaskplotplotly-dash

解决方案


这就是您的问题的来源:

    # Draw and append traces for each stock
    trace = []  


    for stock in input_data:  
        stock_info = execute_query(conn, f"SELECT date, close FROM security_price WHERE security_price.id  = '{stock}' ;") 
        for row in stock_info:
            date = []
            adj_close = []

            date.append(row[0])
            adj_close.append(row[1])
        # STEP 2
            trace.append(go.Scatter(x=date,
                                     y=adj_close,
                                     mode='lines',
                                     opacity=0.7,
                                     name=stock,
                                     textposition='bottom center'))  
    # STEP 3
    traces = [trace]

您已经制作trace了一个列表,然后将其放入traces另一个列表中。您应该将所有go.Scatter对象放入traces中,以便列表包含Scatter对象,而不是子列表。


推荐阅读