Dash 应用程序没有错误,但没有绘图

Dash app has no errors, but does not plot

我有一些长而复杂的代码似乎可以正确执行,但没有在绘制。这是怎么回事?

正在绘制的数据是一个嵌套字典,字典中的每个键对应一个下拉选项。这是一些核心代码:

from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from pandas import Timestamp
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import numpy as np
import pandas as pd
import numpy as np
from datetime import timedelta
import glob
import datetime as dt

Edit3:我修复了回调问题并能够从 dcc.Store 加载数据,这只是一个日期对象。现在,我使用该日期对象加载并格式化我的数据,结果为 final_dict。但是,之后数据仍然不想用我的代码绘制。

我很困惑为什么这不起作用。

app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
controls = dbc.Card(
    [dcc.Store(id='date_output'),
         dbc.FormGroup([
                dcc.DatePickerSingle(
                    id='my-date-picker-single',
                    min_date_allowed=dt.date(2018, 4, 17),
                    max_date_allowed=dt.date(2020, 10, 6),
                    initial_visible_month=dt.date(2020, 10, 6),
                    date=dt.date(2020, 10, 6)
            ),
        ],
    ),
        dbc.FormGroup(
                dcc.RadioItems(
                    id='hour_radio',
                    options=[{'label': '00z', 'value': '00z'},
                            {'label': '12z', 'value': '12z'}],
                    value='00z',
                    labelStyle={'display': 'inline-block'},
                    inputStyle={"margin-left": "15px","margin-right": "5px"}
                ),
            ),


       dbc.FormGroup(
            [dbc.Label("Model"),
                dcc.Dropdown(
                    id='model_dd',
                    options=[{'label': k, 'value': k} for k in model_list],
                    value=model_list[0],
                    clearable=False
                ),
            ]
        ),
        dbc.FormGroup(
            [dbc.Label("Crop"),
                dcc.Dropdown(
                    id='crop_dd',
                    options=[{'label': i.title(), 'value': i} for i in crop_list],
                    value=crop_list[0],
                    clearable=False
                ),
            ]
        ),           
        dbc.FormGroup(
            [dbc.Label("Weighting"),
                dcc.Dropdown(
                    id='weight_dd',
                    options=[{'label': i, 'value': i} for i in weight_list],
                    value=weight_list[0],
                    clearable=False
                ),
            ]
        ),
        dbc.FormGroup(
            [dbc.Label("Forecast Variable"),
                dcc.Dropdown(
                    id='columns_dd',
                    options=[{'label': i, 'value': i} for i in column_list],
                    value=column_list[0],
                    clearable=False
                ),
            ]
        ),
         dbc.FormGroup(
                dcc.RadioItems(
                    id='units_radio',
                    options=[{'label': 'Metric', 'value': 'Metric'},
                            {'label': 'Imperial', 'value': 'Imperial'}],
                    value='Metric',
                    labelStyle={'display': 'inline-block'},
                    inputStyle={"margin-left": "20px","margin-right": "5px"}
                ),
        ),

    ],
    body=True,
)


app.layout = dbc.Container(
    [
        html.Hr(),
        dbc.Row([
            dbc.Col([
                dbc.Row([
                    dbc.Col(controls)
                ],  align="start"), 
            ],xs = 2)
            ,
            dbc.Col([
                dbc.Row([
                    dbc.Col([html.Div(id = 'plot_title')],)
                ]),
                dbc.Row([
                    dbc.Col(dcc.Graph(id="crop-graph")),
                ]),
                dbc.Row([
                    dbc.Col([html.Div(id = 'date_picker')],)
                ]),
            ])
        ],), 
    ],
    fluid=True,
)



@app.callback(
    Output('date_output', 'data'),
    [Input('my-date-picker-single', 'date'),
     Input('hour_radio', 'value')])
    
    
def update_output(data, radio2):
    if radio2=='00z':
        data = pd.to_datetime(data)
    
    elif radio2=='12z':
        data = pd.to_datetime(data)
        data=data+dt.timedelta(hours=12)
    return data

 @app.callback(
    Output('crop-graph', 'figure'),
    [Input('model_dd', 'value'),
     Input('weight_dd', 'value'),
     Input('crop_dd', 'value'),
     Input('columns_dd', 'value'),
     Input('units_radio', 'value'),
     Input('date_output', 'data')])
    
def make_graph(model, weight, available_crops, vals, radio, data):
#do data formatting here, and end up with final_dict
    if radio=='Metric':
        if weight == 'Production':
            
            df_delta_prod_temp = pd.concat([final_dict[model][weight][available_crops]['time'], final_dict[model][weight][available_crops]['24h Delta Temp']], axis=1).set_index('time').resample('24h').mean().reset_index()
            df_delta_prod_precip = pd.concat([final_dict[model][weight][available_crops]['time'], final_dict[model][weight][available_crops]['24h Delta Precip']], axis=1).set_index('time').resample('24h').mean().reset_index()
            
            if vals=='Temperature':
                fig.add_trace(go.Scatter(x=final_dict[model][weight][available_crops]['time'], y=final_dict[model][weight][available_crops][vals]-273,
                                        mode = 'lines', line=dict(color='red', width=4),
                                        hovertemplate='Date: %{x|%d %b %H%M} UTC<br>Temp: %{y:.2f} C<extra></extra>'), secondary_y=True)
                fig.add_trace(go.Bar(x=df_delta_prod_temp['time']['time'],
                                 y=df_delta_prod_temp['24h Delta Temp'],
                                 marker_color = "white", opacity=1,hovertemplate='Date: %{x|%d %b}<br>Delta: %{y:.2f} C<extra></extra>'),
                          secondary_y=False)
                fig.update_yaxes(title_text="<b>Temp (C)<b>", color='red', secondary_y=True)
                fig.update_yaxes(title_text="<b>24hr Forecast Change (C)</b>", secondary_y=False)
     print(fig)
     return fig

   
app.run_server(mode='external', port = 4100, debug=True)

final_dict 的形式为 final_dict[model_key][weight_keys][crop_key][value_key][dataframe] 我收到此错误: ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). 这是在行 if vals=='Temperature' 上触发的。我在这里使用 if 语句,以便我可以正确地格式化绘图(正如您在 plot 命令后面的行中看到的那样),因为 3 个变量(温度、总降水量和总雪量)的绘图都将不同。我怎样才能解决这个问题?这是嵌套字典末尾数据框的打印结果:

24h Delta Temp  Temperature  Total Snow  24h Delta Precip  Total Precip  \
0         0.498935   290.315356         NaN               NaN           NaN   
1         0.237127   285.985779    0.000000          0.000866      0.006311   
2         0.328559   283.643185    0.000000          0.003557      0.013087   
3         0.749757   295.701362    0.000000          0.006307      0.015658   
4         0.888228   293.332520    0.000000         -0.000009      0.005487   
..             ...          ...         ...               ...           ...   
56       -2.917237   285.034693    0.009300          0.161451      0.523343   
57             NaN   281.955112    0.010279               NaN      0.729168   
58             NaN   280.365132    0.013355               NaN      0.605418   
59             NaN   287.087138    0.012851               NaN      0.522774   
60             NaN   284.684470    0.006231               NaN      0.459217   

                  time  
0  2020-10-06 00:00:00  
1  2020-10-06 06:00:00  
2  2020-10-06 12:00:00  
3  2020-10-06 18:00:00  
4  2020-10-07 00:00:00  
..                 ...  
56 2020-10-20 00:00:00  
57 2020-10-20 06:00:00  
58 2020-10-20 12:00:00  
59 2020-10-20 18:00:00  
60 2020-10-21 00:00:00 

你永远不会定义final_dict

编辑:更新答案和代码示例以回应进一步的讨论

@app.callback(
    Output('date_output', 'data'),
    [Input('my-date-picker-single', 'date'),
     Input('hour_radio', 'value')])
def update_output(date_value, radio2):
    final_dict = {
        'tempurature': {0: 1, 1: 5, 2: 3, 3: 5, 4: 1, 5: 2, 6: 5, 7: 6},
        # and so on
    }
    return final_dict

这个函数需要定义那个变量,否则它只会return None。也要小心你的缩进,因为设置的方式会阻止第二个 if 语句的执行,并且总是 return 在第一个 return 语句。

此外,你不需要括号,你可以只做 return final_dict

你的第二个回调,它输出到图中,正确地从 dcc.Store 中获取数据,但你从来没有使用它。 Input 对应于您在回调函数签名中定义的 data arg。您应该将该函数中 final_dict 的使用替换为 data.