Skip to content

Commit cee6171

Browse files
to v0.6.0 with BasicForecaster
1 parent e3d19d9 commit cee6171

File tree

23 files changed

+614
-147
lines changed

23 files changed

+614
-147
lines changed

.DS_Store

0 Bytes
Binary file not shown.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,6 @@ ENV/
106106

107107
# R artifacts
108108
R-package/.Rproj.*
109+
110+
# Apple stuff
111+
.DS_Store

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ Welcome to __ahead__ (Python version; the R version is [here](https://github.com
99

1010
`ahead` is a package for univariate and multivariate **time series forecasting**. The Python version is built on top of [the R package](https://techtonique.github.io/ahead/) with the same name. __ahead__'s source code is [available on GitHub](https://github.com/Techtonique/ahead_python).
1111

12-
Currently, 5 forecasting methods are implemented in the Python package:
12+
Currently, 6 forecasting methods are implemented in the Python package:
1313

1414
- `DynamicRegressor`: **univariate** time series forecasting method adapted from [`forecast::nnetar`](https://otexts.com/fpp2/nnetar.html#neural-network-autoregression).
1515
The Python implementation contains only the [automatic version](https://thierrymoudiki.github.io/blog/2021/10/22/r/misc/ahead-ridge).
1616
- `EAT`: **univariate** time series forecasting method based on combinations of R's `forecast::ets`, `forecast::auto.arima`, and `forecast::thetaf`
1717
- `ArmaGarch`: **univariate** forecasting simulations of an ARMA(1, 1)-GARCH(1, 1)
18+
- `BasicForecaster`: **multivariate** time series forecasting methods; mean, median and random walk
1819
- `Ridge2Regressor`: **multivariate** time series forecasting method, based on __quasi-randomized networks__ and presented in [this paper](https://www.mdpi.com/2227-9091/6/1/22)
1920
- `VAR`: **multivariate** time series forecasting method using Vector AutoRegressive model (VAR, mostly here for benchmarking purpose)
2021

ahead/Basic/BasicForecaster.py

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import os
2+
import numpy as np
3+
import pandas as pd
4+
5+
from rpy2.robjects.packages import importr
6+
from rpy2.robjects import FloatVector, numpy2ri
7+
import rpy2.robjects as robjects
8+
import rpy2.robjects.packages as rpackages
9+
from datetime import datetime
10+
from rpy2.robjects.vectors import StrVector
11+
12+
from ..utils import multivariate as mv
13+
from ..utils import unimultivariate as umv
14+
15+
required_packages = ["ahead"] # list of required R packages
16+
17+
if all(rpackages.isinstalled(x) for x in required_packages):
18+
check_packages = True # True if packages are already installed
19+
else:
20+
check_packages = False # False if packages are not installed
21+
22+
if check_packages == False: # Not installed? Then install.
23+
24+
packages_to_install = [
25+
x for x in required_packages if not rpackages.isinstalled(x)
26+
]
27+
28+
if len(packages_to_install) > 0:
29+
base = importr("base")
30+
utils = importr("utils")
31+
base.options(
32+
repos=base.c(
33+
techtonique="https://techtonique.r-universe.dev",
34+
CRAN="https://cloud.r-project.org",
35+
)
36+
)
37+
utils.install_packages(StrVector(packages_to_install))
38+
check_packages = True
39+
40+
base = importr("base")
41+
stats = importr("stats")
42+
ahead = importr("ahead")
43+
44+
45+
class BasicForecaster(object):
46+
"""Basic forecasting functions for multivariate time series (mean, median, random walk)
47+
48+
Parameters:
49+
50+
h: an integer;
51+
forecasting horizon
52+
53+
level: an integer;
54+
Confidence level for prediction intervals
55+
56+
method: a string;
57+
Forecasting method, either "mean", "median", or random walk ("rw")
58+
59+
type_pi: a string;
60+
Type of prediction interval (currently "gaussian",
61+
or "bootstrap")
62+
63+
B: an integer;
64+
Number of bootstrap replications for `type_pi == bootstrap`
65+
66+
date_formatting: a string;
67+
Currently:
68+
- "original": yyyy-mm-dd
69+
- "ms": milliseconds
70+
71+
seed: an integer;
72+
reproducibility seed for type_pi == 'bootstrap'
73+
74+
Attributes:
75+
76+
fcast_: an object;
77+
raw result from fitting R's `ahead::ridge2f` through `rpy2`
78+
79+
averages_: a list of lists;
80+
mean forecast in a list for each series
81+
82+
ranges_: a list of lists;
83+
lower and upper prediction intervals in a list for each series
84+
85+
output_dates_: a list;
86+
a list of output dates (associated to forecast)
87+
88+
mean_: a numpy array
89+
contains series mean forecast as a numpy array
90+
91+
lower_: a numpy array
92+
contains series lower bound forecast as a numpy array
93+
94+
upper_: a numpy array
95+
contains series upper bound forecast as a numpy array
96+
97+
result_dfs_: a tuple of data frames;
98+
each element of the tuple contains 3 columns,
99+
mean forecast, lower + upper prediction intervals,
100+
and a date index
101+
102+
sims_: currently a tuple of numpy arrays
103+
for `type_pi == bootstrap`, simulations for each series
104+
105+
Examples:
106+
107+
```python
108+
import pandas as pd
109+
from ahead import BasicForecaster
110+
111+
# Data frame containing the time series
112+
dataset = {
113+
'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'],
114+
'series1' : [34, 30, 35.6, 33.3, 38.1],
115+
'series2' : [4, 5.5, 5.6, 6.3, 5.1],
116+
'series3' : [100, 100.5, 100.6, 100.2, 100.1]}
117+
df = pd.DataFrame(dataset).set_index('date')
118+
print(df)
119+
120+
# multivariate time series forecasting
121+
r1 = BasicForecaster(h = 5)
122+
r1.forecast(df)
123+
print(r1.result_dfs_)
124+
```
125+
126+
"""
127+
128+
def __init__(
129+
self,
130+
h=5,
131+
level=95,
132+
method="mean",
133+
type_pi="gaussian",
134+
B=100,
135+
date_formatting="original",
136+
seed=123,
137+
):
138+
139+
self.h = h
140+
self.level = level
141+
self.method = method
142+
self.type_pi = type_pi
143+
self.B = B
144+
self.date_formatting = date_formatting
145+
self.seed = seed
146+
147+
self.averages_ = None
148+
self.ranges_ = None
149+
self.output_dates_ = []
150+
self.mean_ = None
151+
self.lower_ = None
152+
self.upper_ = None
153+
self.result_df_s_ = None
154+
self.sims_ = None
155+
156+
def forecast(self, df):
157+
"""Forecasting method from `BasicForecaster` class
158+
159+
Parameters:
160+
161+
df: a data frame;
162+
a data frame containing the input time series (see example)
163+
164+
"""
165+
166+
self.input_df = df
167+
n_series = len(df.columns)
168+
169+
# obtain dates 'forecast' -----
170+
171+
output_dates, frequency = umv.compute_output_dates(
172+
self.input_df, self.h
173+
)
174+
175+
# obtain time series forecast -----
176+
177+
y = mv.compute_y_mts(self.input_df, frequency)
178+
self.fcast_ = ahead.basicf(
179+
y,
180+
h=self.h,
181+
level=self.level,
182+
method=self.method,
183+
type_pi=self.type_pi,
184+
B=self.B,
185+
seed=self.seed,
186+
)
187+
188+
# result -----
189+
190+
(
191+
self.averages_,
192+
self.ranges_,
193+
self.output_dates_,
194+
) = mv.format_multivariate_forecast(
195+
n_series=n_series,
196+
date_formatting=self.date_formatting,
197+
output_dates=output_dates,
198+
horizon=self.h,
199+
fcast=self.fcast_,
200+
)
201+
202+
self.mean_ = np.asarray(self.fcast_.rx2['mean'])
203+
self.lower_= np.asarray(self.fcast_.rx2['lower'])
204+
self.upper_= np.asarray(self.fcast_.rx2['upper'])
205+
206+
self.result_dfs_ = tuple(
207+
umv.compute_result_df(self.averages_[i], self.ranges_[i])
208+
for i in range(n_series)
209+
)
210+
211+
if self.type_pi == "bootstrap":
212+
self.sims_ = tuple(
213+
np.asarray(self.fcast_.rx2["sims"][i]) for i in range(self.B)
214+
)
215+
216+
return self

ahead/Basic/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .BasicForecaster import BasicForecaster
2+
3+
__all__ = ["BasicForecaster"]

ahead/DynamicRegressor/DynamicRegressor.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -90,23 +90,23 @@ class DynamicRegressor(object):
9090
9191
Examples:
9292
93-
```
94-
import pandas as pd
95-
from ahead import DynamicRegressor
96-
97-
# Data frame containing the time series
98-
dataset = {
99-
'date' : ['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01', '2020-05-01'],
100-
'value' : [34, 30, 35.6, 33.3, 38.1]}
101-
102-
df = pd.DataFrame(dataset).set_index('date')
103-
print(df)
104-
105-
# univariate time series forecasting
106-
d1 = DynamicRegressor(h = 5)
107-
d1.forecast(df)
108-
print(d1.result_df_)
109-
```
93+
```python
94+
import pandas as pd
95+
from ahead import DynamicRegressor
96+
97+
# Data frame containing the time series
98+
dataset = {
99+
'date' : ['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01', '2020-05-01'],
100+
'value' : [34, 30, 35.6, 33.3, 38.1]}
101+
102+
df = pd.DataFrame(dataset).set_index('date')
103+
print(df)
104+
105+
# univariate time series forecasting
106+
d1 = DynamicRegressor(h = 5)
107+
d1.forecast(df)
108+
print(d1.result_df_)
109+
```
110110
111111
"""
112112

ahead/EAT/EAT.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,23 +95,23 @@ class EAT(object):
9595
9696
Examples:
9797
98-
```
99-
import pandas as pd
100-
from ahead import EAT
101-
102-
# Data frame containing the time series
103-
dataset = {
104-
'date' : ['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01', '2020-05-01'],
105-
'value' : [34, 30, 35.6, 33.3, 38.1]}
106-
107-
df = pd.DataFrame(dataset).set_index('date')
108-
print(df)
109-
110-
# univariate time series forecasting
111-
e1 = EAT(h = 5) # default, equal weights for each model=[1/3, 1/3, 1/3]
112-
e1.forecast(df)
113-
print(e1.result_df_)
114-
```
98+
```python
99+
import pandas as pd
100+
from ahead import EAT
101+
102+
# Data frame containing the time series
103+
dataset = {
104+
'date' : ['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01', '2020-05-01'],
105+
'value' : [34, 30, 35.6, 33.3, 38.1]}
106+
107+
df = pd.DataFrame(dataset).set_index('date')
108+
print(df)
109+
110+
# univariate time series forecasting
111+
e1 = EAT(h = 5) # default, equal weights for each model=[1/3, 1/3, 1/3]
112+
e1.forecast(df)
113+
print(e1.result_df_)
114+
```
115115
116116
"""
117117

ahead/Ridge2/Ridge2Regressor.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,24 @@ class Ridge2Regressor(object):
130130
131131
Examples:
132132
133-
```
134-
import pandas as pd
135-
from ahead import Ridge2Regressor
136-
137-
# Data frame containing the time series
138-
dataset = {
139-
'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'],
140-
'series1' : [34, 30, 35.6, 33.3, 38.1],
141-
'series2' : [4, 5.5, 5.6, 6.3, 5.1],
142-
'series3' : [100, 100.5, 100.6, 100.2, 100.1]}
143-
df = pd.DataFrame(dataset).set_index('date')
144-
print(df)
145-
146-
# multivariate time series forecasting
147-
r1 = Ridge2Regressor(h = 5)
148-
r1.forecast(df)
149-
print(r1.result_dfs_)
150-
```
133+
```python
134+
import pandas as pd
135+
from ahead import Ridge2Regressor
136+
137+
# Data frame containing the time series
138+
dataset = {
139+
'date' : ['2001-01-01', '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01'],
140+
'series1' : [34, 30, 35.6, 33.3, 38.1],
141+
'series2' : [4, 5.5, 5.6, 6.3, 5.1],
142+
'series3' : [100, 100.5, 100.6, 100.2, 100.1]}
143+
df = pd.DataFrame(dataset).set_index('date')
144+
print(df)
145+
146+
# multivariate time series forecasting
147+
r1 = Ridge2Regressor(h = 5)
148+
r1.forecast(df)
149+
print(r1.result_dfs_)
150+
```
151151
152152
"""
153153

0 commit comments

Comments
 (0)