enacimie commited on
Commit
9e28cdd
·
verified ·
1 Parent(s): 642e362

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +23 -96
src/streamlit_app.py CHANGED
@@ -164,10 +164,23 @@ try:
164
  except Exception as e:
165
  st.error(f"Could not decompose series: {e}")
166
 
167
- # ACF / PACF Plots
168
  st.subheader("🔗 Autocorrelation (ACF) & Partial Autocorrelation (PACF)")
169
 
170
- max_lags = st.slider("Max lags:", min_value=10, max_value=100, value=40, step=5)
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
  col1, col2 = st.columns(2)
173
 
@@ -179,9 +192,13 @@ with col1:
179
 
180
  with col2:
181
  st.write("**PACF Plot**")
182
- fig_pacf, ax_pacf = plt.subplots(figsize=(6, 4))
183
- plot_pacf(ts.dropna(), lags=max_lags, ax=ax_pacf)
184
- st.pyplot(fig_pacf)
 
 
 
 
185
 
186
  # === FORECASTING MODELS ===
187
  st.header("🤖 Forecasting Models")
@@ -255,94 +272,4 @@ if forecast is not None:
255
  # Metrics
256
  mae = mean_absolute_error(test, forecast)
257
  mse = mean_squared_error(test, forecast)
258
- rmse = np.sqrt(mse)
259
-
260
- st.subheader("📈 Forecast Results")
261
- col1, col2, col3 = st.columns(3)
262
- col1.metric("MAE", f"{mae:.2f}")
263
- col2.metric("MSE", f"{mse:.2f}")
264
- col3.metric("RMSE", f"{rmse:.2f}")
265
-
266
- # Plot forecast vs actual
267
- fig = go.Figure()
268
- fig.add_trace(go.Scatter(x=train.index, y=train, mode='lines', name='Training', line=dict(color='blue')))
269
- fig.add_trace(go.Scatter(x=test.index, y=test, mode='lines', name='Actual', line=dict(color='green')))
270
- fig.add_trace(go.Scatter(x=test.index, y=forecast, mode='lines+markers', name='Forecast', line=dict(color='red', dash='dash')))
271
- fig.update_layout(
272
- title=f"{model_choice} Forecast",
273
- xaxis_title="Date",
274
- yaxis_title=value_col,
275
- legend=dict(x=0, y=1)
276
- )
277
- st.plotly_chart(fig, use_container_width=True)
278
-
279
- # Allow forecasting into future
280
- st.subheader("🔮 Forecast Future Periods")
281
- future_periods = st.number_input("Number of future periods to forecast:", min_value=1, max_value=365, value=30, step=1)
282
-
283
- if st.button("🚀 Generate Future Forecast"):
284
- try:
285
- if model_choice == "Holt-Winters Exponential Smoothing":
286
- future_forecast = model.forecast(future_periods)
287
- last_date = ts.index[-1]
288
- if freq == 'D':
289
- future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=future_periods, freq='D')
290
- elif freq == 'W':
291
- future_dates = pd.date_range(start=last_date + pd.Timedelta(weeks=1), periods=future_periods, freq='W')
292
- elif freq == 'M':
293
- future_dates = pd.date_range(start=last_date + pd.DateOffset(months=1), periods=future_periods, freq='M')
294
- else:
295
- future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=future_periods, freq='D')
296
-
297
- elif model_choice == "ARIMA":
298
- future_forecast = model.forecast(future_periods)
299
- last_date = ts.index[-1]
300
- if freq == 'D':
301
- future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=future_periods, freq='D')
302
- elif freq == 'W':
303
- future_dates = pd.date_range(start=last_date + pd.Timedelta(weeks=1), periods=future_periods, freq='W')
304
- elif freq == 'M':
305
- future_dates = pd.date_range(start=last_date + pd.DateOffset(months=1), periods=future_periods, freq='M')
306
- else:
307
- future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=future_periods, freq='D')
308
-
309
- elif model_choice == "Prophet":
310
- last_date = ts.index[-1]
311
- if freq == 'D':
312
- future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=future_periods, freq='D')
313
- elif freq == 'W':
314
- future_dates = pd.date_range(start=last_date + pd.Timedelta(weeks=1), periods=future_periods, freq='W')
315
- elif freq == 'M':
316
- future_dates = pd.date_range(start=last_date + pd.DateOffset(months=1), periods=future_periods, freq='M')
317
- else:
318
- future_dates = pd.date_range(start=last_date + pd.Timedelta(days=1), periods=future_periods, freq='D')
319
-
320
- future_df = pd.DataFrame({'ds': future_dates})
321
- forecast_df = model.predict(future_df)
322
- future_forecast = forecast_df['yhat'].values
323
-
324
- # Plot future forecast
325
- fig_future = go.Figure()
326
- fig_future.add_trace(go.Scatter(x=ts.index, y=ts.values, mode='lines', name='Historical', line=dict(color='blue')))
327
- fig_future.add_trace(go.Scatter(x=future_dates, y=future_forecast, mode='lines+markers', name='Future Forecast', line=dict(color='red', dash='dash')))
328
- fig_future.update_layout(
329
- title="Future Forecast",
330
- xaxis_title="Date",
331
- yaxis_title=value_col
332
- )
333
- st.plotly_chart(fig_future, use_container_width=True)
334
-
335
- # Show as table
336
- forecast_df = pd.DataFrame({
337
- 'Date': future_dates,
338
- 'Forecast': future_forecast
339
- })
340
- with st.expander("📋 View Forecast Table"):
341
- st.dataframe(forecast_df)
342
-
343
- except Exception as e:
344
- st.error(f"Could not generate future forecast: {e}")
345
-
346
- # Footer
347
- st.markdown("---")
348
- st.caption(f"© {AUTHOR} | License {LICENSE} | Contact: {EMAIL}")
 
164
  except Exception as e:
165
  st.error(f"Could not decompose series: {e}")
166
 
167
+ # ACF / PACF Plots (CORREGIDO)
168
  st.subheader("🔗 Autocorrelation (ACF) & Partial Autocorrelation (PACF)")
169
 
170
+ # Calculate safe max lags (must be < 50% of sample size for PACF)
171
+ n = len(ts.dropna())
172
+ safe_max_lag = max(1, int(n * 0.49)) # Must be strictly less than 50%
173
+
174
+ # Adjust slider dynamically
175
+ max_lags_default = min(40, safe_max_lag)
176
+ max_lags = st.slider(
177
+ "Max lags:",
178
+ min_value=1,
179
+ max_value=safe_max_lag,
180
+ value=max_lags_default,
181
+ step=1,
182
+ help=f"Max allowed lags: {safe_max_lag} (based on sample size: {n})"
183
+ )
184
 
185
  col1, col2 = st.columns(2)
186
 
 
192
 
193
  with col2:
194
  st.write("**PACF Plot**")
195
+ try:
196
+ fig_pacf, ax_pacf = plt.subplots(figsize=(6, 4))
197
+ plot_pacf(ts.dropna(), lags=max_lags, ax=ax_pacf)
198
+ st.pyplot(fig_pacf)
199
+ except Exception as e:
200
+ st.error(f"Could not generate PACF plot: {e}")
201
+ st.write("Try reducing the number of lags.")
202
 
203
  # === FORECASTING MODELS ===
204
  st.header("🤖 Forecasting Models")
 
272
  # Metrics
273
  mae = mean_absolute_error(test, forecast)
274
  mse = mean_squared_error(test, forecast)
275
+ rm