Ejemplo n.º 1
0
def test_standardize_lag_order_int():
    # Integer input
    assert_equal(standardize_lag_order(0, title='test'), 0)
    assert_equal(standardize_lag_order(3), 3)
Ejemplo n.º 2
0
    def __init__(self,
                 endog=None,
                 exog=None,
                 order=None,
                 seasonal_order=None,
                 ar_order=None,
                 diff=None,
                 ma_order=None,
                 seasonal_ar_order=None,
                 seasonal_diff=None,
                 seasonal_ma_order=None,
                 seasonal_periods=None,
                 trend=None,
                 enforce_stationarity=None,
                 enforce_invertibility=None,
                 concentrate_scale=None,
                 trend_offset=1,
                 dates=None,
                 freq=None,
                 missing='none',
                 validate_specification=True):

        # Basic parameters
        self.enforce_stationarity = enforce_stationarity
        self.enforce_invertibility = enforce_invertibility
        self.concentrate_scale = concentrate_scale
        self.trend_offset = trend_offset

        # Validate that we were not given conflicting specifications
        has_order = order is not None
        has_specific_order = (ar_order is not None or diff is not None
                              or ma_order is not None)
        has_seasonal_order = seasonal_order is not None
        has_specific_seasonal_order = (seasonal_ar_order is not None
                                       or seasonal_diff is not None
                                       or seasonal_ma_order is not None
                                       or seasonal_periods is not None)
        if has_order and has_specific_order:
            raise ValueError('Cannot specify both `order` and either of'
                             ' `ar_order` or `ma_order`.')
        if has_seasonal_order and has_specific_seasonal_order:
            raise ValueError('Cannot specify both `seasonal_order` and any of'
                             ' `seasonal_ar_order`, `seasonal_ma_order`,'
                             ' or `seasonal_periods`.')

        # Compute `order`
        if has_specific_order:
            ar_order = 0 if ar_order is None else ar_order
            diff = 0 if diff is None else diff
            ma_order = 0 if ma_order is None else ma_order
            order = (ar_order, diff, ma_order)
        elif not has_order:
            order = (0, 0, 0)

        # Compute `seasonal_order`
        if has_specific_seasonal_order:
            seasonal_ar_order = (0 if seasonal_ar_order is None else
                                 seasonal_ar_order)
            seasonal_diff = 0 if seasonal_diff is None else seasonal_diff
            seasonal_ma_order = (0 if seasonal_ma_order is None else
                                 seasonal_ma_order)
            seasonal_periods = (0 if seasonal_periods is None else
                                seasonal_periods)
            seasonal_order = (seasonal_ar_order, seasonal_diff,
                              seasonal_ma_order, seasonal_periods)
        elif not has_seasonal_order:
            seasonal_order = (0, 0, 0, 0)

        # Validate shapes of `order`, `seasonal_order`
        if len(order) != 3:
            raise ValueError('`order` argument must be an iterable with three'
                             ' elements.')
        if len(seasonal_order) != 4:
            raise ValueError('`seasonal_order` argument must be an iterable'
                             ' with four elements.')

        # Validate differencing parameters
        if validate_specification:
            if order[1] < 0:
                raise ValueError('Cannot specify negative differencing.')
            if order[1] != int(order[1]):
                raise ValueError('Cannot specify fractional differencing.')
            if seasonal_order[1] < 0:
                raise ValueError('Cannot specify negative seasonal'
                                 ' differencing.')
            if seasonal_order[1] != int(seasonal_order[1]):
                raise ValueError('Cannot specify fractional seasonal'
                                 ' differencing.')
            if seasonal_order[3] < 0:
                raise ValueError('Cannot specify negative seasonal'
                                 ' periodicity.')

        # Standardize to integers or lists of integers
        order = (standardize_lag_order(order[0], 'AR'), int(order[1]),
                 standardize_lag_order(order[2], 'MA'))
        seasonal_order = (standardize_lag_order(seasonal_order[0],
                                                'seasonal AR'),
                          int(seasonal_order[1]),
                          standardize_lag_order(seasonal_order[2],
                                                'seasonal MA'),
                          int(seasonal_order[3]))

        # Validate seasonals
        if validate_specification:
            if seasonal_order[3] == 1:
                raise ValueError('Seasonal periodicity must be greater'
                                 ' than 1.')
            if ((seasonal_order[0] != 0 or seasonal_order[1] != 0
                 or seasonal_order[2] != 0) and seasonal_order[3] == 0):
                raise ValueError('Must include nonzero seasonal periodicity if'
                                 ' including seasonal AR, MA, or'
                                 ' differencing.')

        # Basic order
        self.order = order
        self.ar_order, self.diff, self.ma_order = order

        self.seasonal_order = seasonal_order
        (self.seasonal_ar_order, self.seasonal_diff, self.seasonal_ma_order,
         self.seasonal_periods) = seasonal_order

        # Lists of included lags
        if isinstance(self.ar_order, list):
            self.ar_lags = self.ar_order
        else:
            self.ar_lags = np.arange(1, self.ar_order + 1).tolist()
        if isinstance(self.ma_order, list):
            self.ma_lags = self.ma_order
        else:
            self.ma_lags = np.arange(1, self.ma_order + 1).tolist()

        if isinstance(self.seasonal_ar_order, list):
            self.seasonal_ar_lags = self.seasonal_ar_order
        else:
            self.seasonal_ar_lags = (np.arange(1, self.seasonal_ar_order +
                                               1).tolist())
        if isinstance(self.seasonal_ma_order, list):
            self.seasonal_ma_lags = self.seasonal_ma_order
        else:
            self.seasonal_ma_lags = (np.arange(1, self.seasonal_ma_order +
                                               1).tolist())

        # Maximum lag orders
        self.max_ar_order = self.ar_lags[-1] if self.ar_lags else 0
        self.max_ma_order = self.ma_lags[-1] if self.ma_lags else 0

        self.max_seasonal_ar_order = (self.seasonal_ar_lags[-1]
                                      if self.seasonal_ar_lags else 0)
        self.max_seasonal_ma_order = (self.seasonal_ma_lags[-1]
                                      if self.seasonal_ma_lags else 0)

        self.max_reduced_ar_order = (
            self.max_ar_order +
            self.max_seasonal_ar_order * self.seasonal_periods)
        self.max_reduced_ma_order = (
            self.max_ma_order +
            self.max_seasonal_ma_order * self.seasonal_periods)

        # Check that we don't have duplicate AR or MA lags from the seasonal
        # component
        ar_lags = set(self.ar_lags)
        seasonal_ar_lags = set(
            np.array(self.seasonal_ar_lags) * self.seasonal_periods)
        duplicate_ar_lags = ar_lags.intersection(seasonal_ar_lags)
        if validate_specification and len(duplicate_ar_lags) > 0:
            raise ValueError('Invalid model: autoregressive lag(s) %s are'
                             ' in both the seasonal and non-seasonal'
                             ' autoregressive components.' % duplicate_ar_lags)

        ma_lags = set(self.ma_lags)
        seasonal_ma_lags = set(
            np.array(self.seasonal_ma_lags) * self.seasonal_periods)
        duplicate_ma_lags = ma_lags.intersection(seasonal_ma_lags)
        if validate_specification and len(duplicate_ma_lags) > 0:
            raise ValueError('Invalid model: moving average lag(s) %s are'
                             ' in both the seasonal and non-seasonal'
                             ' moving average components.' % duplicate_ma_lags)

        # Handle trend
        self.trend = trend
        self.trend_poly, _ = prepare_trend_spec(trend)

        # Check for a constant column in the provided exog
        exog_is_pandas = _is_using_pandas(exog, None)
        if (validate_specification and exog is not None
                and len(self.trend_poly) > 0 and self.trend_poly[0] == 1):
            # Figure out if we have any constant columns
            x = np.asanyarray(exog)
            ptp0 = np.ptp(x, axis=0)
            col_is_const = ptp0 == 0
            nz_const = col_is_const & (x[0] != 0)
            col_const = nz_const

            # If we already have a constant column, raise an error
            if np.any(col_const):
                raise ValueError('A constant trend was included in the model'
                                 ' specification, but the `exog` data already'
                                 ' contains a column of constants.')

        # This contains the included exponents of the trend polynomial,
        # where e.g. the constant term has exponent 0, a linear trend has
        # exponent 1, etc.
        self.trend_terms = np.where(self.trend_poly == 1)[0]
        # Trend order is either the degree of the trend polynomial, if all
        # exponents are included, or a list of included exponents. Here we need
        # to make a distinction between a degree zero polynomial (i.e. a
        # constant) and the zero polynomial (i.e. not even a constant). The
        # former has `trend_order = 0`, while the latter has
        # `trend_order = None`.
        self.k_trend = len(self.trend_terms)
        if len(self.trend_terms) == 0:
            self.trend_order = None
            self.trend_degree = None
        elif np.all(self.trend_terms == np.arange(len(self.trend_terms))):
            self.trend_order = self.trend_terms[-1]
            self.trend_degree = self.trend_terms[-1]
        else:
            self.trend_order = self.trend_terms
            self.trend_degree = self.trend_terms[-1]

        # Handle endog / exog
        # Standardize exog
        self.k_exog, exog = prepare_exog(exog)

        # Standardize endog (including creating a faux endog if necessary)
        faux_endog = endog is None
        if endog is None:
            endog = [] if exog is None else np.zeros(len(exog)) * np.nan

        # Add trend data into exog
        nobs = len(endog) if exog is None else len(exog)
        if self.trend_order is not None:
            # Add in the data
            trend_data = self.construct_trend_data(nobs, trend_offset)
            if exog is None:
                exog = trend_data
            elif exog_is_pandas:
                trend_data = pd.DataFrame(trend_data,
                                          index=exog.index,
                                          columns=self.construct_trend_names())
                exog = pd.concat([trend_data, exog], axis=1)
            else:
                exog = np.c_[trend_data, exog]

        # Create an underlying time series model, to handle endog / exog,
        # especially validating shapes, retrieving names, and potentially
        # providing us with a time series index
        self._model = TimeSeriesModel(endog,
                                      exog=exog,
                                      dates=dates,
                                      freq=freq,
                                      missing=missing)
        self.endog = None if faux_endog else self._model.endog
        self.exog = self._model.exog

        # Validate endog shape
        if (validate_specification and not faux_endog and self.endog.ndim > 1
                and self.endog.shape[1] > 1):
            raise ValueError('SARIMAX models require univariate `endog`. Got'
                             ' shape %s.' % str(self.endog.shape))

        self._has_missing = (None if faux_endog else np.any(
            np.isnan(self.endog)))
