Skip to content

Commit 9296aa1

Browse files
univariate ridge2+plot
1 parent ad8d9c7 commit 9296aa1

File tree

4 files changed

+110
-28
lines changed

4 files changed

+110
-28
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ dist: clean ## builds source and wheel package
7575
ls -l dist
7676

7777
install: clean ## install the package to the active Python's site-packages
78-
pip install -e .
78+
uv pip install -e .
7979

8080
build-site: docs ## export mkdocs website to a folder
8181
cp -rf ahead-docs/* ../../Pro_Website/Techtonique.github.io/ahead_python

ahead/Base/Base.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,13 @@ def get_forecast(self, method=None, xreg=None):
240240
self.fcast_ = config.AHEAD_PACKAGE.mlarchf(**mlarch_args)
241241

242242

243-
def plot(self, series, type_axis="dates", type_plot="pi"):
243+
def plot(self, series=None, type_axis="dates", type_plot="pi"):
244244
"""Plot time series forecast
245245
246246
Parameters:
247247
248-
series: {integer} or {string}
249-
series index or name
248+
series: {integer} or {string} or {None}
249+
series index or name. Optional when univariate; defaults to the only series.
250250
"""
251251
assert all(
252252
[
@@ -257,7 +257,15 @@ def plot(self, series, type_axis="dates", type_plot="pi"):
257257
]
258258
), "model forecasting must be obtained first (with `forecast` method)"
259259

260-
if isinstance(series, str):
260+
# Auto-select the only series in univariate case if not provided
261+
if (self.n_series == 1) and (series is None):
262+
series_idx = 0
263+
try:
264+
series = self.series_names[0]
265+
except Exception:
266+
series = 0
267+
268+
elif isinstance(series, str):
261269
assert (
262270
series in self.series_names
263271
), f"series {series} doesn't exist in the input dataset"
@@ -268,11 +276,19 @@ def plot(self, series, type_axis="dates", type_plot="pi"):
268276
), f"check series index (< {self.n_series})"
269277
series_idx = series
270278

271-
y_all = list(self.input_df.iloc[:, series_idx]) + list(
272-
self.result_dfs_[series_idx]["mean"].values
273-
)
274-
275-
y_test = list(self.result_dfs_[series_idx]["mean"].values)
279+
# Build y vectors depending on storage (multivariate uses result_dfs_, univariate uses mean_/lower_/upper_)
280+
if self.result_dfs_ is not None:
281+
y_test_arr = self.result_dfs_[series_idx]["mean"].values
282+
y_all = list(self.input_df.iloc[:, series_idx]) + list(y_test_arr)
283+
y_test = list(y_test_arr)
284+
lower_arr = self.result_dfs_[series_idx]["lower"].values
285+
upper_arr = self.result_dfs_[series_idx]["upper"].values
286+
else:
287+
y_test_arr = np.asarray(self.mean_).reshape(-1)
288+
lower_arr = np.asarray(self.lower_).reshape(-1)
289+
upper_arr = np.asarray(self.upper_).reshape(-1)
290+
y_all = list(self.input_df.iloc[:, series_idx]) + list(y_test_arr)
291+
y_test = list(y_test_arr)
276292
n_points_all = len(y_all)
277293
n_points_train = self.input_df.shape[0]
278294

@@ -291,8 +307,8 @@ def plot(self, series, type_axis="dates", type_plot="pi"):
291307
ax.plot(x_test, y_test, "-", color="orange")
292308
ax.fill_between(
293309
x_test,
294-
self.result_dfs_[series_idx]["lower"].values,
295-
self.result_dfs_[series_idx]["upper"].values,
310+
lower_arr,
311+
upper_arr,
296312
alpha=0.2,
297313
color="orange",
298314
)

ahead/Ridge2/Ridge2Regressor.py

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from ..Base import Base
1212
from ..utils import multivariate as mv
13+
from ..utils import univariate as uv
1314
from ..utils import unimultivariate as umv
1415
from .. import config
1516

@@ -146,7 +147,7 @@ def __init__(
146147
self,
147148
h=5,
148149
level=95,
149-
lags=1,
150+
lags=15,
150151
nb_hidden=5,
151152
nodes_sim="sobol",
152153
activation="relu",
@@ -228,26 +229,42 @@ def forecast(self, df, xreg=None):
228229
self.get_forecast("ridge2")
229230

230231
# result -----
231-
(
232-
self.averages_,
233-
self.ranges_,
234-
_,
235-
) = mv.format_multivariate_forecast(
236-
n_series=self.n_series,
237-
date_formatting=self.date_formatting,
238-
output_dates=self.output_dates_,
239-
horizon=self.h,
240-
fcast=self.fcast_,
241-
)
232+
try:
233+
(
234+
self.averages_,
235+
self.ranges_,
236+
_,
237+
) = mv.format_multivariate_forecast(
238+
n_series=self.n_series,
239+
date_formatting=self.date_formatting,
240+
output_dates=self.output_dates_,
241+
horizon=self.h,
242+
fcast=self.fcast_,
243+
)
244+
except Exception:
245+
# result -----
246+
(
247+
self.averages_,
248+
self.ranges_,
249+
_,
250+
) = uv.format_univariate_forecast(
251+
date_formatting=self.date_formatting,
252+
output_dates=self.output_dates_,
253+
horizon=self.h,
254+
fcast=self.fcast_,
255+
)
242256

243257
self.mean_ = np.asarray(self.fcast_.rx2["mean"])
244258
self.lower_ = np.asarray(self.fcast_.rx2["lower"])
245259
self.upper_ = np.asarray(self.fcast_.rx2["upper"])
246260

247-
self.result_dfs_ = tuple(
248-
umv.compute_result_df(self.averages_[i], self.ranges_[i])
249-
for i in range(self.n_series)
250-
)
261+
try:
262+
self.result_dfs_ = tuple(
263+
umv.compute_result_df(self.averages_[i], self.ranges_[i])
264+
for i in range(self.n_series)
265+
)
266+
except Exception:
267+
self.result_df_ = umv.compute_result_df(self.averages_, self.ranges_)
251268

252269
if self.type_pi in (
253270
"bootstrap",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import os
2+
import numpy as np
3+
import pandas as pd
4+
from ahead import Ridge2Regressor
5+
from time import time
6+
7+
8+
print(f"\n ----- Running: {os.path.basename(__file__)}... ----- \n")
9+
10+
# Forecasting horizon
11+
h = 20
12+
13+
14+
# Data frame containing the time series
15+
df = pd.read_csv("https://raw.githubusercontent.com/Techtonique/datasets/refs/heads/main/time_series/univariate/AirPassengers.csv").set_index('date')
16+
df.index = pd.DatetimeIndex(df.index)
17+
print(df)
18+
19+
# univariate ts forecasting
20+
print("Example 1 -----")
21+
d1 = Ridge2Regressor(h = h, date_formatting = "original")
22+
23+
start = time()
24+
d1.forecast(df)
25+
print(f"Elapsed: {time()-start} \n")
26+
print("averages: \n")
27+
print(d1.averages_)
28+
print("\n")
29+
print("ranges: \n")
30+
print(d1.ranges_)
31+
print("\n")
32+
d1.plot()
33+
34+
print("Example 2 -----")
35+
36+
d3 = Ridge2Regressor(h = h, date_formatting = "original",
37+
type_pi="bootstrap", B=5)
38+
39+
start = time()
40+
d3.forecast(df)
41+
print(f"Elapsed: {time()-start} \n")
42+
43+
print(d3.fcast_.rx2['mean'])
44+
print(d3.averages_[1])
45+
print(np.asarray(d3.fcast_.rx2['mean']))
46+
47+
print(d3.fcast_.rx2['sims'][0])
48+
print(d3.fcast_.rx2['sims'][1])
49+
d3.plot()

0 commit comments

Comments
 (0)