Skip to content

Commit e9d068c

Browse files
Merge pull request #9 from Techtonique/dov080
align with R version 0.8.1
2 parents fb943f9 + 527d6f9 commit e9d068c

File tree

7 files changed

+146
-41
lines changed

7 files changed

+146
-41
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# version 0.8.1
2+
3+
- Align with R version (see [https://github.com/Techtonique/ahead/blob/main/NEWS.md#version-070](https://github.com/Techtonique/ahead/blob/main/NEWS.md#version-070) and [https://github.com/Techtonique/ahead/blob/main/NEWS.md#version-080](https://github.com/Techtonique/ahead/blob/main/NEWS.md#version-080)) as much as possible
4+
- moving block bootstrap in `ridge2f`, `basicf`, in addition to circular block bootstrap from 0.6.2
5+
- adjust R-Vine copulas on residuals for `ridge2f` simulation (with empirical and Gaussian marginals)
6+
17
# version 0.6.2
28

39
- Add Block Bootstrap to `ridge2f` and `basicf`

ahead/Basic/BasicForecaster.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,23 @@ class BasicForecaster():
2020
2121
type_pi: a string;
2222
Type of prediction interval (currently "gaussian",
23-
or "bootstrap")
23+
"bootstrap" (independent), "blockbootstrap" (circular),
24+
"movingblockbootstrap")
2425
2526
block_length: an integer
26-
length of block for multivariate circular block bootstrap (`type_pi == blockbootstrap`)
27+
length of block for multivariate block bootstrap (`type_pi == blockbootstrap`
28+
or `type_pi == movingblockbootstrap`)
2729
2830
B: an integer;
29-
Number of bootstrap replications for `type_pi == bootstrap`
31+
Number of replications
3032
3133
date_formatting: a string;
3234
Currently:
3335
- "original": yyyy-mm-dd
3436
- "ms": milliseconds
3537
3638
seed: an integer;
37-
reproducibility seed for type_pi == 'bootstrap'
39+
reproducibility seed
3840
3941
Attributes:
4042
@@ -151,8 +153,8 @@ def forecast(self, df):
151153

152154
y = mv.compute_y_mts(self.input_df, frequency)
153155

154-
if self.type_pi is "blockbootstrap":
155-
assert self.block_length is not None, "For `type_pi == 'blockbootstrap'`, `block_length` must be not None"
156+
if self.type_pi in ("blockbootstrap", "movingblockbootstrap"):
157+
assert self.block_length is not None, "For `type_pi in ('blockbootstrap', 'movingblockbootstrap')`, `block_length` must be not None"
156158

157159
self.fcast_ = config.AHEAD_PACKAGE.basicf(
158160
y,
@@ -188,7 +190,8 @@ def forecast(self, df):
188190
for i in range(n_series)
189191
)
190192

191-
if self.type_pi == "bootstrap" or self.type_pi == "blockbootstrap":
193+
if self.type_pi in ("bootstrap", "blockbootstrap",
194+
"movingblockbootstrap"):
192195
self.sims_ = tuple(
193196
np.asarray(self.fcast_.rx2["sims"][i]) for i in range(self.B)
194197
)

ahead/Ridge2/Ridge2Regressor.py

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,19 @@ class Ridge2Regressor():
4444
4545
type_pi: a string;
4646
Type of prediction interval (currently "gaussian",
47-
or "bootstrap" or "blockbootstrap")
47+
"bootstrap", (circular) "blockbootstrap", "movingblockbootstrap", or "rvinecopula")
4848
4949
block_length: an integer
50-
length of block for multivariate circular block bootstrap (`type_pi == blockbootstrap`)
50+
length of block for multivariate block bootstrap (`type_pi == blockbootstrap` or
51+
`type_pi == movingblockbootstrap`)
52+
53+
margins: a string;
54+
distribution of residuals' marginals for `type_pi == rvinecopula`: "empirical" (default),
55+
"gaussian"
5156
5257
B: an integer;
53-
Number of bootstrap replications for `type_pi == bootstrap` or `type_pi == blockbootstrap`
58+
Number of bootstrap replications for `type_pi == bootstrap`, "blockbootstrap",
59+
"movingblockbootstrap", or "rvinecopula"
5460
5561
type_aggregation: a string;
5662
Type of aggregation, ONLY for bootstrapping; either "mean" or "median"
@@ -140,6 +146,7 @@ def __init__(
140146
dropout = 0,
141147
type_pi = "gaussian",
142148
block_length = 3, # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
149+
margins = "empirical",
143150
B = 100,
144151
type_aggregation = "mean",
145152
centers = 2,
@@ -148,6 +155,12 @@ def __init__(
148155
date_formatting ="original",
149156
seed =123,
150157
):
158+
159+
if not config.R_IS_INSTALLED:
160+
raise ImportError("R is not installed! \n" + config.USAGE_MESSAGE)
161+
162+
if not config.RPY2_IS_INSTALLED:
163+
raise ImportError(config.RPY2_ERROR_MESSAGE + config.USAGE_MESSAGE)
151164

152165
self.h = h
153166
self.level = level
@@ -161,6 +174,7 @@ def __init__(
161174
self.dropout = dropout
162175
self.type_pi = type_pi
163176
self.block_length = block_length
177+
self.margins = margins
164178
self.B = B
165179
self.type_aggregation = type_aggregation
166180
self.centers = centers # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
@@ -209,29 +223,28 @@ def forecast(self, df, xreg = None):
209223

210224
if xreg is None:
211225

212-
with cv.localconverter(default_converter + config.NONE_CONVERTER):
213-
self.fcast_ = config.AHEAD_PACKAGE.ridge2f(
214-
y,
215-
xreg = xreg,
216-
h=self.h,
217-
level=self.level,
218-
lags=self.lags,
219-
nb_hidden=self.nb_hidden,
220-
nodes_sim=self.nodes_sim,
221-
activ=self.activation,
222-
a=self.a,
223-
lambda_1=self.lambda_1,
224-
lambda_2=self.lambda_2,
225-
dropout=self.dropout,
226-
type_pi=self.type_pi,
227-
block_length=self.block_length, # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
228-
B=self.B,
229-
type_aggregation = self.type_aggregation,
230-
centers = self.centers, # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
231-
type_clustering = self.type_clustering,
232-
cl=self.cl,
233-
seed=self.seed,
234-
)
226+
self.fcast_ = config.AHEAD_PACKAGE.ridge2f(
227+
y,
228+
h=self.h,
229+
level=self.level,
230+
lags=self.lags,
231+
nb_hidden=self.nb_hidden,
232+
nodes_sim=self.nodes_sim,
233+
activ=self.activation,
234+
a=self.a,
235+
lambda_1=self.lambda_1,
236+
lambda_2=self.lambda_2,
237+
dropout=self.dropout,
238+
type_pi=self.type_pi,
239+
margins=self.margins,
240+
block_length=self.block_length, # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
241+
B=self.B,
242+
type_aggregation = self.type_aggregation,
243+
centers = self.centers, # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
244+
type_clustering = self.type_clustering,
245+
cl=self.cl,
246+
seed=self.seed,
247+
)
235248

236249
else: # xreg is not None:
237250

@@ -263,6 +276,7 @@ def forecast(self, df, xreg = None):
263276
lambda_2=self.lambda_2,
264277
dropout=self.dropout,
265278
type_pi=self.type_pi,
279+
margins=self.margins,
266280
block_length=self.block_length, # can be NULL, but in R (use 0 in R instead of NULL for v0.7.0)
267281
B=self.B,
268282
type_aggregation = self.type_aggregation,
@@ -295,7 +309,8 @@ def forecast(self, df, xreg = None):
295309
for i in range(n_series)
296310
)
297311

298-
if self.type_pi == "bootstrap" or self.type_pi == "blockbootstrap":
312+
if self.type_pi in ("bootstrap", "blockbootstrap",
313+
"movingblockbootstrap", "rvinecopula"):
299314
self.sims_ = tuple(
300315
np.asarray(self.fcast_.rx2["sims"][i]) for i in range(self.B)
301316
)

ahead/utils/univariate.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from rpy2.robjects.vectors import StrVector
1111
from .unimultivariate import get_frequency
1212

13+
base = importr("base")
1314
stats = importr("stats")
1415

1516

@@ -20,10 +21,9 @@ def compute_y_ts(df, df_frequency):
2021
ts = stats.ts(
2122
FloatVector(input_series.flatten()),
2223
frequency=get_frequency(df_frequency),
24+
names = StrVector(df.columns.tolist())
2325
)
2426

25-
ts.colnames = StrVector(df.columns.tolist())
26-
2727
return ts
2828

2929

examples/basicforecaster.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,37 @@
122122
print(d4.mean_)
123123
print(d4.lower_)
124124
print(d4.upper_)
125+
126+
print("\n")
127+
print("Example 5 -----")
128+
129+
dataset = {
130+
'date' : ['2001-01-01', '2002-01-01', '2003-01-01',
131+
'2004-01-01', '2005-01-01', '2006-01-01',
132+
'2007-01-01'],
133+
'series1' : [34, 30, 35.6, 33.3, 38.1, 34.4, 33.9],
134+
'series2' : [4, 5.5, 5.6, 6.3, 5.1, 4.9, 4.7],
135+
'series3' : [100, 100.5, 100.6, 100.2, 100.1, 99.9, 101.0]}
136+
df = pd.DataFrame(dataset).set_index('date')
137+
138+
139+
d5 = BasicForecaster(h = 5, date_formatting = "original",
140+
type_pi="movingblockbootstrap", B=20, block_length=3)
141+
142+
start = time()
143+
d5.forecast(df)
144+
print(f"Elapsed: {time()-start} \n")
145+
146+
print("\n output_dates_: \n")
147+
print(d5.output_dates_)
148+
149+
print("\n mean, lower, upper as numpy arrays: \n")
150+
print(d5.mean_)
151+
print(d5.lower_)
152+
print(d5.upper_)
153+
154+
print("\n result_dfs_: \n")
155+
print(d5.result_dfs_)
156+
157+
print("\n sims_: \n")
158+
print(d5.sims_)

examples/ridge2regressor.py

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
print("\n")
3939
print(d1.ranges_[2])
4040
print("\n")
41-
plot(d1, selected_series="series1")
41+
#plot(d1, selected_series="series1")
4242

4343
print("Example 2 -----")
4444
d2 = Ridge2Regressor(h = h, date_formatting = "original")
@@ -58,7 +58,7 @@
5858
print("\n")
5959
print(d2.ranges_[2])
6060
print("\n")
61-
plot(d2, selected_series="series1")
61+
#plot(d2, selected_series="series1")
6262
print("\n")
6363

6464
print("Example 3 -----")
@@ -94,7 +94,7 @@
9494
print(d3.lower_)
9595
print(d3.upper_)
9696
print("\n")
97-
plot(d3, selected_series="series1")
97+
#plot(d3, selected_series="series1")
9898
print("\n")
9999

100100
print("Example 4 -----")
@@ -141,7 +141,7 @@
141141
print(d4.lower_)
142142
print(d4.upper_)
143143
print("\n")
144-
plot(d4, selected_series="series1")
144+
#plot(d4, selected_series="series1")
145145
print("\n")
146146

147147
# print("Example 5 -----")
@@ -191,3 +191,50 @@
191191
# plot(d5, selected_series="series1")
192192
# print("\n")
193193

194+
195+
print("Example 6 -----")
196+
197+
d6 = Ridge2Regressor(h = 7, date_formatting = "original",
198+
type_pi="rvinecopula",
199+
margins="empirical",
200+
B=10, seed=1)
201+
202+
start = time()
203+
d6.forecast(df, xreg = xreg)
204+
print(f"Elapsed: {time()-start} \n")
205+
206+
print("\n mean: \n")
207+
print(d6.mean_)
208+
209+
print("\n lower: \n")
210+
print(d6.lower_)
211+
212+
print("\n upper: \n")
213+
print(d6.upper_)
214+
215+
print("\n sims: \n")
216+
print(d6.sims_)
217+
print("\n")
218+
219+
print("Example 7 -----")
220+
221+
d7 = Ridge2Regressor(h = 7, date_formatting = "original",
222+
type_pi="rvinecopula",
223+
margins="gaussian",
224+
B=8, seed=1)
225+
226+
start = time()
227+
d7.forecast(df)
228+
print(f"Elapsed: {time()-start} \n")
229+
230+
print("\n mean: \n")
231+
print(d7.mean_)
232+
233+
print("\n lower: \n")
234+
print(d7.lower_)
235+
236+
print("\n upper: \n")
237+
print(d7.upper_)
238+
239+
print("\n sims: \n")
240+
print(d6.sims_)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from codecs import open
33
from os import path
44

5-
__version__ = "0.6.2"
5+
__version__ = "0.8.1"
66

77
here = path.abspath(path.dirname(__file__))
88

0 commit comments

Comments
 (0)