Ejemplo n.º 3
0
def test_standardize_lag_order_ndarray_bool():
    assert_equal(standardize_lag_order(np.array([0])), 0)
    assert_equal(standardize_lag_order(np.array([1])), 1)
    assert_equal(standardize_lag_order(np.array([0, 1])), [2])
    assert_equal(standardize_lag_order(np.array([0, 1, 0, 1])), [2, 4])
Ejemplo n.º 4
0
def test_standardize_lag_order_misc():
    # Misc.
    assert_equal(standardize_lag_order(np.array([[1], [3]])), [1, 3])
Ejemplo n.º 5
0
def test_standardize_lag_order_tuple_bool():
    # Non-list iterable input, lags
    assert_equal(standardize_lag_order((0)), 0)
    assert_equal(standardize_lag_order((1)), 1)
    assert_equal(standardize_lag_order((0, 1)), [2])
    assert_equal(standardize_lag_order((0, 1, 0, 1)), [2, 4])
Ejemplo n.º 6
0
def test_standardize_lag_order_list_bool():
    # List input, booleans
    assert_equal(standardize_lag_order([0]), 0)
    assert_equal(standardize_lag_order([1]), 1)
    assert_equal(standardize_lag_order([0, 1]), [2])
    assert_equal(standardize_lag_order([0, 1, 0, 1]), [2, 4])
Ejemplo n.º 7
0
def test_standardize_lag_order_ndarray_int():
    assert_equal(standardize_lag_order(np.array([1, 2])), 2)
    assert_equal(standardize_lag_order(np.array([1, 3])), [1, 3])
Ejemplo n.º 8
0
def test_standardize_lag_order_tuple_int():
    # Non-list iterable input, lags
    assert_equal(standardize_lag_order((1, 2)), 2)
    assert_equal(standardize_lag_order((1, 3)), [1, 3])
Ejemplo n.º 9
0
def test_standardize_lag_order_list_int():
    # List input, lags
    assert_equal(standardize_lag_order([]), 0)
    assert_equal(standardize_lag_order([1, 2]), 2)
    assert_equal(standardize_lag_order([1, 3]), [1, 3])