mgbam commited on
Commit
9db6dea
Β·
verified Β·
1 Parent(s): 49d873b

Update tools/forecaster.py

Browse files
Files changed (1) hide show
  1. tools/forecaster.py +23 -11
tools/forecaster.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import pandas as pd
2
  from statsmodels.tsa.arima.model import ARIMA
3
  import plotly.graph_objects as go
@@ -5,28 +7,38 @@ import plotly.graph_objects as go
5
  def forecast_metric_tool(file_path: str, date_col: str, value_col: str):
6
  """
7
  Forecast next 3 periods for any numeric metric.
8
- Saves PNG and returns forecast DataFrame as text.
9
  """
 
10
  df = pd.read_csv(file_path)
11
 
 
12
  try:
13
  df[date_col] = pd.to_datetime(df[date_col])
14
  except Exception:
15
- return f"❌ '{date_col}' not parseable as dates."
16
 
17
- if value_col not in df.columns:
18
- return f"❌ '{value_col}' column missing."
 
19
 
20
- df.set_index(date_col, inplace=True)
21
- model = ARIMA(df[value_col], order=(1, 1, 1))
22
- model_fit = model.fit()
23
- forecast = model_fit.forecast(steps=3)
24
 
25
- # Plot
 
 
 
 
 
 
 
 
26
  fig = go.Figure()
27
- fig.add_scatter(x=df.index, y=df[value_col], mode="lines", name=value_col)
28
  fig.add_scatter(x=forecast.index, y=forecast, mode="lines", name="Forecast")
29
  fig.update_layout(title=f"{value_col} Forecast", template="plotly_dark")
30
- fig.write_image("forecast_plot.png")
31
 
 
32
  return forecast.to_frame(name="Forecast").to_string()
 
1
+ # tools/forecaster.py
2
+
3
  import pandas as pd
4
  from statsmodels.tsa.arima.model import ARIMA
5
  import plotly.graph_objects as go
 
7
  def forecast_metric_tool(file_path: str, date_col: str, value_col: str):
8
  """
9
  Forecast next 3 periods for any numeric metric.
10
+ Saves PNG to /tmp via our safe write monkey-patch, returns forecast table as text.
11
  """
12
+ # 1) Load
13
  df = pd.read_csv(file_path)
14
 
15
+ # 2) Parse dates
16
  try:
17
  df[date_col] = pd.to_datetime(df[date_col])
18
  except Exception:
19
+ return f"❌ Could not parse '{date_col}' as dates."
20
 
21
+ # 3) Coerce metric to numeric, drop invalid
22
+ df[value_col] = pd.to_numeric(df[value_col], errors="coerce")
23
+ series = df.set_index(date_col)[value_col].dropna()
24
 
25
+ if series.empty:
26
+ return f"❌ Column '{value_col}' has no valid numeric data after coercion."
 
 
27
 
28
+ # 4) Fit ARIMA
29
+ try:
30
+ model = ARIMA(series, order=(1, 1, 1))
31
+ model_fit = model.fit()
32
+ except Exception as e:
33
+ return f"❌ ARIMA fitting failed: {e}"
34
+
35
+ # 5) Forecast & plot
36
+ forecast = model_fit.forecast(steps=3)
37
  fig = go.Figure()
38
+ fig.add_scatter(x=series.index, y=series, mode="lines", name=value_col)
39
  fig.add_scatter(x=forecast.index, y=forecast, mode="lines", name="Forecast")
40
  fig.update_layout(title=f"{value_col} Forecast", template="plotly_dark")
41
+ fig.write_image("forecast_plot.png") # goes into /tmp thanks to our monkey-patch
42
 
43
+ # 6) Return textual table
44
  return forecast.to_frame(name="Forecast").to_string()