Reputation: 1061
I have some long convoluted code that seems to be executing properly, but is not plotting. What is going on here?
The data that is being plotted is a nested dictionary, with each key in the dictionary corresponding to a dropdown option. Here is some of the core code:
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: I fixed the callback issue and was able load in the data from the dcc.Store, which was just a date object. Now, I load in and format my data using that date object, which results in final_dict
. However, the data still doesn't want to plot with my code afterwards.
I am confused why this isn't working.
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
is in the form of final_dict[model_key][weight_keys][crop_key][value_key][dataframe]
I am getting this error:
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
This is being triggered on the line if vals=='Temperature'
. I am using the if statement here so that I can properly format the plot (as you can see in the lines following the plot command), as plotting for the 3 variables (Temperature, Total Precip, and Total Snow) will all be different. How can I fix this? Here is a print out of a the dataframe at the end of the nested dict:
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
Upvotes: 1
Views: 1142
Reputation: 6616
You never define final_dict
Edit: updated answer and code example to respond to further discussion
@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
This function needs to define that variable, otherwise it's just going to return None
. Be careful of your indentation as well, because the way this is set up would prevent the second if
statement from ever executing, and would ALWAYS return at the first return
statement.
Also, you don't need the parens, you can just do return final_dict
.
Your second callback, which outputs to the figure, is taking in the data from the dcc.Store
correctly, but you don't ever use it. That Input
corresponds to the data
arg you defined in the callback function's signature. You should replace uses of final_dict
in that function with data
.
Upvotes: 2