7
7
import numpy
8
8
import pandas
9
9
import converters
10
-
10
+ import validate
11
+ import itertools
11
12
12
13
fc = importr ('forecast' )
13
14
stats = importr ('stats' )
@@ -643,13 +644,30 @@ def seasadj(decomp):
643
644
was seasonally decomposed to get decomp.
644
645
645
646
Args:
646
- decomp: an R seasonal decomposition from stl or decompose
647
+ decomp: an R seasonal decomposition from stl or decompose,
648
+ or a Pandas data frame containing a seasonal decomposition.
647
649
648
650
Returns:
649
651
an object that maps an R time series of the seasonally adjusted
650
652
values of the series that decomp was formed from
651
653
'''
652
- return fc .seasadj (decomp )
654
+ if validate .is_Pandas_decomposition (decomp ):
655
+ if decomp .trend .isnull ().any ():
656
+ # classical
657
+ seasonal_mean = decomp .seasonal .mean (axis = 0 )
658
+ if numpy .allclose (seasonal_mean , 1.0 , atol = 1e-5 ):
659
+ # multiplicative
660
+ return decomp .data / decomp .seasonal
661
+ else :
662
+ # additive
663
+ return decomp .data - decomp .seasonal
664
+ else :
665
+ # stl decomposition
666
+ return decomp .data - decomp .seasonal
667
+ elif validate .is_R_decomposition (decomp ):
668
+ return fc .seasadj (decomp )
669
+ else :
670
+ raise ValueError ('seasadj requires a seasonal decomposition as input' )
653
671
654
672
655
673
def sindexf (decomp , h ):
@@ -658,14 +676,29 @@ def sindexf(decomp, h):
658
676
forward by h time steps into the future.
659
677
660
678
Args:
661
- decomp: an R seasonal decomposition from stl or decompose
679
+ decomp: an R seasonal decomposition from stl or decompose,
680
+ or a Pandas data frame containing a seasonal decomposition.
662
681
h: a forecast horizon
663
682
664
683
Returns:
665
684
an object that maps to am R time series containing the seasonal component
666
685
of decomp, projected naively forward h steps.
667
686
'''
668
- return fc .sindexf (x , h )
687
+ if validate .is_Pandas_decomposition (decomp ):
688
+ freq = len (decomp .index .levels [1 ])
689
+ seasonal = list (decomp .seasonal [- freq :])
690
+ it = itertools .cycle (seasonal )
691
+ data = []
692
+ for k in range (h ):
693
+ data .append (it .next ())
694
+ data = [0 ] + data
695
+ start = decomp .seasonal .last_valid_index ()
696
+ series = converters .sequence_as_series (data , start = start , freq = freq )
697
+ return series [1 :]
698
+ elif validate .is_R_decomposition (decomp ):
699
+ return fc .sindexf (decomp , h )
700
+ else :
701
+ raise ValueError ('seasadj requires a seasonal decomposition as input' )
669
702
670
703
671
704
def BoxCox (x , lam ):
0 commit comments