some new features

This commit is contained in:
ilgazca
2025-07-30 17:09:11 +03:00
parent db5d46760a
commit 8019bd3b7c
20616 changed files with 4375466 additions and 8 deletions

View File

@ -0,0 +1,348 @@
315.58
316.39
316.79
317.82
318.39
318.22
316.68
315.01
314.02
313.55
315.02
315.75
316.52
317.1
317.79
319.22
320.08
319.7
318.27
315.99
314.24
314.05
315.05
316.23
316.92
317.76
318.54
319.49
320.64
319.85
318.7
316.96
315.17
315.47
316.19
317.17
318.12
318.72
319.79
320.68
321.28
320.89
319.79
317.56
316.46
315.59
316.85
317.87
318.87
319.25
320.13
321.49
322.34
321.62
319.85
317.87
316.36
316.24
317.13
318.46
319.57
320.23
320.89
321.54
322.2
321.9
320.42
318.6
316.73
317.15
317.94
318.91
319.73
320.78
321.23
322.49
322.59
322.35
321.61
319.24
318.23
317.76
319.36
319.5
320.35
321.4
322.22
323.45
323.8
323.5
322.16
320.09
318.26
317.66
319.47
320.7
322.06
322.23
322.78
324.1
324.63
323.79
322.34
320.73
319
318.99
320.41
321.68
322.3
322.89
323.59
324.65
325.3
325.15
323.88
321.8
319.99
319.86
320.88
322.36
323.59
324.23
325.34
326.33
327.03
326.24
325.39
323.16
321.87
321.31
322.34
323.74
324.61
325.58
326.55
327.81
327.82
327.53
326.29
324.66
323.12
323.09
324.01
325.1
326.12
326.62
327.16
327.94
329.15
328.79
327.53
325.65
323.6
323.78
325.13
326.26
326.93
327.84
327.96
329.93
330.25
329.24
328.13
326.42
324.97
325.29
326.56
327.73
328.73
329.7
330.46
331.7
332.66
332.22
331.02
329.39
327.58
327.27
328.3
328.81
329.44
330.89
331.62
332.85
333.29
332.44
331.35
329.58
327.58
327.55
328.56
329.73
330.45
330.98
331.63
332.88
333.63
333.53
331.9
330.08
328.59
328.31
329.44
330.64
331.62
332.45
333.36
334.46
334.84
334.29
333.04
330.88
329.23
328.83
330.18
331.5
332.8
333.22
334.54
335.82
336.45
335.97
334.65
332.4
331.28
330.73
332.05
333.54
334.65
335.06
336.32
337.39
337.66
337.56
336.24
334.39
332.43
332.22
333.61
334.78
335.88
336.43
337.61
338.53
339.06
338.92
337.39
335.72
333.64
333.65
335.07
336.53
337.82
338.19
339.89
340.56
341.22
340.92
339.26
337.27
335.66
335.54
336.71
337.79
338.79
340.06
340.93
342.02
342.65
341.8
340.01
337.94
336.17
336.28
337.76
339.05
340.18
341.04
342.16
343.01
343.64
342.91
341.72
339.52
337.75
337.68
339.14
340.37
341.32
342.45
343.05
344.91
345.77
345.3
343.98
342.41
339.89
340.03
341.19
342.87
343.74
344.55
345.28
347
347.37
346.74
345.36
343.19
340.97
341.2
342.76
343.96
344.82
345.82
347.24
348.09
348.66
347.9
346.27
344.21
342.88
342.58
343.99
345.31
345.98
346.72
347.63
349.24
349.83
349.1
347.52
345.43
344.48
343.89
345.29
346.54
347.66
348.07
349.12
350.55
351.34
350.8
349.1
347.54
346.2
346.2
347.44
348.67
1 315.58
2 316.39
3 316.79
4 317.82
5 318.39
6 318.22
7 316.68
8 315.01
9 314.02
10 313.55
11 315.02
12 315.75
13 316.52
14 317.1
15 317.79
16 319.22
17 320.08
18 319.7
19 318.27
20 315.99
21 314.24
22 314.05
23 315.05
24 316.23
25 316.92
26 317.76
27 318.54
28 319.49
29 320.64
30 319.85
31 318.7
32 316.96
33 315.17
34 315.47
35 316.19
36 317.17
37 318.12
38 318.72
39 319.79
40 320.68
41 321.28
42 320.89
43 319.79
44 317.56
45 316.46
46 315.59
47 316.85
48 317.87
49 318.87
50 319.25
51 320.13
52 321.49
53 322.34
54 321.62
55 319.85
56 317.87
57 316.36
58 316.24
59 317.13
60 318.46
61 319.57
62 320.23
63 320.89
64 321.54
65 322.2
66 321.9
67 320.42
68 318.6
69 316.73
70 317.15
71 317.94
72 318.91
73 319.73
74 320.78
75 321.23
76 322.49
77 322.59
78 322.35
79 321.61
80 319.24
81 318.23
82 317.76
83 319.36
84 319.5
85 320.35
86 321.4
87 322.22
88 323.45
89 323.8
90 323.5
91 322.16
92 320.09
93 318.26
94 317.66
95 319.47
96 320.7
97 322.06
98 322.23
99 322.78
100 324.1
101 324.63
102 323.79
103 322.34
104 320.73
105 319
106 318.99
107 320.41
108 321.68
109 322.3
110 322.89
111 323.59
112 324.65
113 325.3
114 325.15
115 323.88
116 321.8
117 319.99
118 319.86
119 320.88
120 322.36
121 323.59
122 324.23
123 325.34
124 326.33
125 327.03
126 326.24
127 325.39
128 323.16
129 321.87
130 321.31
131 322.34
132 323.74
133 324.61
134 325.58
135 326.55
136 327.81
137 327.82
138 327.53
139 326.29
140 324.66
141 323.12
142 323.09
143 324.01
144 325.1
145 326.12
146 326.62
147 327.16
148 327.94
149 329.15
150 328.79
151 327.53
152 325.65
153 323.6
154 323.78
155 325.13
156 326.26
157 326.93
158 327.84
159 327.96
160 329.93
161 330.25
162 329.24
163 328.13
164 326.42
165 324.97
166 325.29
167 326.56
168 327.73
169 328.73
170 329.7
171 330.46
172 331.7
173 332.66
174 332.22
175 331.02
176 329.39
177 327.58
178 327.27
179 328.3
180 328.81
181 329.44
182 330.89
183 331.62
184 332.85
185 333.29
186 332.44
187 331.35
188 329.58
189 327.58
190 327.55
191 328.56
192 329.73
193 330.45
194 330.98
195 331.63
196 332.88
197 333.63
198 333.53
199 331.9
200 330.08
201 328.59
202 328.31
203 329.44
204 330.64
205 331.62
206 332.45
207 333.36
208 334.46
209 334.84
210 334.29
211 333.04
212 330.88
213 329.23
214 328.83
215 330.18
216 331.5
217 332.8
218 333.22
219 334.54
220 335.82
221 336.45
222 335.97
223 334.65
224 332.4
225 331.28
226 330.73
227 332.05
228 333.54
229 334.65
230 335.06
231 336.32
232 337.39
233 337.66
234 337.56
235 336.24
236 334.39
237 332.43
238 332.22
239 333.61
240 334.78
241 335.88
242 336.43
243 337.61
244 338.53
245 339.06
246 338.92
247 337.39
248 335.72
249 333.64
250 333.65
251 335.07
252 336.53
253 337.82
254 338.19
255 339.89
256 340.56
257 341.22
258 340.92
259 339.26
260 337.27
261 335.66
262 335.54
263 336.71
264 337.79
265 338.79
266 340.06
267 340.93
268 342.02
269 342.65
270 341.8
271 340.01
272 337.94
273 336.17
274 336.28
275 337.76
276 339.05
277 340.18
278 341.04
279 342.16
280 343.01
281 343.64
282 342.91
283 341.72
284 339.52
285 337.75
286 337.68
287 339.14
288 340.37
289 341.32
290 342.45
291 343.05
292 344.91
293 345.77
294 345.3
295 343.98
296 342.41
297 339.89
298 340.03
299 341.19
300 342.87
301 343.74
302 344.55
303 345.28
304 347
305 347.37
306 346.74
307 345.36
308 343.19
309 340.97
310 341.2
311 342.76
312 343.96
313 344.82
314 345.82
315 347.24
316 348.09
317 348.66
318 347.9
319 346.27
320 344.21
321 342.88
322 342.58
323 343.99
324 345.31
325 345.98
326 346.72
327 347.63
328 349.24
329 349.83
330 349.1
331 347.52
332 345.43
333 344.48
334 343.89
335 345.29
336 346.54
337 347.66
338 348.07
339 349.12
340 350.55
341 351.34
342 350.8
343 349.1
344 347.54
345 346.2
346 346.2
347 347.44
348 348.67

View File

@ -0,0 +1,189 @@
from pathlib import Path
from numpy.testing import assert_allclose, assert_equal
import pandas as pd
import pytest
from statsmodels.tsa.seasonal import MSTL
@pytest.fixture(scope="function")
def mstl_results():
cur_dir = Path(__file__).parent.resolve()
file_path = cur_dir / "results/mstl_test_results.csv"
return pd.read_csv(file_path)
@pytest.fixture(scope="function")
def data_pd():
cur_dir = Path(__file__).parent.resolve()
file_path = cur_dir / "results/mstl_elec_vic.csv"
return pd.read_csv(file_path, index_col=["ds"], parse_dates=["ds"])
@pytest.fixture(scope="function")
def data(data_pd):
return data_pd["y"].values
def test_return_pandas_series_when_input_pandas_and_len_periods_one(data_pd):
mod = MSTL(endog=data_pd, periods=5)
res = mod.fit()
assert isinstance(res.trend, pd.Series)
assert isinstance(res.seasonal, pd.Series)
assert isinstance(res.resid, pd.Series)
assert isinstance(res.weights, pd.Series)
def test_seasonal_is_datafame_when_input_pandas_and_multiple_periods(data_pd):
mod = MSTL(endog=data_pd, periods=(3, 5))
res = mod.fit()
assert isinstance(res.seasonal, pd.DataFrame)
@pytest.mark.parametrize(
"data, periods, windows, expected",
[
(data, 3, None, 1),
(data, (3, 6), None, 2),
(data, (3, 6, 1e6), None, 2),
],
indirect=["data"],
)
def test_number_of_seasonal_components(data, periods, windows, expected):
mod = MSTL(endog=data, periods=periods, windows=windows)
res = mod.fit()
n_seasonal_components = (
res.seasonal.shape[1] if res.seasonal.ndim > 1 else res.seasonal.ndim
)
assert n_seasonal_components == expected
@pytest.mark.parametrize(
"periods, windows",
[((3, 5), 1), (7, (3, 5))],
)
def test_raise_value_error_when_periods_and_windows_diff_lengths(
periods, windows
):
with pytest.raises(
ValueError, match="Periods and windows must have same length"
):
MSTL(endog=[1, 2, 3, 4, 5], periods=periods, windows=windows)
@pytest.mark.parametrize(
"data, lmbda",
[(data, 0.1), (data, 1), (data, -3.0), (data, "auto")],
indirect=["data"],
)
def test_fit_with_box_cox(data, lmbda):
periods = (5, 6, 7)
mod = MSTL(endog=data, periods=periods, lmbda=lmbda)
mod.fit()
def test_auto_fit_with_box_cox(data):
periods = (5, 6, 7)
mod = MSTL(endog=data, periods=periods, lmbda="auto")
mod.fit()
assert hasattr(mod, "est_lmbda")
assert isinstance(mod.est_lmbda, float)
def test_stl_kwargs_smoke(data):
stl_kwargs = {
"period": 12,
"seasonal": 15,
"trend": 17,
"low_pass": 15,
"seasonal_deg": 0,
"trend_deg": 1,
"low_pass_deg": 1,
"seasonal_jump": 2,
"trend_jump": 2,
"low_pass_jump": 3,
"robust": False,
"inner_iter": 3,
"outer_iter": 3,
}
periods = (5, 6, 7)
mod = MSTL(
endog=data, periods=periods, lmbda="auto", stl_kwargs=stl_kwargs
)
mod.fit()
@pytest.mark.matplotlib
def test_plot(data, data_pd, close_figures):
mod = MSTL(endog=data, periods=5)
res = mod.fit()
res.plot()
mod = MSTL(endog=data_pd, periods=5)
res = mod.fit()
res.plot()
def test_output_similar_to_R_implementation(data_pd, mstl_results):
mod = MSTL(
endog=data_pd,
periods=(24, 24 * 7),
stl_kwargs={
"seasonal_deg": 0,
"seasonal_jump": 1,
"trend_jump": 1,
"trend_deg": 1,
"low_pass_jump": 1,
"low_pass_deg": 1,
"inner_iter": 2,
"outer_iter": 0,
},
)
res = mod.fit()
expected_observed = mstl_results["Data"]
expected_trend = mstl_results["Trend"]
expected_seasonal = mstl_results[["Seasonal24", "Seasonal168"]]
expected_resid = mstl_results["Remainder"]
assert_allclose(res.observed, expected_observed)
assert_allclose(res.trend, expected_trend)
assert_allclose(res.seasonal, expected_seasonal)
assert_allclose(res.resid, expected_resid)
@pytest.mark.parametrize(
"data, periods_ordered, windows_ordered, periods_not_ordered, "
"windows_not_ordered",
[
(data, (12, 24, 24 * 7), (11, 15, 19), (12, 24 * 7, 24), (11, 19, 15)),
(
data,
(12, 24, 24 * 7 * 1e6),
(11, 15, 19),
(12, 24 * 7 * 1e6, 24),
(11, 19, 15),
),
(data, (12, 24, 24 * 7), None, (12, 24 * 7, 24), None),
],
indirect=["data"],
)
def test_output_invariant_to_period_order(
data,
periods_ordered,
windows_ordered,
periods_not_ordered,
windows_not_ordered,
):
mod1 = MSTL(endog=data, periods=periods_ordered, windows=windows_ordered)
res1 = mod1.fit()
mod2 = MSTL(
endog=data, periods=periods_not_ordered, windows=windows_not_ordered
)
res2 = mod2.fit()
assert_equal(res1.observed, res2.observed)
assert_equal(res1.trend, res2.trend)
assert_equal(res1.seasonal, res2.seasonal)
assert_equal(res1.resid, res2.resid)

