Skip to content

Instantly share code, notes, and snippets.

@ChadFulton
Created August 5, 2013 19:33
Show Gist options
  • Save ChadFulton/6158785 to your computer and use it in GitHub Desktop.
Save ChadFulton/6158785 to your computer and use it in GitHub Desktop.
Setar multiple inheritance
diff --git a/statsmodels/regression/linear_model.py b/statsmodels/regression/linear_model.py
index e4be23e..d7cf538 100644
--- a/statsmodels/regression/linear_model.py
+++ b/statsmodels/regression/linear_model.py
@@ -90,7 +90,7 @@ class RegressionModel(base.LikelihoodModel):
self.df_resid = self.nobs - self.rank
self.df_model = float(rank(self.exog) - self.k_constant)
- def fit(self, method="pinv", **kwargs):
+ def _fit(self, method="pinv", **kwargs):
"""
Full fit of the model.
@@ -143,6 +143,38 @@ class RegressionModel(base.LikelihoodModel):
beta = np.linalg.solve(R, effects)
# no upper triangular solve routine in numpy/scipy?
+ return beta
+
+ def fit(self, method="pinv", **kwargs):
+ """
+ Full fit of the model.
+
+ The results include an estimate of covariance matrix, (whitened)
+ residuals and an estimate of scale.
+
+ Parameters
+ ----------
+ method : str
+ Can be "pinv", "qr". "pinv" uses the Moore-Penrose pseudoinverse
+ to solve the least squares problem. "qr" uses the QR
+ factorization.
+
+ Returns
+ -------
+ A RegressionResults class instance.
+
+ See Also
+ ---------
+ regression.RegressionResults
+
+ Notes
+ -----
+ The fit method uses the pseudoinverse of the design/exogenous variables
+ to solve the least squares minimization.
+ """
class SETAR(OLS, tsbase.TimeSeriesModel):
def __init__(self, endog, order, ar_order,
delay=None, thresholds=None, trend='c',
min_regime_frac=0.1, max_delay=None, threshold_grid_size=100,
dates=None, freq=None, missing='none'):
if delay is not None and delay < 1 or delay > ar_order:
raise ValueError('Delay parameter must be greater than zero'
' and less than ar_order. Got %d.' % delay)
# Unsure of statistical properties if length of sample changes when
# estimating hyperparameters, which happens if delay can be greater
# than ar_order, so that the number of initial observations changes
if delay is None and max_delay > ar_order:
raise ValueError('Maximum delay for grid search must not be '
' greater than the autoregressive order.')
if delay is None and thresholds is not None:
raise ValueError('Thresholds cannot be specified without delay'
' parameter.')
if thresholds is not None and not len(thresholds) + 1 == order:
raise ValueError('Number of thresholds must match'
' the order of the SETAR model')
# "Immutable" properties
self.nobs_initial = ar_order
self.nobs = endog.shape[0] - ar_order
self.order = order
self.ar_order = ar_order
self.k_trend = int(trend == 'c')
self.min_regime_frac = min_regime_frac
self.min_regime_num = np.ceil(min_regime_frac * self.nobs)
self.max_delay = max_delay if max_delay is not None else ar_order
self.threshold_grid_size = threshold_grid_size
# "Flexible" properties
self.delay = delay
self.thresholds = thresholds
if self.thresholds:
self.thresholds = np.sort(self.thresholds)
# Estimation properties
self.nobs_regimes = None
self.objectives = {}
self.ar1_resids = None
# Make a copy of original datasets
orig_endog = endog
orig_exog = lagmat(orig_endog, ar_order)
# Trends
if self.k_trend:
orig_exog = add_constant(orig_exog)
# Create datasets / complete initialization
endog = orig_endog[self.nobs_initial:]
exog = orig_exog[self.nobs_initial:]
super(SETAR, self).__init__(endog, exog,
hasconst=self.k_trend, missing=missing)
# Overwrite originals
self.data.orig_endog = orig_endog
self.data.orig_exog = orig_exog
def fit(self):
"""
Fits SETAR() model using arranged autoregression.
Returns
-------
statsmodels.tsa.arima_model.SETARResults class
See also
--------
statsmodels.regression.linear_model.OLS : this estimates each regime
SETARResults : results class returned by fit
"""
if self.delay is None or self.thresholds is None:
self.delay, self.thresholds = self.select_hyperparameters()
self.endog, self.exog, self.nobs_regimes = self.build_datasets(
self.delay, self.thresholds
)
self.initialize()
beta = self._fit()
lfit = SETARResults(
self, beta, normalized_cov_params=self.normalized_cov_params
)
return lfit
class SETARResults(OLSResults, tsbase.TimeSeriesModelResults):
def __init__(self, model, params, normalized_cov_params=None, scale=1.):
super(SETARResults, self).__init__(model, params, normalized_cov_params,
scale)
diff --git a/statsmodels/tsa/base/tsa_model.py b/statsmodels/tsa/base/tsa_model.py
index 5f8c6b1..a4e964f 100644
--- a/statsmodels/tsa/base/tsa_model.py
+++ b/statsmodels/tsa/base/tsa_model.py
@@ -36,8 +36,8 @@ class TimeSeriesModel(base.LikelihoodModel):
"extra_params" : _missing_param_doc,
"extra_sections" : ""}
- def __init__(self, endog, exog=None, dates=None, freq=None, missing='none'):
- super(TimeSeriesModel, self).__init__(endog, exog, missing=missing)
+ def __init__(self, endog, exog=None, dates=None, freq=None, missing='none', **kwargs):
+ super(TimeSeriesModel, self).__init__(endog, exog, missing=missing, **kwargs)
self._init_dates(dates, freq)
def _init_dates(self, dates, freq):
@j-grana6
Copy link

j-grana6 commented Aug 5, 2013

For some reason it is not letting me comment on the Gist. However, instead of changing RegressionModel, why not just write a wrapper function around that fit. For example, you can have a _fit function as part of setar that is a wrapper around the OLS.fit(). Then you can call it withing the setar.fit().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment