Here is the complete code some example files are there.
app = dash.Dash()
app.scripts.config.serve_locally = True
app.config[‘suppress_callback_exceptions’]=True
#app.title = ‘Forecasting Tool’
#server = app.server
app.layout = html.Div([
html.H3(datetime.datetime.now().strftime('%d/%m/%Y %H:%M'), style={'color': 'blue','align': 'right', 'fontSize': 18}),
html.Div(children=[
dcc.Markdown(children='''### Forecast Model for Laundry System: '''),
#Add filters for the data
html.Div([
html.Div([html.Label('Choose Data to Show:'),
dcc.RadioItems(id='dataselector', options=[
{'label': 'View Data Only', 'value': 1},
{'label': 'View Data and Forecast', 'value': 2},
{'label': 'View Forecast Only', 'value': 3}
], value=2, labelStyle={'display': 'inline-block'})
], style={'width': '30%', 'display': 'inline-block'}),
], style={'borderBottom': 'thin lightgrey dotted', 'padding': '20px 5px'}),
#Graph
html.Div([dcc.Graph(id='graph-daily')], style={'backgroundColor': '#fbebe0','margin-top':'10px','padding': '10 10','borderRadius': '5px', 'display': 'inline-block', 'width': '100%',}),
#Choose Forecasting Model
html.Div([html.Label('Choose Forecasting Model:'),
dcc.Dropdown(id='model-dropdown',
options=[
{'label': 'ARIMA Time Series', 'value': 1},
{'label': 'FB Prophet', 'value': 2},
{'label': 'Average Forecast', 'value': 3}], value=3)
], style={'width': '100%','display': 'inline-block', 'float': 'left'}),
#Take ARIMA Inputs
html.Div([
html.Div(dcc.Input(id='arima-p', type='number', placeholder='AR(p)= 0'), style={'display': 'inline-block'}),
html.Div(dcc.Input(id='arima-d', type='number', placeholder='I(d)= 1'), style={'display': 'inline-block'}),
html.Div(dcc.Input(id='arima-q', type='number', placeholder='MA(q)= 0'), style={'display': 'inline-block'}),
html.Button('Submit ARIMA Parameters ', id='arima-submit', className='button-primary'),
html.Div(id='output-container-button',
children='Enter ARIMA parameters and click Submit to refresh forecast!')], id='arima-inputblock'),
#Take Moving Average Inputs
html.Div([
html.Div(dcc.Input(id='n_weeks', type='number', placeholder='#Week for averaging = 3'), style={'display': 'inline-block'}),
html.Div(dcc.Input(id='period', type='number', placeholder='Period = 3'), style={'display': 'inline-block'}),
html.Button('Update Moving Average Forecast ', id='movingavg-submit', className='button-primary'),
html.Div(id='output-container-button-ma',
children='Enter Moving Average parameters and click Submit to refresh forecast!')], id='movingavg-inputblock'),
#Stores df-to-json for a forecast method
html.Div(id='intermediate-value', style={'display': 'none'}),
#Stores uploded data converted to df-to-json
html.Div(id='upload-data-df', style={'display': 'none'}),
html.Div([html.Label('Choose Laundry Status to Forecast:'),
dcc.Dropdown(id='select-dataset',
options=[{'label': 'Entry Laundry Items', 'value': 1},
{'label': 'Sorting Laundry Items', 'value': 2},
{'label': 'Processing Laundry Items', 'value': 3},
{'label': 'Complete Laundry Items', 'value': 4}],
placeholder='Select Here to Forecast', value='',style={}),
], style={'backgroundColor': '#ebebe0','margin-top':'10px', 'padding': '10', 'borderRadius': '5px','display': 'inline-block', 'width': '100%', 'verticalAlign': 'middle'})
]),
html.Div(id='output-data-upload'),
#html.Div(dte.DataTable(data=[{}]), style={'display': 'none'})
])
def return_a_textbox(value):
‘’’
‘’’
if value:
return html.Div([
html.Div(dcc.Input(id=‘input-box’, type=‘text’)),
html.Button(‘Submit’, id=‘button’),
html.Div(id=‘output-container-button’,
children=‘Enter a value and press submit’)])
#--------------------------------------------------------
#Show ARIMA input parameters block
@app.callback(
Output(‘arima-inputblock’, ‘style’),
[Input(‘model-dropdown’, ‘value’)])
def update_arimablock(value):
if value ==1:
return {‘display’: ‘block’, ‘padding’: ‘20 0’}
else:
return {‘display’: ‘none’}
#--------------------------------------------------------
#Show ARIMA input parameters block
@app.callback(
Output(‘movingavg-inputblock’, ‘style’),
[Input(‘model-dropdown’, ‘value’)])
def update_movingavgblock(value):
if value ==3:
return {‘display’: ‘block’, ‘padding’: ‘20 0’}
else:
return {‘display’: ‘none’}
#--------------------------------------------------------
#Generate forecasts - Forecast dataframe is generated
@app.callback(
Output(‘intermediate-value’, ‘children’),
[Input(‘upload-data-df’, ‘children’),
Input(‘model-dropdown’, ‘value’),
Input(‘arima-submit’, ‘n_clicks’),
Input(‘movingavg-submit’, ‘n_clicks’)],
[State(‘arima-p’, ‘value’),
State(‘arima-d’, ‘value’),
State(‘arima-q’, ‘value’),
State(‘n_weeks’, ‘value’),
State(‘period’, ‘value’)])
def update_daily_view(uploaded_df, modelselected, arima_n_clicks, ma_n_clicks, arimap=1, arimad=0, arimaq=1,n_weeks_ma=6, period_ma=4):
print("-----Printing Uploaded Data------")
print(uploaded_df)
#print("-----Printing Uploaded Data Done ------")
df = pd.read_json(uploaded_df, orient='split').dropna()
#df['Date'] = pd.to_datetime(df['Date'], format='%Y/%m/%d %H:%M', )
print(df)
if modelselected ==1: #1=ARIMA
df_final = fcst.fcst_wklyavg(df, stop_at_futuredates=1)
arima_fcst = forecast_models.forecast_ARIMA(df, p=arimap, d=arimad, q=arimaq)
df_final['Forecast'][df.shape[0]:] = arima_fcst[0][0]
print("modelselected 1")
#return df_final.to_json(date_format='iso', orient='split')
elif modelselected == 2: #2= FB Prophet
df_final = fcst.fcst_wklyavg(df, stop_at_futuredates=1)
print('--------------Empty forecast dataframe generated-----------')
print(df_final.tail())
prophetfcst = forecast_models.forecast_FBProphet(df, futureperiod=15)
df_final['Forecast'][df.shape[0]:] = prophetfcst['yhat'][df.shape[0]:]
df_final = plot_error_range(df, df_final, prophetfcst)
#return df_final.to_json(date_format='iso', orient='split')
df_final = df_final.rename(columns={'ds':'Date', 'yhat':'Forecast'})
print("modelselected 2")
elif modelselected ==3: #3=Moving Average
df_final = fcst.fcst_wklyavg(df, n_week=n_weeks_ma, data_period=period_ma)
print(df_final.tail())
print("modelselected 3")
print("Print final data here:",df_final)
return df_final.to_json(date_format='iso', orient='split')
#--------------------------------------------------------
def plot_error_range(df, df_final, df_fcst, modelselected=3):
‘’’
‘’’
df_final[‘Forecast_upper’]=0.0
df_final[‘Forecast_lower’]=0.0
if modelselected ==3: #FB Prophet Model
df_final['Forecast_upper'][df.shape[0]:] = df_fcst['yhat_upper'][df.shape[0]:]
df_final['Forecast_lower'][df.shape[0]:] = df_fcst['yhat_lower'][df.shape[0]:]
print("-----error range df returned------")
print(df_final.tail())
return df_final
#--------------------------------------------------------
#Update graph based on filters
app.callback(
Output(‘graph-daily’, ‘figure’),
[#Input(‘date-dropdown’, ‘value’),
Input(‘dataselector’, ‘value’),
Input(‘intermediate-value’, ‘children’)
#dash.dependencies.Input(‘adj-forecast-df’, ‘children’)
])
def update_daily_viewfilters(dataselected, json_intermediate_data):
‘’’
‘’’
filtered_df = pd.read_json(json_intermediate_data, orient=‘split’)
#print("-------->>> using original forecast", df_final)
#date_dict, values_date_default = dropdown_dict(df_final)
#filtered_df = df_final[‘Date’]#.dt.month.isin(selected_month)]
traces = []
print(“dataselected”,traces)
if dataselected !=3: #Option 3 is Forecast Only!
traces.append(go.Scatter(
x=filtered_df[filtered_df[‘Items’]>0][‘Date’],
y=filtered_df[filtered_df[‘Items’]>0][‘Items’],
mode=‘lines’, name=‘Actuals’
))
if dataselected !=1: #Option 1 is Data Only!
traces.append(go.Scatter(
x=filtered_df[filtered_df[‘Forecast’]>0][‘Date’],
y=filtered_df[filtered_df[‘Forecast’]>0][‘Forecast’],
mode=‘lines’, name=‘Forecast’
))
if ‘Forecast_upper’ in filtered_df.columns:
traces.append(go.Scatter(
x=filtered_df[filtered_df[‘Forecast’]>0][‘Date’].tolist() + filtered_df[filtered_df[‘Forecast’]>0][‘Date’].tolist()[::-1],
y=filtered_df[filtered_df[‘Forecast’]>0][‘Forecast_upper’].tolist() + filtered_df[filtered_df[‘Forecast’]>0][‘Forecast_lower’].tolist()[::-1],
fill=‘tozeroy’, fillcolor=‘rgba(0,100,80,0.2)’, line=dict(color=‘rgba(255,255,255,0)’), name=‘Forecast-errorzone’
))
return {
'data': traces,
'layout': go.Layout(
xaxis={'title': 'Date of Laundry'},
yaxis={'title': 'Items'},
hovermode='closest',
)
}
#--------------------------------------------------------
#Store the uploaded DF
@app.callback(Output(‘upload-data-df’, ‘children’),
[Input(‘select-dataset’, ‘value’)])
#def update_output(list_of_contents, list_of_names, list_of_dates, dataset_selected):
def update_output(dataset_selected):
if dataset_selected == 1:
return pd.read_csv(‘sample_datasets/Item0.csv’).to_json(date_format=‘iso’, orient=‘split’)
elif dataset_selected == 2:
return pd.read_csv('sample_datasets/Item1.csv').to_json(date_format='iso', orient='split')
elif dataset_selected == 3:
return pd.read_csv('sample_datasets/Item2.csv').to_json(date_format='iso', orient='split')
elif dataset_selected == 4:
return pd.read_csv('sample_datasets/Item3.csv').to_json(date_format='iso', orient='split')
if name == ‘main’:
app.run_server(debug=True, port=8055)