View File

@ -0,0 +1,343 @@
from statsmodels.compat.pandas import MONTH_END
import os
import pickle
import numpy as np
from numpy.testing import assert_allclose
import pandas as pd
import pytest
from statsmodels.datasets import co2
from statsmodels.tsa.seasonal import STL, DecomposeResult
cur_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(cur_dir, "results", "stl_test_results.csv")
results = pd.read_csv(file_path)
results.columns = [c.strip() for c in results.columns]
results.scenario = results.scenario.apply(str.strip)
results = results.set_index(["scenario", "idx"])
@pytest.fixture(scope="module", params=[True, False])
def robust(request):
return request.param
def default_kwargs_base():
file_path = os.path.join(cur_dir, "results", "stl_co2.csv")
co2 = np.asarray(pd.read_csv(file_path, header=None).iloc[:, 0])
y = co2
nobs = y.shape[0]
nperiod = 12
work = np.zeros((nobs + 2 * nperiod, 7))
rw = np.ones(nobs)
trend = np.zeros(nobs)
season = np.zeros(nobs)
return dict(
y=y,
n=y.shape[0],
np=nperiod,
ns=35,
nt=19,
nl=13,
no=2,
ni=1,
nsjump=4,
ntjump=2,
nljump=2,
isdeg=1,
itdeg=1,
ildeg=1,
rw=rw,
trend=trend,
season=season,
work=work,
)
@pytest.fixture(scope="function")
def default_kwargs():
return default_kwargs_base()
@pytest.fixture(scope="function")
def default_kwargs_short():
kwargs = default_kwargs_base()
y = kwargs["y"][:-1]
nobs = y.shape[0]
work = np.zeros((nobs + 2 * kwargs["np"], 7))
rw = np.ones(nobs)
trend = np.zeros(nobs)
season = np.zeros(nobs)
kwargs.update(
dict(y=y, n=nobs, rw=rw, trend=trend, season=season, work=work)
)
return kwargs
def _to_class_kwargs(kwargs, robust=False):
endog = kwargs["y"]
np = kwargs["np"]
ns = kwargs["ns"]
nt = kwargs["nt"]
nl = kwargs["nl"]
isdeg = kwargs["isdeg"]
itdeg = kwargs["itdeg"]
ildeg = kwargs["ildeg"]
nsjump = kwargs["nsjump"]
ntjump = kwargs["ntjump"]
nljump = kwargs["nljump"]
outer_iter = kwargs["no"]
inner_iter = kwargs["ni"]
class_kwargs = dict(
endog=endog,
period=np,
seasonal=ns,
trend=nt,
low_pass=nl,
seasonal_deg=isdeg,
trend_deg=itdeg,
low_pass_deg=ildeg,
robust=robust,
seasonal_jump=nsjump,
trend_jump=ntjump,
low_pass_jump=nljump,
)
return class_kwargs, outer_iter, inner_iter
def test_baseline_class(default_kwargs):
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs)
mod = STL(**class_kwargs)
res = mod.fit(outer_iter=outer, inner_iter=inner)
expected = results.loc["baseline"].sort_index()
assert_allclose(res.trend, expected.trend)
assert_allclose(res.seasonal, expected.season)
assert_allclose(res.weights, expected.rw)
resid = class_kwargs["endog"] - expected.trend - expected.season
assert_allclose(res.resid, resid)
def test_short_class(default_kwargs_short):
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs_short)
mod = STL(**class_kwargs)
res = mod.fit(outer_iter=outer, inner_iter=inner)
expected = results.loc["short"].sort_index()
assert_allclose(res.seasonal, expected.season)
assert_allclose(res.trend, expected.trend)
assert_allclose(res.weights, expected.rw)
def test_nljump_1_class(default_kwargs):
default_kwargs["nljump"] = 1
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs)
mod = STL(**class_kwargs)
res = mod.fit(outer_iter=outer, inner_iter=inner)
expected = results.loc["nljump-1"].sort_index()
assert_allclose(res.seasonal, expected.season)
assert_allclose(res.trend, expected.trend)
assert_allclose(res.weights, expected.rw)
def test_ntjump_1_class(default_kwargs):
default_kwargs["ntjump"] = 1
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs)
mod = STL(**class_kwargs)
res = mod.fit(outer_iter=outer, inner_iter=inner)
expected = results.loc["ntjump-1"].sort_index()
assert_allclose(res.seasonal, expected.season)
assert_allclose(res.trend, expected.trend)
assert_allclose(res.weights, expected.rw)
def test_nljump_1_ntjump_1_class(default_kwargs):
default_kwargs["nljump"] = 1
default_kwargs["ntjump"] = 1
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs)
mod = STL(**class_kwargs)
res = mod.fit(outer_iter=outer, inner_iter=inner)
expected = results.loc["nljump-1-ntjump-1"].sort_index()
assert_allclose(res.seasonal, expected.season)
assert_allclose(res.trend, expected.trend)
assert_allclose(res.weights, expected.rw)
def test_parameter_checks_period(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
endog = class_kwargs["endog"]
endog2 = np.hstack((endog[:, None], endog[:, None]))
period = class_kwargs["period"]
with pytest.raises(ValueError, match="endog is required to have ndim 1"):
STL(endog=endog2, period=period)
match = "period must be a positive integer >= 2"
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=1)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=-12)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=4.0)
def test_parameter_checks_seasonal(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
endog = class_kwargs["endog"]
period = class_kwargs["period"]
match = "seasonal must be an odd positive integer >= 3"
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, seasonal=2)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, seasonal=-7)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, seasonal=13.0)
def test_parameter_checks_trend(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
endog = class_kwargs["endog"]
period = class_kwargs["period"]
match = "trend must be an odd positive integer >= 3 where trend > period"
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, trend=14)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, trend=11)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, trend=-19)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, trend=19.0)
def test_parameter_checks_low_pass(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
endog = class_kwargs["endog"]
period = class_kwargs["period"]
match = (
"low_pass must be an odd positive integer >= 3 where"
" low_pass > period"
)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, low_pass=14)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, low_pass=7)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, low_pass=-19)
with pytest.raises(ValueError, match=match):
STL(endog=endog, period=period, low_pass=19.0)
def test_jump_errors(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
endog = class_kwargs["endog"]
period = class_kwargs["period"]
with pytest.raises(ValueError, match="low_pass_jump must be a positive"):
STL(endog=endog, period=period, low_pass_jump=0)
with pytest.raises(ValueError, match="low_pass_jump must be a positive"):
STL(endog=endog, period=period, low_pass_jump=1.0)
with pytest.raises(ValueError, match="seasonal_jump must be a positive"):
STL(endog=endog, period=period, seasonal_jump=0)
with pytest.raises(ValueError, match="seasonal_jump must be a positive"):
STL(endog=endog, period=period, seasonal_jump=1.0)
with pytest.raises(ValueError, match="trend_jump must be a positive"):
STL(endog=endog, period=period, trend_jump=0)
with pytest.raises(ValueError, match="trend_jump must be a positive"):
STL(endog=endog, period=period, trend_jump=1.0)
def test_defaults_smoke(default_kwargs, robust):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs, robust)
endog = class_kwargs["endog"]
period = class_kwargs["period"]
mod = STL(endog=endog, period=period)
mod.fit()
def test_pandas(default_kwargs, robust):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs, robust)
endog = pd.Series(class_kwargs["endog"], name="y")
period = class_kwargs["period"]
mod = STL(endog=endog, period=period)
res = mod.fit()
assert isinstance(res.trend, pd.Series)
assert isinstance(res.seasonal, pd.Series)
assert isinstance(res.resid, pd.Series)
assert isinstance(res.weights, pd.Series)
def test_period_detection(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
mod = STL(**class_kwargs)
res = mod.fit()
del class_kwargs["period"]
endog = class_kwargs["endog"]
index = pd.date_range("1-1-1959", periods=348, freq=MONTH_END)
class_kwargs["endog"] = pd.Series(endog, index=index)
mod = STL(**class_kwargs)
res_implicit_period = mod.fit()
assert_allclose(res.seasonal, res_implicit_period.seasonal)
def test_no_period(default_kwargs):
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
del class_kwargs["period"]
class_kwargs["endog"] = pd.Series(class_kwargs["endog"])
with pytest.raises(ValueError, match="Unable to determine period from"):
STL(**class_kwargs)
@pytest.mark.matplotlib
def test_plot(default_kwargs, close_figures):
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs)
res = STL(**class_kwargs).fit(outer_iter=outer, inner_iter=inner)
res.plot()
class_kwargs["endog"] = pd.Series(class_kwargs["endog"], name="CO2")
res = STL(**class_kwargs).fit()
res.plot()
def test_default_trend(default_kwargs):
# GH 6686
class_kwargs, _, _ = _to_class_kwargs(default_kwargs)
class_kwargs["seasonal"] = 17
class_kwargs["trend"] = None
mod = STL(**class_kwargs)
period = class_kwargs["period"]
seasonal = class_kwargs["seasonal"]
expected = int(np.ceil(1.5 * period / (1 - 1.5 / seasonal)))
expected += 1 if expected % 2 == 0 else 0
assert mod.config["trend"] == expected
class_kwargs["seasonal"] = 7
mod = STL(**class_kwargs)
period = class_kwargs["period"]
seasonal = class_kwargs["seasonal"]
expected = int(np.ceil(1.5 * period / (1 - 1.5 / seasonal)))
expected += 1 if expected % 2 == 0 else 0
assert mod.config["trend"] == expected
def test_pickle(default_kwargs):
class_kwargs, outer, inner = _to_class_kwargs(default_kwargs)
mod = STL(**class_kwargs)
res = mod.fit()
pkl = pickle.dumps(mod)
reloaded = pickle.loads(pkl)
res2 = reloaded.fit()
assert_allclose(res.trend, res2.trend)
assert_allclose(res.seasonal, res2.seasonal)
assert mod.config == reloaded.config
def test_squezable_to_1d():
data = co2.load().data
data = data.resample(MONTH_END).mean().ffill()
res = STL(data).fit()
assert isinstance(res, DecomposeResult)