Repository: statsmodels/statsmodels

Issue:
statsmodels 0.8.0 is missing smf.WLS.fit_regularized 
I have been using statsmodels 0.6.0 and was able to train models using
```
import statsmodels.api as smf
smf.WLS.fit_regularized()
```
This allowed me to fit a weighted least squares estimation with L1/L2 regularization.
I recently upgraded to statsmodels 0.8.0 to access improved time series models, but do not see the WLS regularized module anymore. 

In statsmodels 0.8.0 we have:
```
import statsmodels.api as smf
smf.OLS.fit_regularized()
```
which is not the same thing and missing the weight parameters. How can i apply smf.WLS.fit_regularized() in statsmodels 0.8.0
statsmodels 0.8.0 is missing smf.WLS.fit_regularized 
I have been using statsmodels 0.6.0 and was able to train models using
```
import statsmodels.api as smf
smf.WLS.fit_regularized()
```
This allowed me to fit a weighted least squares estimation with L1/L2 regularization.
I recently upgraded to statsmodels 0.8.0 to access improved time series models, but do not see the WLS regularized module anymore. 

In statsmodels 0.8.0 we have:
```
import statsmodels.api as smf
smf.OLS.fit_regularized()
```
which is not the same thing and missing the weight parameters. How can i apply smf.WLS.fit_regularized() in statsmodels 0.8.0


Discussion:
This may be something that happened when we made fit_regularized more generic, I will try to look into it later today.
Dr. Shedden thank you much, we are trying to use statsmodels 0.8.0 in production and your response will help us move forward. By the way, i was in your Stats650 class, an amazing class, you are one of the smartest people i have met. 
This may be something that happened when we made fit_regularized more generic, I will try to look into it later today.
Dr. Shedden thank you much, we are trying to use statsmodels 0.8.0 in production and your response will help us move forward. By the way, i was in your Stats650 class, an amazing class, you are one of the smartest people i have met. 

Resolving patch:
diff --git a/statsmodels/regression/linear_model.py b/statsmodels/regression/linear_model.py
--- a/statsmodels/regression/linear_model.py
+++ b/statsmodels/regression/linear_model.py
@@ -33,14 +33,8 @@
 
 from __future__ import print_function
 
-from collections import namedtuple
-
 from statsmodels.compat.python import lrange, lzip, range
 
-__docformat__ = 'restructuredtext en'
-
-__all__ = ['GLS', 'WLS', 'OLS', 'GLSAR']
-
 import numpy as np
 from scipy.linalg import toeplitz
 from scipy import stats
@@ -60,6 +54,95 @@
 # need import in module instead of lazily to copy `__doc__`
 from . import _prediction as pred
 
+__docformat__ = 'restructuredtext en'
+
+__all__ = ['GLS', 'WLS', 'OLS', 'GLSAR']
+
+
+_fit_regularized_doc =\
+        r"""
+        Return a regularized fit to a linear regression model.
+
+        Parameters
+        ----------
+        method : string
+            Only the 'elastic_net' approach is currently implemented.
+        alpha : scalar or array-like
+            The penalty weight.  If a scalar, the same penalty weight
+            applies to all variables in the model.  If a vector, it
+            must have the same length as `params`, and contains a
+            penalty weight for each coefficient.
+        L1_wt: scalar
+            The fraction of the penalty given to the L1 penalty term.
+            Must be between 0 and 1 (inclusive).  If 0, the fit is a
+            ridge fit, if 1 it is a lasso fit.
+        start_params : array-like
+            Starting values for ``params``.
+        profile_scale : bool
+            If True the penalized fit is computed using the profile
+            (concentrated) log-likelihood for the Gaussian model.
+            Otherwise the fit uses the residual sum of squares.
+        refit : bool
+            If True, the model is refit using only the variables that
+            have non-zero coefficients in the regularized fit.  The
+            refitted model is not regularized.
+        distributed : bool
+            If True, the model uses distributed methods for fitting,
+            will raise an error if True and partitions is None.
+        generator : function
+            generator used to partition the model, allows for handling
+            of out of memory/parallel computing.
+        partitions : scalar
+            The number of partitions desired for the distributed
+            estimation.
+        threshold : scalar or array-like
+            The threshold below which coefficients are zeroed out,
+            only used for distributed estimation
+
+        Returns
+        -------
+        A RegularizedResults instance.
+
+        Notes
+        -----
+
+        The elastic net approach closely follows that implemented in
+        the glmnet package in R.  The penalty is a combination of L1
+        and L2 penalties.
+
+        The function that is minimized is:
+
+        .. math::
+
+            0.5*RSS/n + alpha*((1-L1\_wt)*|params|_2^2/2 + L1\_wt*|params|_1)
+
+        where RSS is the usual regression sum of squares, n is the
+        sample size, and :math:`|*|_1` and :math:`|*|_2` are the L1 and L2
+        norms.
+
+        For WLS and GLS, the RSS is calculated using the whitened endog and
+        exog data.
+
+        Post-estimation results are based on the same data used to
+        select variables, hence may be subject to overfitting biases.
+
+        The elastic_net method uses the following keyword arguments:
+
+        maxiter : int
+            Maximum number of iterations
+        cnvrg_tol : float
+            Convergence threshold for line searches
+        zero_tol : float
+            Coefficients below this threshold are treated as zero.
+
+        References
+        ----------
+        Friedman, Hastie, Tibshirani (2008).  Regularization paths for
+        generalized linear models via coordinate descent.  Journal of
+        Statistical Software 33(1), 1-22 Feb 2010.
+        """
+
+
 def _get_sigma(sigma, nobs):
     """
     Returns sigma (matrix, nobs by nobs) for GLS and the inverse of its
@@ -139,7 +222,6 @@ def df_resid(self):
     def df_resid(self, value):
         self._df_resid = value
 
-
     def whiten(self, X):
         raise NotImplementedError("Subclasses should implement.")
 
@@ -184,13 +266,13 @@ def fit(self, method="pinv", cov_type='nonrobust', cov_kwds=None,
         to solve the least squares minimization.
         """
         if method == "pinv":
-            if ((not hasattr(self, 'pinv_wexog')) or
-                (not hasattr(self, 'normalized_cov_params')) or
-                (not hasattr(self, 'rank'))):
+            if not (hasattr(self, 'pinv_wexog') and
+                    hasattr(self, 'normalized_cov_params') and
+                    hasattr(self, 'rank')):
 
                 self.pinv_wexog, singular_values = pinv_extended(self.wexog)
-                self.normalized_cov_params = np.dot(self.pinv_wexog,
-                                        np.transpose(self.pinv_wexog))
+                self.normalized_cov_params = np.dot(
+                    self.pinv_wexog, np.transpose(self.pinv_wexog))
 
                 # Cache these singular values for use later.
                 self.wexog_singular_values = singular_values
@@ -199,10 +281,10 @@ def fit(self, method="pinv", cov_type='nonrobust', cov_kwds=None,
             beta = np.dot(self.pinv_wexog, self.wendog)
 
         elif method == "qr":
-            if ((not hasattr(self, 'exog_Q')) or
-                (not hasattr(self, 'exog_R')) or
-                (not hasattr(self, 'normalized_cov_params')) or
-                (getattr(self, 'rank', None) is None)):
+            if not (hasattr(self, 'exog_Q') and
+                    hasattr(self, 'exog_R') and
+                    hasattr(self, 'normalized_cov_params') and
+                    hasattr(self, 'rank')):
                 Q, R = np.linalg.qr(self.wexog)
                 self.exog_Q, self.exog_R = Q, R
                 self.normalized_cov_params = np.linalg.inv(np.dot(R.T, R))
@@ -223,17 +305,18 @@ def fit(self, method="pinv", cov_type='nonrobust', cov_kwds=None,
             self.df_resid = self.nobs - self.rank
 
         if isinstance(self, OLS):
-            lfit = OLSResults(self, beta,
-                       normalized_cov_params=self.normalized_cov_params,
-                       cov_type=cov_type, cov_kwds=cov_kwds, use_t=use_t)
+            lfit = OLSResults(
+                self, beta,
+                normalized_cov_params=self.normalized_cov_params,
+                cov_type=cov_type, cov_kwds=cov_kwds, use_t=use_t)
         else:
-            lfit = RegressionResults(self, beta,
-                       normalized_cov_params=self.normalized_cov_params,
-                       cov_type=cov_type, cov_kwds=cov_kwds, use_t=use_t,
-                       **kwargs)
+            lfit = RegressionResults(
+                self, beta,
+                normalized_cov_params=self.normalized_cov_params,
+                cov_type=cov_type, cov_kwds=cov_kwds, use_t=use_t,
+                **kwargs)
         return RegressionResultsWrapper(lfit)
 
-
     def predict(self, params, exog=None):
         """
         Return linear predicted values from a design matrix.
@@ -253,8 +336,8 @@ def predict(self, params, exog=None):
         -----
         If the model has not yet been fit, params is not optional.
         """
-        #JP: this doesn't look correct for GLMAR
-        #SS: it needs its own predict method
+        # JP: this doesn't look correct for GLMAR
+        # SS: it needs its own predict method
 
         if exog is None:
             exog = self.exog
@@ -371,23 +454,22 @@ class GLS(RegressionModel):
     >>> gls_results = gls_model.fit()
     >>> print(gls_results.summary())
 
-    """ % {'params' : base._model_params_doc,
-           'extra_params' : base._missing_param_doc + base._extra_param_doc}
+    """ % {'params': base._model_params_doc,
+           'extra_params': base._missing_param_doc + base._extra_param_doc}
 
     def __init__(self, endog, exog, sigma=None, missing='none', hasconst=None,
                  **kwargs):
-    #TODO: add options igls, for iterative fgls if sigma is None
-    #TODO: default if sigma is none should be two-step GLS
+        # TODO: add options igls, for iterative fgls if sigma is None
+        # TODO: default if sigma is none should be two-step GLS
         sigma, cholsigmainv = _get_sigma(sigma, len(endog))
 
         super(GLS, self).__init__(endog, exog, missing=missing,
                                   hasconst=hasconst, sigma=sigma,
                                   cholsigmainv=cholsigmainv, **kwargs)
 
-        #store attribute names for data arrays
+        # store attribute names for data arrays
         self._data_attr.extend(['sigma', 'cholsigmainv'])
 
-
     def whiten(self, X):
         """
         GLS whiten method.
@@ -416,8 +498,6 @@ def whiten(self, X):
         else:
             return np.dot(self.cholsigmainv, X)
 
-
-
     def loglike(self, params):
         """
         Returns the value of the Gaussian log-likelihood function at params.
@@ -445,14 +525,14 @@ def loglike(self, params):
         Y and Y-hat are whitened.
 
         """
-        #TODO: combine this with OLS/WLS loglike and add _det_sigma argument
+        # TODO: combine this with OLS/WLS loglike and add _det_sigma argument
         nobs2 = self.nobs / 2.0
         SSR = np.sum((self.wendog - np.dot(self.wexog, params))**2, axis=0)
         llf = -np.log(SSR) * nobs2      # concentrated likelihood
         llf -= (1+np.log(np.pi/nobs2))*nobs2  # with likelihood constant
         if np.any(self.sigma):
-        #FIXME: robust-enough check?  unneeded if _det_sigma gets defined
-            if self.sigma.ndim==2:
+            # FIXME: robust-enough check? unneeded if _det_sigma gets defined
+            if self.sigma.ndim == 2:
                 det = np.linalg.slogdet(self.sigma)
                 llf -= .5*det[1]
             else:
@@ -460,7 +540,6 @@ def loglike(self, params):
             # with error covariance matrix
         return llf
 
-
     def hessian_factor(self, params, scale=None, observed=True):
         """Weights for calculating Hessian
 
@@ -490,19 +569,44 @@ def hessian_factor(self, params, scale=None, observed=True):
         else:
             return np.diag(self.cholsigmainv)
 
+    def fit_regularized(self, method="elastic_net", alpha=0.,
+                        L1_wt=1., start_params=None, profile_scale=False,
+                        refit=False, **kwargs):
+        # Docstring attached below
+
+        # Need to adjust since RSS/n term in elastic net uses nominal
+        # n in denominator
+        if self.sigma is not None:
+            alpha = alpha * np.sum(1 / np.diag(self.sigma)) / len(self.endog)
+
+        rslt = OLS(self.wendog, self.wexog).fit_regularized(
+            method=method, alpha=alpha,
+            L1_wt=L1_wt,
+            start_params=start_params,
+            profile_scale=profile_scale,
+            refit=refit, **kwargs)
+
+        from statsmodels.base.elastic_net import (
+            RegularizedResults, RegularizedResultsWrapper)
+        rrslt = RegularizedResults(self, rslt.params)
+        return RegularizedResultsWrapper(rrslt)
+
+    fit_regularized.__doc__ = _fit_regularized_doc
+
+
 class WLS(RegressionModel):
     __doc__ = """
     A regression model with diagonal but non-identity covariance structure.
 
-    The weights are presumed to be (proportional to) the inverse of the
-    variance of the observations.  That is, if the variables are to be
-    transformed by 1/sqrt(W) you must supply weights = 1/W.
+    The weights are presumed to be (proportional to) the inverse of
+    the variance of the observations.  That is, if the variables are
+    to be transformed by 1/sqrt(W) you must supply weights = 1/W.
 
     %(params)s
     weights : array-like, optional
-        1d array of weights.  If you supply 1/W then the variables are pre-
-        multiplied by 1/sqrt(W).  If no weights are supplied the default value
-        is 1 and WLS results are the same as OLS.
+        1d array of weights.  If you supply 1/W then the variables are
+        pre- multiplied by 1/sqrt(W).  If no weights are supplied the
+        default value is 1 and WLS results are the same as OLS.
     %(extra_params)s
 
     Attributes
@@ -535,8 +639,8 @@ class WLS(RegressionModel):
     If the weights are a function of the data, then the post estimation
     statistics such as fvalue and mse_model might not be correct, as the
     package does not yet support no-constant regression.
-    """ % {'params' : base._model_params_doc,
-           'extra_params' : base._missing_param_doc + base._extra_param_doc}
+    """ % {'params': base._model_params_doc,
+           'extra_params': base._missing_param_doc + base._extra_param_doc}
 
     def __init__(self, endog, exog, weights=1., missing='none', hasconst=None,
                  **kwargs):
@@ -575,7 +679,7 @@ def whiten(self, X):
         -------
         sqrt(weights)*X
         """
-        #print(self.weights.var()))
+
         X = np.asarray(X)
         if X.ndim == 1:
             return X * np.sqrt(self.weights)
@@ -606,7 +710,7 @@ def loglike(self, params):
         where :math:`W` is a diagonal matrix
         """
         nobs2 = self.nobs / 2.0
-        SSR = np.sum((self.wendog - np.dot(self.wexog,params))**2, axis=0)
+        SSR = np.sum((self.wendog - np.dot(self.wexog, params))**2, axis=0)
         llf = -np.log(SSR) * nobs2      # concentrated likelihood
         llf -= (1+np.log(np.pi/nobs2))*nobs2  # with constant
         llf += 0.5 * np.sum(np.log(self.weights))
@@ -636,6 +740,29 @@ def hessian_factor(self, params, scale=None, observed=True):
 
         return self.weights
 
+    def fit_regularized(self, method="elastic_net", alpha=0.,
+                        L1_wt=1., start_params=None, profile_scale=False,
+                        refit=False, **kwargs):
+        # Docstring attached below
+
+        # Need to adjust since RSS/n in elastic net uses nominal n in
+        # denominator
+        alpha = alpha * np.sum(self.weights) / len(self.weights)
+
+        rslt = OLS(self.wendog, self.wexog).fit_regularized(
+            method=method, alpha=alpha,
+            L1_wt=L1_wt,
+            start_params=start_params,
+            profile_scale=profile_scale,
+            refit=refit, **kwargs)
+
+        from statsmodels.base.elastic_net import (
+            RegularizedResults, RegularizedResultsWrapper)
+        rrslt = RegularizedResults(self, rslt.params)
+        return RegularizedResultsWrapper(rrslt)
+
+    fit_regularized.__doc__ = _fit_regularized_doc
+
 
 class OLS(WLS):
     __doc__ = """
@@ -677,9 +804,10 @@ class OLS(WLS):
     Notes
     -----
     No constant is added by the model unless you are using formulas.
-    """ % {'params' : base._model_params_doc,
-           'extra_params' : base._missing_param_doc + base._extra_param_doc}
-    #TODO: change example to use datasets.  This was the point of datasets!
+    """ % {'params': base._model_params_doc,
+           'extra_params': base._missing_param_doc + base._extra_param_doc}
+
+    # TODO: change example to use datasets.  This was the point of datasets!
     def __init__(self, endog, exog=None, missing='none', hasconst=None,
                  **kwargs):
         super(OLS, self).__init__(endog, exog, missing=missing,
@@ -718,14 +846,12 @@ def loglike(self, params, scale=None):
             llf = -nobs2 * np.log(2 * np.pi * scale) - ssr / (2*scale)
         return llf
 
-
     def whiten(self, Y):
         """
         OLS model whitener does nothing: returns Y.
         """
         return Y
 
-
     def score(self, params, scale=None):
         """
         Evaluate the score function at a given point.
@@ -756,13 +882,13 @@ def score(self, params, scale=None):
         sdr = -self._wexog_x_wendog + xtxb
 
         if scale is None:
-            ssr = self._wendog_xprod - 2 * np.dot(self._wexog_x_wendog.T, params)
+            ssr = self._wendog_xprod - 2 * np.dot(self._wexog_x_wendog.T,
+                                                  params)
             ssr += np.dot(params, xtxb)
             return -self.nobs * sdr / ssr
         else:
             return -sdr / scale
 
-
     def _setup_score_hess(self):
         y = self.wendog
         if hasattr(self, 'offset'):
@@ -771,7 +897,6 @@ def _setup_score_hess(self):
         self._wexog_xprod = np.dot(self.wexog.T, self.wexog)
         self._wexog_x_wendog = np.dot(self.wexog.T, y)
 
-
     def hessian(self, params, scale=None):
         """
         Evaluate the Hessian function at a given point.
@@ -796,7 +921,8 @@ def hessian(self, params, scale=None):
         xtxb = np.dot(self._wexog_xprod, params)
 
         if scale is None:
-            ssr = self._wendog_xprod - 2 * np.dot(self._wexog_x_wendog.T, params)
+            ssr = self._wendog_xprod - 2 * np.dot(self._wexog_x_wendog.T,
+                                                  params)
             ssr += np.dot(params, xtxb)
             ssrp = -2*self._wexog_x_wendog + 2*xtxb
             hm = self._wexog_xprod / ssr - np.outer(ssrp, ssrp) / ssr**2
@@ -804,9 +930,6 @@ def hessian(self, params, scale=None):
         else:
             return -self._wexog_xprod / scale
 
-        return hess
-
-
     def hessian_factor(self, params, scale=None, observed=True):
         """Weights for calculating Hessian
 
@@ -831,89 +954,10 @@ def hessian_factor(self, params, scale=None, observed=True):
 
         return np.ones(self.exog.shape[0])
 
-
     def fit_regularized(self, method="elastic_net", alpha=0.,
                         L1_wt=1., start_params=None, profile_scale=False,
                         refit=False, **kwargs):
-        r"""
-        Return a regularized fit to a linear regression model.
-
-        Parameters
-        ----------
-        method : string
-            Only the 'elastic_net' approach is currently implemented.
-        alpha : scalar or array-like
-            The penalty weight.  If a scalar, the same penalty weight
-            applies to all variables in the model.  If a vector, it
-            must have the same length as `params`, and contains a
-            penalty weight for each coefficient.
-        L1_wt: scalar
-            The fraction of the penalty given to the L1 penalty term.
-            Must be between 0 and 1 (inclusive).  If 0, the fit is a
-            ridge fit, if 1 it is a lasso fit.
-        start_params : array-like
-            Starting values for ``params``.
-        profile_scale : bool
-            If True the penalized fit is computed using the profile
-            (concentrated) log-likelihood for the Gaussian model.
-            Otherwise the fit uses the residual sum of squares.
-        refit : bool
-            If True, the model is refit using only the variables that
-            have non-zero coefficients in the regularized fit.  The
-            refitted model is not regularized.
-        distributed : bool
-            If True, the model uses distributed methods for fitting,
-            will raise an error if True and partitions is None.
-        generator : function
-            generator used to partition the model, allows for handling
-            of out of memory/parallel computing.
-        partitions : scalar
-            The number of partitions desired for the distributed
-            estimation.
-        threshold : scalar or array-like
-            The threshold below which coefficients are zeroed out,
-            only used for distributed estimation
-
-        Returns
-        -------
-        An array of coefficients, or a RegressionResults object of the
-        same type returned by ``fit``.
-
-        Notes
-        -----
-
-        The elastic net approach closely follows that implemented in
-        the glmnet package in R.  The penalty is a combination of L1
-        and L2 penalties.
-
-        The function that is minimized is: 
-        
-        .. math::
-
-            0.5*RSS/n + alpha*((1-L1\_wt)*|params|_2^2/2 + L1\_wt*|params|_1)
-
-        where RSS is the usual regression sum of squares, n is the
-        sample size, and :math:`|*|_1` and :math:`|*|_2` are the L1 and L2
-        norms.
-
-        Post-estimation results are based on the same data used to
-        select variables, hence may be subject to overfitting biases.
-
-        The elastic_net method uses the following keyword arguments:
-
-        maxiter : int
-            Maximum number of iterations
-        cnvrg_tol : float
-            Convergence threshold for line searches
-        zero_tol : float
-            Coefficients below this threshold are treated as zero.
-
-        References
-        ----------
-        Friedman, Hastie, Tibshirani (2008).  Regularization paths for
-        generalized linear models via coordinate descent.  Journal of
-        Statistical Software 33(1), 1-22 Feb 2010.
-        """
+        # Docstring attached below
 
         from statsmodels.base.elastic_net import fit_elasticnet
 
@@ -925,8 +969,8 @@ def fit_regularized(self, method="elastic_net", alpha=0.,
             raise ValueError("method for fit_regularized must be elastic_net")
 
         # Set default parameters.
-        defaults = {"maxiter" : 50, "cnvrg_tol" : 1e-10,
-                    "zero_tol" : 1e-10}
+        defaults = {"maxiter":  50, "cnvrg_tol": 1e-10,
+                    "zero_tol": 1e-10}
         defaults.update(kwargs)
 
         # If a scale parameter is passed in, the non-profile
@@ -952,6 +996,7 @@ def fit_regularized(self, method="elastic_net", alpha=0.,
                               check_step=False,
                               **defaults)
 
+    fit_regularized.__doc__ = _fit_regularized_doc
 
     def _fit_ridge(self, alpha):
         """
@@ -1031,25 +1076,26 @@ class GLSAR(GLS):
     GLSAR is considered to be experimental.
     The linear autoregressive process of order p--AR(p)--is defined as:
     TODO
-    """ % {'params' : base._model_params_doc,
-           'extra_params' : base._missing_param_doc + base._extra_param_doc}
+    """ % {'params': base._model_params_doc,
+           'extra_params': base._missing_param_doc + base._extra_param_doc}
+
     def __init__(self, endog, exog=None, rho=1, missing='none', **kwargs):
-        #this looks strange, interpreting rho as order if it is int
+        # this looks strange, interpreting rho as order if it is int
         if isinstance(rho, np.int):
             self.order = rho
             self.rho = np.zeros(self.order, np.float64)
         else:
             self.rho = np.squeeze(np.asarray(rho))
-            if len(self.rho.shape) not in [0,1]:
+            if len(self.rho.shape) not in [0, 1]:
                 raise ValueError("AR parameters must be a scalar or a vector")
             if self.rho.shape == ():
                 self.rho.shape = (1,)
             self.order = self.rho.shape[0]
         if exog is None:
-            #JP this looks wrong, should be a regression on constant
-            #results for rho estimate now identical to yule-walker on y
-            #super(AR, self).__init__(endog, add_constant(endog))
-            super(GLSAR, self).__init__(endog, np.ones((endog.shape[0],1)),
+            # JP this looks wrong, should be a regression on constant
+            # results for rho estimate now identical to yule-walker on y
+            # super(AR, self).__init__(endog, add_constant(endog))
+            super(GLSAR, self).__init__(endog, np.ones((endog.shape[0], 1)),
                                         missing=missing, **kwargs)
         else:
             super(GLSAR, self).__init__(endog, exog, missing=missing,
@@ -1076,7 +1122,7 @@ def iterative_fit(self, maxiter=3, rtol=1e-4, **kwds):
         # TODO: update this after going through example.
         converged = False
         i = -1  # need to initialize for maxiter < 1 (skip loop)
-        history = {'params': [], 'rho':[self.rho]}
+        history = {'params': [], 'rho': [self.rho]}
         for i in range(maxiter - 1):
             if hasattr(self, 'pinv_wexog'):
                 del self.pinv_wexog
@@ -1103,7 +1149,8 @@ def iterative_fit(self, maxiter=3, rtol=1e-4, **kwds):
                 del self.pinv_wexog
             self.initialize()
 
-        # if converged then this is a duplicate fit, because we didn't update rho
+        # if converged then this is a duplicate fit, because we didn't
+        # update rho
         results = self.fit(history=history, **kwds)
         results.iter = i + 1
         # add last fit to history, not if duplicate fit
@@ -1115,7 +1162,6 @@ def iterative_fit(self, maxiter=3, rtol=1e-4, **kwds):
 
         return results
 
-
     def whiten(self, X):
         """
         Whiten a series of columns according to an AR(p)
@@ -1131,17 +1177,18 @@ def whiten(self, X):
         whitened array
 
         """
-        #TODO: notation for AR process
+        # TODO: notation for AR process
         X = np.asarray(X, np.float64)
         _X = X.copy()
 
-        #the following loops over the first axis,  works for 1d and nd
+        # the following loops over the first axis,  works for 1d and nd
         for i in range(self.order):
             _X[(i+1):] = _X[(i+1):] - self.rho[i] * X[0:-(i+1)]
         return _X[self.order:]
 
 
-def yule_walker(X, order=1, method="unbiased", df=None, inv=False, demean=True):
+def yule_walker(X, order=1, method="unbiased", df=None, inv=False,
+                demean=True):
     """
     Estimate AR(p) parameters from a sequence X using Yule-Walker equation.
 
@@ -1158,15 +1205,17 @@ def yule_walker(X, order=1, method="unbiased", df=None, inv=False, demean=True):
     order : integer, optional
         The order of the autoregressive process.  Default is 1.
     method : string, optional
-       Method can be "unbiased" or "mle" and this determines denominator in
-       estimate of autocorrelation function (ACF) at lag k. If "mle", the
-       denominator is n=X.shape[0], if "unbiased" the denominator is n-k.
-       The default is unbiased.
+       Method can be 'unbiased' or 'mle' and this determines
+       denominator in estimate of autocorrelation function (ACF) at
+       lag k. If 'mle', the denominator is n=X.shape[0], if 'unbiased'
+       the denominator is n-k.  The default is unbiased.
     df : integer, optional
-       Specifies the degrees of freedom. If `df` is supplied, then it is assumed
-       the X has `df` degrees of freedom rather than `n`.  Default is None.
+       Specifies the degrees of freedom. If `df` is supplied, then it
+       is assumed the X has `df` degrees of freedom rather than `n`.
+       Default is None.
     inv : bool
-        If inv is True the inverse of R is also returned.  Default is False.
+        If inv is True the inverse of R is also returned.  Default is
+        False.
     demean : bool
         True, the mean is subtracted from `X` before estimation.
 
@@ -1191,9 +1240,9 @@ def yule_walker(X, order=1, method="unbiased", df=None, inv=False, demean=True):
     16.808022730464351
 
     """
-    #TODO: define R better, look back at notes and technical notes on YW.
-    #First link here is useful
-    #http://www-stat.wharton.upenn.edu/~steele/Courses/956/ResourceDetails/YuleWalkerAndMore.htm
+    # TODO: define R better, look back at notes and technical notes on YW.
+    # First link here is useful
+    # http://www-stat.wharton.upenn.edu/~steele/Courses/956/ResourceDetails/YuleWalkerAndMore.htm
     method = str(method).lower()
     if method not in ["unbiased", "mle"]:
         raise ValueError("ACF estimation method must be 'unbiased' or 'MLE'")
@@ -1210,13 +1259,13 @@ def yule_walker(X, order=1, method="unbiased", df=None, inv=False, demean=True):
         raise ValueError("expecting a vector to estimate AR parameters")
     r = np.zeros(order+1, np.float64)
     r[0] = (X**2).sum() / denom(0)
-    for k in range(1,order+1):
-        r[k] = (X[0:-k]*X[k:]).sum() / denom(k)
+    for k in range(1, order+1):
+        r[k] = (X[0:-k] * X[k:]).sum() / denom(k)
     R = toeplitz(r[:-1])
 
     rho = np.linalg.solve(R, r[1:])
     sigmasq = r[0] - (r[1:]*rho).sum()
-    if inv==True:
+    if inv:
         return rho, np.sqrt(sigmasq), np.linalg.inv(R)
     else:
         return rho, np.sqrt(sigmasq)
@@ -1317,21 +1366,22 @@ class RegressionResults(base.LikelihoodModelResults):
     model
         A pointer to the model instance that called fit() or results.
     mse_model
-        Mean squared error the model. This is the explained sum of squares
-        divided by the model degrees of freedom.
+        Mean squared error the model. This is the explained sum of
+        squares divided by the model degrees of freedom.
     mse_resid
-        Mean squared error of the residuals.  The sum of squared residuals
-        divided by the residual degrees of freedom.
+        Mean squared error of the residuals.  The sum of squared
+        residuals divided by the residual degrees of freedom.
     mse_total
-        Total mean squared error.  Defined as the uncentered total sum of
-        squares divided by n the number of observations.
+        Total mean squared error.  Defined as the uncentered total sum
+        of squares divided by n the number of observations.
     nobs
         Number of observations n.
     normalized_cov_params
         See specific model class docstring
     params
-        The linear coefficients that minimize the least squares criterion.  This
-        is usually called Beta for the classical linear model.
+        The linear coefficients that minimize the least squares
+        criterion.  This is usually called Beta for the classical
+        linear model.
     pvalues
         The two-tailed p values for the t-stats of the params.
     resid
@@ -1339,33 +1389,35 @@ class RegressionResults(base.LikelihoodModelResults):
     resid_pearson
         `wresid` normalized to have unit variance.
     rsquared
-        R-squared of a model with an intercept.  This is defined here as
-        1 - `ssr`/`centered_tss` if the constant is included in the model and
-        1 - `ssr`/`uncentered_tss` if the constant is omitted.
+        R-squared of a model with an intercept.  This is defined here
+        as 1 - `ssr`/`centered_tss` if the constant is included in the
+        model and 1 - `ssr`/`uncentered_tss` if the constant is
+        omitted.
     rsquared_adj
-        Adjusted R-squared.  This is defined here as
-        1 - (`nobs`-1)/`df_resid` * (1-`rsquared`) if a constant is included
-        and 1 - `nobs`/`df_resid` * (1-`rsquared`) if no constant is included.
+        Adjusted R-squared.  This is defined here as 1 -
+        (`nobs`-1)/`df_resid` * (1-`rsquared`) if a constant is
+        included and 1 - `nobs`/`df_resid` * (1-`rsquared`) if no
+        constant is included.
     scale
-        A scale factor for the covariance matrix.
-        Default value is ssr/(n-p).  Note that the square root of `scale` is
-        often called the standard error of the regression.
+        A scale factor for the covariance matrix.  Default value is
+        ssr/(n-p).  Note that the square root of `scale` is often
+        called the standard error of the regression.
     ssr
         Sum of squared (whitened) residuals.
     uncentered_tss
         Uncentered sum of squares.  Sum of the squared values of the
         (whitened) endogenous response variable.
     wresid
-        The residuals of the transformed/whitened regressand and regressor(s)
+        The residuals of the transformed/whitened regressand and
+        regressor(s)
     """
 
-    _cache = {} # needs to be a class attribute for scale setter?
+    _cache = {}  # needs to be a class attribute for scale setter?
 
     def __init__(self, model, params, normalized_cov_params=None, scale=1.,
-                       cov_type='nonrobust', cov_kwds=None, use_t=None, **kwargs):
-        super(RegressionResults, self).__init__(model, params,
-                                                normalized_cov_params,
-                                                scale)
+                 cov_type='nonrobust', cov_kwds=None, use_t=None, **kwargs):
+        super(RegressionResults, self).__init__(
+            model, params, normalized_cov_params, scale)
 
         self._cache = resettable_cache()
         if hasattr(model, 'wexog_singular_values'):
@@ -1376,15 +1428,14 @@ def __init__(self, model, params, normalized_cov_params=None, scale=1.,
         self.df_model = model.df_model
         self.df_resid = model.df_resid
 
-
-
         if cov_type == 'nonrobust':
             self.cov_type = 'nonrobust'
-            self.cov_kwds = {'description' : 'Standard Errors assume that the ' +
-                             'covariance matrix of the errors is correctly ' +
-                             'specified.'}
+            self.cov_kwds = {
+                'description': 'Standard Errors assume that the ' +
+                'covariance matrix of the errors is correctly ' +
+                'specified.'}
             if use_t is None:
-                self.use_t = True    # TODO: class default
+                self.use_t = True  # TODO: class default
         else:
             if cov_kwds is None:
                 cov_kwds = {}
@@ -1422,7 +1473,6 @@ def conf_int(self, alpha=.05, cols=None):
         ci = super(RegressionResults, self).conf_int(alpha=alpha, cols=cols)
         return ci
 
-
     @cache_readonly
     def nobs(self):
         return float(self.model.wexog.shape[0])
@@ -1433,15 +1483,15 @@ def fittedvalues(self):
 
     @cache_readonly
     def wresid(self):
-        return self.model.wendog - self.model.predict(self.params,
-                self.model.wexog)
+        return self.model.wendog - self.model.predict(
+            self.params, self.model.wexog)
 
     @cache_readonly
     def resid(self):
-        return self.model.endog - self.model.predict(self.params,
-                self.model.exog)
+        return self.model.endog - self.model.predict(
+            self.params, self.model.exog)
 
-    #TODO: fix writable example
+    # TODO: fix writable example
     @cache_writable()
     def scale(self):
         wresid = self.wresid
@@ -1457,8 +1507,8 @@ def centered_tss(self):
         model = self.model
         weights = getattr(model, 'weights', None)
         if weights is not None:
-            return np.sum(weights*(model.endog - np.average(model.endog,
-                                                        weights=weights))**2)
+            return np.sum(weights * (
+                model.endog - np.average(model.endog, weights=weights))**2)
         else:  # this is probably broken for GLS
             centered_endog = model.wendog - model.wendog.mean()
             return np.dot(centered_endog, centered_endog)
@@ -1484,7 +1534,8 @@ def rsquared(self):
 
     @cache_readonly
     def rsquared_adj(self):
-        return 1 - np.divide(self.nobs - self.k_constant, self.df_resid) * (1 - self.rsquared)
+        return 1 - (np.divide(self.nobs - self.k_constant, self.df_resid)
+                    * (1 - self.rsquared))
 
     @cache_readonly
     def mse_model(self):
@@ -1508,8 +1559,10 @@ def fvalue(self):
             k_params = self.normalized_cov_params.shape[0]
             mat = np.eye(k_params)
             const_idx = self.model.data.const_idx
-            # TODO: What if model includes implicit constant, e.g. all dummies but no constant regressor?
-            # TODO: Restats as LM test by projecting orthogonalizing to constant?
+            # TODO: What if model includes implicit constant, e.g. all
+            #       dummies but no constant regressor?
+            # TODO: Restats as LM test by projecting orthogonalizing
+            #       to constant?
             if self.model.data.k_constant == 1:
                 # if constant is implicit, return nan see #2444
                 if const_idx is None:
@@ -1534,7 +1587,6 @@ def f_pvalue(self):
     def bse(self):
         return np.sqrt(np.diag(self.cov_params()))
 
-
     @cache_readonly
     def aic(self):
         return -2 * self.llf + 2 * (self.df_model + self.k_constant)
@@ -1552,7 +1604,8 @@ def eigenvals(self):
         if self._wexog_singular_values is not None:
             eigvals = self._wexog_singular_values ** 2
         else:
-            eigvals = np.linalg.linalg.eigvalsh(np.dot(self.model.wexog.T, self.model.wexog))
+            eigvals = np.linalg.linalg.eigvalsh(np.dot(self.model.wexog.T,
+                                                       self.model.wexog))
         return np.sort(eigvals)[::-1]
 
     @cache_readonly
@@ -1565,13 +1618,12 @@ def condition_number(self):
         eigvals = self.eigenvals
         return np.sqrt(eigvals[0]/eigvals[-1])
 
-    #TODO: make these properties reset bse
+    # TODO: make these properties reset bse
     def _HCCM(self, scale):
         H = np.dot(self.model.pinv_wexog,
-            scale[:,None]*self.model.pinv_wexog.T)
+                   scale[:, None] * self.model.pinv_wexog.T)
         return H
 
-
     @cache_readonly
     def cov_HC0(self):
         """
@@ -1582,7 +1634,6 @@ def cov_HC0(self):
         cov_HC0 = self._HCCM(self.het_scale)
         return cov_HC0
 
-
     @cache_readonly
     def cov_HC1(self):
         """
@@ -1593,7 +1644,6 @@ def cov_HC1(self):
         cov_HC1 = self._HCCM(self.het_scale)
         return cov_HC1
 
-
     @cache_readonly
     def cov_HC2(self):
         """
@@ -1608,20 +1658,17 @@ def cov_HC2(self):
         cov_HC2 = self._HCCM(self.het_scale)
         return cov_HC2
 
-
     @cache_readonly
     def cov_HC3(self):
         """
         See statsmodels.RegressionResults
         """
-        h = np.diag(chain_dot(self.model.wexog,
-                              self.normalized_cov_params,
-                              self.model.wexog.T))
-        self.het_scale=(self.wresid/(1-h))**2
+        h = np.diag(chain_dot(
+            self.model.wexog, self.normalized_cov_params, self.model.wexog.T))
+        self.het_scale = (self.wresid / (1 - h))**2
         cov_HC3 = self._HCCM(self.het_scale)
         return cov_HC3
 
-
     @cache_readonly
     def HC0_se(self):
         """
@@ -1629,7 +1676,6 @@ def HC0_se(self):
         """
         return np.sqrt(np.diag(self.cov_HC0))
 
-
     @cache_readonly
     def HC1_se(self):
         """
@@ -1637,7 +1683,6 @@ def HC1_se(self):
         """
         return np.sqrt(np.diag(self.cov_HC1))
 
-
     @cache_readonly
     def HC2_se(self):
         """
@@ -1645,7 +1690,6 @@ def HC2_se(self):
         """
         return np.sqrt(np.diag(self.cov_HC2))
 
-
     @cache_readonly
     def HC3_se(self):
         """
@@ -1653,7 +1697,6 @@ def HC3_se(self):
         """
         return np.sqrt(np.diag(self.cov_HC3))
 
-
     @cache_readonly
     def resid_pearson(self):
         """
@@ -1693,8 +1736,9 @@ def _is_nested(self, restricted):
 
         Notes
         -----
-        A most nests another model if the regressors in the smaller model are spanned
-        by the regressors in the larger model and the regressand is identical.
+        A most nests another model if the regressors in the smaller
+        model are spanned by the regressors in the larger model and
+        the regressand is identical.
         """
 
         if self.model.nobs != restricted.model.nobs:
@@ -1706,13 +1750,13 @@ def _is_nested(self, restricted):
             return False
 
         restricted_exog = restricted.model.wexog
-        full_wresid  = self.wresid
+        full_wresid = self.wresid
 
-        scores = restricted_exog * full_wresid[:,None]
+        scores = restricted_exog * full_wresid[:, None]
         score_l2 = np.sqrt(np.mean(scores.mean(0) ** 2))
-        # TODO: Could be improved, and may fail depending on scale of regressors
-        return np.allclose(score_l2,0)
-
+        # TODO: Could be improved, and may fail depending on scale of
+        # regressors
+        return np.allclose(score_l2, 0)
 
     def compare_lm_test(self, restricted, demean=True, use_lr=False):
         """Use Lagrange Multiplier test to test whether restricted model is correct
@@ -1720,16 +1764,16 @@ def compare_lm_test(self, restricted, demean=True, use_lr=False):
         Parameters
         ----------
         restricted : Result instance
-            The restricted model is assumed to be nested in the current
-            model. The result instance of the restricted model is required to
-            have two attributes, residual sum of squares, `ssr`, residual
-            degrees of freedom, `df_resid`.
+            The restricted model is assumed to be nested in the
+            current model. The result instance of the restricted model
+            is required to have two attributes, residual sum of
+            squares, `ssr`, residual degrees of freedom, `df_resid`.
 
         demean : bool
-            Flag indicating whether the demean the scores based on the residuals
-            from the restricted model.  If True, the covariance of the scores
-            are used and the LM test is identical to the large sample version
-            of the LR test.
+            Flag indicating whether the demean the scores based on the
+            residuals from the restricted model.  If True, the
+            covariance of the scores are used and the LM test is
+            identical to the large sample version of the LR test.
 
         Returns
         -------
@@ -1738,8 +1782,8 @@ def compare_lm_test(self, restricted, demean=True, use_lr=False):
         p_value : float
             p-value of the test statistic
         df_diff : int
-            degrees of freedom of the restriction, i.e. difference in df between
-            models
+            degrees of freedom of the restriction, i.e. difference in df
+            between models
 
         Notes
         -----
@@ -1753,7 +1797,7 @@ def compare_lm_test(self, restricted, demean=True, use_lr=False):
 
         wresid = restricted.wresid
         wexog = self.model.wexog
-        scores = wexog * wresid[:,None]
+        scores = wexog * wresid[:, None]
 
         n = self.nobs
         df_full = self.df_resid
@@ -1762,11 +1806,11 @@ def compare_lm_test(self, restricted, demean=True, use_lr=False):
 
         s = scores.mean(axis=0)
         if use_lr:
-            scores = wexog * self.wresid[:,None]
+            scores = wexog * self.wresid[:, None]
             demean = False
 
         if demean:
-            scores = scores - scores.mean(0)[None,:]
+            scores = scores - scores.mean(0)[None, :]
         # Form matters here.  If homoskedastics can be sigma^2 (X'X)^-1
         # If Heteroskedastic then the form below is fine
         # If HAC then need to use HAC
@@ -1775,16 +1819,15 @@ def compare_lm_test(self, restricted, demean=True, use_lr=False):
         cov_type = getattr(self, 'cov_type', 'nonrobust')
         if cov_type == 'nonrobust':
             sigma2 = np.mean(wresid**2)
-            XpX = np.dot(wexog.T,wexog) / n
+            XpX = np.dot(wexog.T, wexog) / n
             Sinv = inv(sigma2 * XpX)
         elif cov_type in ('HC0', 'HC1', 'HC2', 'HC3'):
-            Sinv = inv(np.dot(scores.T,scores) / n)
+            Sinv = inv(np.dot(scores.T, scores) / n)
         elif cov_type == 'HAC':
-            print("HAC")
             maxlags = self.cov_kwds['maxlags']
             Sinv = inv(sw.S_hac_simple(scores, maxlags) / n)
         elif cov_type == 'cluster':
-            #cluster robust standard errors
+            # cluster robust standard errors
             groups = self.cov_kwds['groups']
             # TODO: Might need demean option in S_crosssection by group?
             Sinv = inv(sw.S_crosssection(scores, groups))
@@ -1792,22 +1835,20 @@ def compare_lm_test(self, restricted, demean=True, use_lr=False):
             raise ValueError('Only nonrobust, HC, HAC and cluster are ' +
                              'currently connected')
 
-        lm_value = n * chain_dot(s,Sinv,s.T)
+        lm_value = n * chain_dot(s, Sinv, s.T)
         p_value = stats.chi2.sf(lm_value, df_diff)
         return lm_value, p_value, df_diff
 
-
-
     def compare_f_test(self, restricted):
         """use F test to test whether restricted model is correct
 
         Parameters
         ----------
         restricted : Result instance
-            The restricted model is assumed to be nested in the current
-            model. The result instance of the restricted model is required to
-            have two attributes, residual sum of squares, `ssr`, residual
-            degrees of freedom, `df_resid`.
+            The restricted model is assumed to be nested in the
+            current model. The result instance of the restricted model
+            is required to have two attributes, residual sum of
+            squares, `ssr`, residual degrees of freedom, `df_resid`.
 
         Returns
         -------
@@ -1816,24 +1857,24 @@ def compare_f_test(self, restricted):
         p_value : float
             p-value of the test statistic
         df_diff : int
-            degrees of freedom of the restriction, i.e. difference in df between
-            models
+            degrees of freedom of the restriction, i.e. difference in
+            df between models
 
         Notes
         -----
         See mailing list discussion October 17,
 
-        This test compares the residual sum of squares of the two models.
-        This is not a valid test, if there is unspecified heteroscedasticity
-        or correlation. This method will issue a warning if this is detected
-        but still return the results under the assumption of homoscedasticity
-        and no autocorrelation (sphericity).
-
+        This test compares the residual sum of squares of the two
+        models.  This is not a valid test, if there is unspecified
+        heteroscedasticity or correlation. This method will issue a
+        warning if this is detected but still return the results under
+        the assumption of homoscedasticity and no autocorrelation
+        (sphericity).
         """
 
         has_robust1 = getattr(self, 'cov_type', 'nonrobust') != 'nonrobust'
         has_robust2 = (getattr(restricted, 'cov_type', 'nonrobust') !=
-                                                                   'nonrobust')
+                       'nonrobust')
 
         if has_robust1 or has_robust2:
             warnings.warn('F test for comparison is likely invalid with ' +
@@ -1874,21 +1915,22 @@ def compare_lr_test(self, restricted, large_sample=False):
         p_value : float
             p-value of the test statistic
         df_diff : int
-            degrees of freedom of the restriction, i.e. difference in df between
-            models
+            degrees of freedom of the restriction, i.e. difference in df
+            between models
 
         Notes
         -----
 
-        The exact likelihood ratio is valid for homoskedastic data, and is
-        defined as
+        The exact likelihood ratio is valid for homoskedastic data,
+        and is defined as
 
         .. math:: D=-2\\log\\left(\\frac{\\mathcal{L}_{null}}
            {\\mathcal{L}_{alternative}}\\right)
 
-        where :math:`\\mathcal{L}` is the likelihood of the model. With :math:`D`
-        distributed as chisquare with df equal to difference in number of
-        parameters or equivalently difference in residual degrees of freedom.
+        where :math:`\\mathcal{L}` is the likelihood of the
+        model. With :math:`D` distributed as chisquare with df equal
+        to difference in number of parameters or equivalently
+        difference in residual degrees of freedom.
 
         The large sample version of the likelihood ratio is defined as
 
@@ -1898,27 +1940,33 @@ def compare_lr_test(self, restricted, large_sample=False):
 
         .. math:: s_{i} = x_{i,alternative} \\epsilon_{i,null}
 
-        is the average score of the model evaluated using the residuals from
-        null model and the regressors from the alternative model and :math:`S`
-        is the covariance of the scores, :math:`s_{i}`.  The covariance of the
-        scores is estimated using the same estimator as in the alternative model.
-
-        This test compares the loglikelihood of the two models.
-        This may not be a valid test, if there is unspecified heteroscedasticity
-        or correlation. This method will issue a warning if this is detected
-        but still return the results without taking unspecified
-        heteroscedasticity or correlation into account.
-
-        This test compares the loglikelihood of the two models.
-        This may not be a valid test, if there is unspecified heteroscedasticity
-        or correlation. This method will issue a warning if this is detected
-        but still return the results without taking unspecified
-        heteroscedasticity or correlation into account.
-
-        is the average score of the model evaluated using the residuals from
-        null model and the regressors from the alternative model and :math:`S`
-        is the covariance of the scores, :math:`s_{i}`.  The covariance of the
-        scores is estimated using the same estimator as in the alternative model.
+        is the average score of the model evaluated using the
+        residuals from null model and the regressors from the
+        alternative model and :math:`S` is the covariance of the
+        scores, :math:`s_{i}`.  The covariance of the scores is
+        estimated using the same estimator as in the alternative
+        model.
+
+        This test compares the loglikelihood of the two models.  This
+        may not be a valid test, if there is unspecified
+        heteroscedasticity or correlation. This method will issue a
+        warning if this is detected but still return the results
+        without taking unspecified heteroscedasticity or correlation
+        into account.
+
+        This test compares the loglikelihood of the two models.  This
+        may not be a valid test, if there is unspecified
+        heteroscedasticity or correlation. This method will issue a
+        warning if this is detected but still return the results
+        without taking unspecified heteroscedasticity or correlation
+        into account.
+
+        is the average score of the model evaluated using the
+        residuals from null model and the regressors from the
+        alternative model and :math:`S` is the covariance of the
+        scores, :math:`s_{i}`.  The covariance of the scores is
+        estimated using the same estimator as in the alternative
+        model.
 
         TODO: put into separate function, needs tests
         """
@@ -1929,8 +1977,8 @@ def compare_lr_test(self, restricted, large_sample=False):
             return self.compare_lm_test(restricted, use_lr=True)
 
         has_robust1 = (getattr(self, 'cov_type', 'nonrobust') != 'nonrobust')
-        has_robust2 = (getattr(restricted, 'cov_type', 'nonrobust') !=
-                                                                  'nonrobust')
+        has_robust2 = (
+            getattr(restricted, 'cov_type', 'nonrobust') != 'nonrobust')
 
         if has_robust1 or has_robust2:
             warnings.warn('Likelihood Ratio test is likely invalid with ' +
@@ -1948,7 +1996,6 @@ def compare_lr_test(self, restricted, large_sample=False):
 
         return lrstat, lr_pvalue, lrdf
 
-
     def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
         """create new results instance with robust covariance as default
 
@@ -1960,7 +2007,8 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
             If true, then the t distribution is used for inference.
             If false, then the normal distribution is used.
             If `use_t` is None, then an appropriate default is used, which is
-            `true` if the cov_type is nonrobust, and `false` in all other cases.
+            `true` if the cov_type is nonrobust, and `false` in all other
+            cases.
         kwds : depends on cov_type
             Required or optional arguments for robust covariance calculation.
             see Notes below
@@ -1968,10 +2016,10 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
         Returns
         -------
         results : results instance
-            This method creates a new results instance with the requested
-            robust covariance as the default covariance of the parameters.
-            Inferential statistics like p-values and hypothesis tests will be
-            based on this covariance matrix.
+            This method creates a new results instance with the
+            requested robust covariance as the default covariance of
+            the parameters.  Inferential statistics like p-values and
+            hypothesis tests will be based on this covariance matrix.
 
         Notes
         -----
@@ -2023,14 +2071,15 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
                   is used.
             - `df_correction` bool (optional)
                   adjustment to df_resid, see cov_type 'cluster' above
-                  #TODO: we need more options here
+                  # TODO: we need more options here
 
         - 'hac-panel' heteroscedasticity and autocorrelation robust standard
             errors in panel data.
-            The data needs to be sorted in this case, the time series for
-            each panel unit or cluster need to be stacked. The membership to
-            a timeseries of an individual or group can be either specified by
-            group indicators or by increasing time periods.
+            The data needs to be sorted in this case, the time series
+            for each panel unit or cluster need to be stacked. The
+            membership to a timeseries of an individual or group can
+            be either specified by group indicators or by increasing
+            time periods.
 
             keywords
 
@@ -2044,7 +2093,7 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
                   small sample correction.
             - `df_correction` bool (optional)
                   adjustment to df_resid, see cov_type 'cluster' above
-                  #TODO: we need more options here
+                  # TODO: we need more options here
 
         Reminder:
         `use_correction` in "hac-groupsum" and "hac-panel" is not bool,
@@ -2052,12 +2101,11 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
 
         TODO: Currently there is no check for extra or misspelled keywords,
         except in the case of cov_type `HCx`
-
         """
 
         import statsmodels.stats.sandwich_covariance as sw
 
-        #normalize names
+        # normalize names
         if cov_type == 'nw-panel':
             cov_type = 'hac-panel'
         if cov_type == 'nw-groupsum':
@@ -2070,22 +2118,23 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
         if use_self:
             res = self
         else:
-            res = self.__class__(self.model, self.params,
-                       normalized_cov_params=self.normalized_cov_params,
-                       scale=self.scale)
+            res = self.__class__(
+                self.model, self.params,
+                normalized_cov_params=self.normalized_cov_params,
+                scale=self.scale)
 
         res.cov_type = cov_type
         # use_t might already be defined by the class, and already set
         if use_t is None:
             use_t = self.use_t
-        res.cov_kwds = {'use_t':use_t}  # store for information
+        res.cov_kwds = {'use_t': use_t}  # store for information
         res.use_t = use_t
 
         adjust_df = False
         if cov_type in ['cluster', 'hac-panel', 'hac-groupsum']:
             df_correction = kwds.get('df_correction', None)
             # TODO: check also use_correction, do I need all combinations?
-            if df_correction is not False: # i.e. in [None, True]:
+            if df_correction is not False:  # i.e. in [None, True]:
                 # user didn't explicitely set it to False
                 adjust_df = True
 
@@ -2105,8 +2154,9 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
             if kwds:
                 raise ValueError('heteroscedasticity robust covarians ' +
                                  'does not use keywords')
-            res.cov_kwds['description'] = ('Standard Errors are heteroscedasticity ' +
-                                           'robust ' + '(' + cov_type + ')')
+            res.cov_kwds['description'] = (
+                'Standard Errors are heteroscedasticity ' +
+                'robust ' + '(' + cov_type + ')')
             # TODO cannot access cov without calling se first
             getattr(self, cov_type.upper() + '_se')
             res.cov_params_default = getattr(self, 'cov_' + cov_type.upper())
@@ -2117,15 +2167,17 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
             res.cov_kwds['weights_func'] = weights_func
             use_correction = kwds.get('use_correction', False)
             res.cov_kwds['use_correction'] = use_correction
-            res.cov_kwds['description'] = ('Standard Errors are heteroscedasticity ' +
-                 'and autocorrelation robust (HAC) using %d lags and %s small ' +
-                 'sample correction') % (maxlags, ['without', 'with'][use_correction])
-
-            res.cov_params_default = sw.cov_hac_simple(self, nlags=maxlags,
-                                                 weights_func=weights_func,
-                                                 use_correction=use_correction)
+            res.cov_kwds['description'] = (
+                'Standard Errors are heteroscedasticity and ' +
+                'autocorrelation robust (HAC) using %d lags and %s small ' +
+                'sample correction') % (maxlags,
+                                        ['without', 'with'][use_correction])
+
+            res.cov_params_default = sw.cov_hac_simple(
+                self, nlags=maxlags, weights_func=weights_func,
+                use_correction=use_correction)
         elif cov_type.lower() == 'cluster':
-            #cluster robust standard errors, one- or two-way
+            # cluster robust standard errors, one- or two-way
             groups = kwds['groups']
             if not hasattr(groups, 'shape'):
                 groups = np.asarray(groups).T
@@ -2141,8 +2193,8 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
                     # need to find number of groups
                     # duplicate work
                     self.n_groups = n_groups = len(np.unique(groups))
-                res.cov_params_default = sw.cov_cluster(self, groups,
-                                                 use_correction=use_correction)
+                res.cov_params_default = sw.cov_cluster(
+                    self, groups, use_correction=use_correction)
 
             elif groups.ndim == 2:
                 if hasattr(groups, 'values'):
@@ -2151,27 +2203,28 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
                 if adjust_df:
                     # need to find number of groups
                     # duplicate work
-                    n_groups0 = len(np.unique(groups[:,0]))
+                    n_groups0 = len(np.unique(groups[:, 0]))
                     n_groups1 = len(np.unique(groups[:, 1]))
                     self.n_groups = (n_groups0, n_groups1)
-                    n_groups = min(n_groups0, n_groups1) # use for adjust_df
+                    n_groups = min(n_groups0, n_groups1)  # use for adjust_df
 
                 # Note: sw.cov_cluster_2groups has 3 returns
-                res.cov_params_default = sw.cov_cluster_2groups(self, groups,
-                                             use_correction=use_correction)[0]
+                res.cov_params_default = sw.cov_cluster_2groups(
+                    self, groups, use_correction=use_correction)[0]
             else:
                 raise ValueError('only two groups are supported')
-            res.cov_kwds['description'] = ('Standard Errors are robust to' +
-                                'cluster correlation ' + '(' + cov_type + ')')
+            res.cov_kwds['description'] = (
+                'Standard Errors are robust to' +
+                'cluster correlation ' + '(' + cov_type + ')')
 
         elif cov_type.lower() == 'hac-panel':
-            #cluster robust standard errors
+            # cluster robust standard errors
             res.cov_kwds['time'] = time = kwds.get('time', None)
             res.cov_kwds['groups'] = groups = kwds.get('groups', None)
-            #TODO: nlags is currently required
-            #nlags = kwds.get('nlags', True)
-            #res.cov_kwds['nlags'] = nlags
-            #TODO: `nlags` or `maxlags`
+            # TODO: nlags is currently required
+            # nlags = kwds.get('nlags', True)
+            # res.cov_kwds['nlags'] = nlags
+            # TODO: `nlags` or `maxlags`
             res.cov_kwds['maxlags'] = maxlags = kwds['maxlags']
             use_correction = kwds.get('use_correction', 'hac')
             res.cov_kwds['use_correction'] = use_correction
@@ -2189,17 +2242,18 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
             groupidx = lzip([0] + tt, tt + [nobs_])
             self.n_groups = n_groups = len(groupidx)
             res.cov_params_default = sw.cov_nw_panel(self, maxlags, groupidx,
-                                                weights_func=weights_func,
-                                                use_correction=use_correction)
-            res.cov_kwds['description'] = ('Standard Errors are robust to' +
-                                'cluster correlation ' + '(' + cov_type + ')')
+                                                     weights_func=weights_func,
+                                                     use_correction=use_correction)
+            res.cov_kwds['description'] = (
+                'Standard Errors are robust to' +
+                'cluster correlation ' + '(' + cov_type + ')')
         elif cov_type.lower() == 'hac-groupsum':
             # Driscoll-Kraay standard errors
             res.cov_kwds['time'] = time = kwds['time']
-            #TODO: nlags is currently required
-            #nlags = kwds.get('nlags', True)
-            #res.cov_kwds['nlags'] = nlags
-            #TODO: `nlags` or `maxlags`
+            # TODO: nlags is currently required
+            # nlags = kwds.get('nlags', True)
+            # res.cov_kwds['nlags'] = nlags
+            # TODO: `nlags` or `maxlags`
             res.cov_kwds['maxlags'] = maxlags = kwds['maxlags']
             use_correction = kwds.get('use_correction', 'cluster')
             res.cov_kwds['use_correction'] = use_correction
@@ -2209,9 +2263,9 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
                 # need to find number of groups
                 tt = (np.nonzero(time[1:] < time[:-1])[0] + 1)
                 self.n_groups = n_groups = len(tt) + 1
-            res.cov_params_default = sw.cov_nw_groupsum(self, maxlags, time,
-                                            weights_func=weights_func,
-                                            use_correction=use_correction)
+            res.cov_params_default = sw.cov_nw_groupsum(
+                self, maxlags, time, weights_func=weights_func,
+                use_correction=use_correction)
             res.cov_kwds['description'] = (
                         'Driscoll and Kraay Standard Errors are robust to ' +
                         'cluster correlation ' + '(' + cov_type + ')')
@@ -2225,16 +2279,15 @@ def get_robustcov_results(self, cov_type='HC1', use_t=None, **kwds):
 
         return res
 
-
     def get_prediction(self, exog=None, transform=True, weights=None,
                        row_labels=None, **kwds):
 
-        return pred.get_prediction(self, exog=exog, transform=transform,
-                              weights=weights, row_labels=row_labels, **kwds)
+        return pred.get_prediction(
+            self, exog=exog, transform=transform, weights=weights,
+            row_labels=row_labels, **kwds)
 
     get_prediction.__doc__ = pred.get_prediction.__doc__
 
-
     def summary(self, yname=None, xname=None, title=None, alpha=.05):
         """Summarize the Regression Results
 
@@ -2263,9 +2316,9 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
 
         """
 
-        #TODO: import where we need it (for now), add as cached attributes
-        from statsmodels.stats.stattools import (jarque_bera,
-                omni_normtest, durbin_watson)
+        # TODO: import where we need it (for now), add as cached attributes
+        from statsmodels.stats.stattools import (
+            jarque_bera, omni_normtest, durbin_watson)
         jb, jbpv, skew, kurtosis = jarque_bera(self.wresid)
         omni, omnipv = omni_normtest(self.wresid)
 
@@ -2276,13 +2329,13 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
                           omni=omni, omnipv=omnipv, condno=condno,
                           mineigval=eigvals[-1])
 
-        #TODO not used yet
-        #diagn_left_header = ['Models stats']
-        #diagn_right_header = ['Residual stats']
+        # TODO not used yet
+        # diagn_left_header = ['Models stats']
+        # diagn_right_header = ['Residual stats']
 
-        #TODO: requiring list/iterable is a bit annoying
-        #need more control over formatting
-        #TODO: default don't work if it's not identically spelled
+        # TODO: requiring list/iterable is a bit annoying
+        # need more control over formatting
+        # TODO: default don't work if it's not identically spelled
 
         top_left = [('Dep. Variable:', None),
                     ('Model:', None),
@@ -2290,8 +2343,8 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
                     ('Date:', None),
                     ('Time:', None),
                     ('No. Observations:', None),
-                    ('Df Residuals:', None), #[self.df_resid]), #TODO: spelling
-                    ('Df Model:', None), #[self.df_model])
+                    ('Df Residuals:', None),  # [self.df_resid]), TODO: spelling
+                    ('Df Model:', None),  # [self.df_model])
                     ]
 
         if hasattr(self, 'cov_type'):
@@ -2299,9 +2352,9 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
 
         top_right = [('R-squared:', ["%#8.3f" % self.rsquared]),
                      ('Adj. R-squared:', ["%#8.3f" % self.rsquared_adj]),
-                     ('F-statistic:', ["%#8.4g" % self.fvalue] ),
+                     ('F-statistic:', ["%#8.4g" % self.fvalue]),
                      ('Prob (F-statistic):', ["%#6.3g" % self.f_pvalue]),
-                     ('Log-Likelihood:', None), #["%#6.4g" % self.llf]),
+                     ('Log-Likelihood:', None),  # ["%#6.4g" % self.llf]),
                      ('AIC:', ["%#8.4g" % self.aic]),
                      ('BIC:', ["%#8.4g" % self.bic])
                      ]
@@ -2312,30 +2365,31 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
                       ('Kurtosis:', ["%#6.3f" % kurtosis])
                       ]
 
-        diagn_right = [('Durbin-Watson:', ["%#8.3f" % durbin_watson(self.wresid)]),
+        diagn_right = [('Durbin-Watson:',
+                        ["%#8.3f" % durbin_watson(self.wresid)]
+                        ),
                        ('Jarque-Bera (JB):', ["%#8.3f" % jb]),
                        ('Prob(JB):', ["%#8.3g" % jbpv]),
                        ('Cond. No.', ["%#8.3g" % condno])
                        ]
 
-
         if title is None:
             title = self.model.__class__.__name__ + ' ' + "Regression Results"
 
-        #create summary table instance
+        # create summary table instance
         from statsmodels.iolib.summary import Summary
         smry = Summary()
         smry.add_table_2cols(self, gleft=top_left, gright=top_right,
-                          yname=yname, xname=xname, title=title)
+                             yname=yname, xname=xname, title=title)
         smry.add_table_params(self, yname=yname, xname=xname, alpha=alpha,
-                             use_t=self.use_t)
+                              use_t=self.use_t)
 
         smry.add_table_2cols(self, gleft=diagn_left, gright=diagn_right,
-                          yname=yname, xname=xname,
-                          title="")
+                             yname=yname, xname=xname,
+                             title="")
 
-        #add warnings/notes, added to text format only
-        etext =[]
+        # add warnings/notes, added to text format only
+        etext = []
         if hasattr(self, 'cov_type'):
             etext.append(self.cov_kwds['description'])
         if self.model.exog.shape[0] < self.model.exog.shape[1]:
@@ -2348,7 +2402,7 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
             wstr += "matrix is singular."
             wstr = wstr % eigvals[-1]
             etext.append(wstr)
-        elif condno > 1000:  #TODO: what is recommended
+        elif condno > 1000:  # TODO: what is recommended
             wstr = "The condition number is large, %6.3g. This might "
             wstr += "indicate that there are\n"
             wstr += "strong multicollinearity or other numerical "
@@ -2357,27 +2411,28 @@ def summary(self, yname=None, xname=None, title=None, alpha=.05):
             etext.append(wstr)
 
         if etext:
-            etext = ["[{0}] {1}".format(i + 1, text) for i, text in enumerate(etext)]
+            etext = ["[{0}] {1}".format(i + 1, text)
+                     for i, text in enumerate(etext)]
             etext.insert(0, "Warnings:")
             smry.add_extra_txt(etext)
 
         return smry
 
-        #top = summary_top(self, gleft=topleft, gright=diagn_left, #[],
-        #                  yname=yname, xname=xname,
-        #                  title=self.model.__class__.__name__ + ' ' +
-        #                  "Regression Results")
-        #par = summary_params(self, yname=yname, xname=xname, alpha=.05,
-        #                     use_t=False)
+        #  top = summary_top(self, gleft=topleft, gright=diagn_left, #[],
+        #                    yname=yname, xname=xname,
+        #                    title=self.model.__class__.__name__ + ' ' +
+        #                    "Regression Results")
+        #  par = summary_params(self, yname=yname, xname=xname, alpha=.05,
+        #                       use_t=False)
         #
-        #diagn = summary_top(self, gleft=diagn_left, gright=diagn_right,
-        #                  yname=yname, xname=xname,
-        #                  title="Linear Model")
+        #  diagn = summary_top(self, gleft=diagn_left, gright=diagn_right,
+        #                      yname=yname, xname=xname,
+        #                      title="Linear Model")
         #
-        #return summary_return([top, par, diagn], return_fmt=return_fmt)
+        #  return summary_return([top, par, diagn], return_fmt=return_fmt)
 
     def summary2(self, yname=None, xname=None, title=None, alpha=.05,
-            float_format="%.4f"):
+                 float_format="%.4f"):
         """Experimental summary function to summarize the regression results
 
         Parameters
@@ -2417,23 +2472,23 @@ def summary2(self, yname=None, xname=None, title=None, alpha=.05,
         dw = durbin_watson(self.wresid)
         eigvals = self.eigenvals
         condno = self.condition_number
-        eigvals = np.sort(eigvals) #in increasing order
+        eigvals = np.sort(eigvals)  # in increasing order
         diagnostic = OrderedDict([
-                     ('Omnibus:',  "%.3f" % omni),
-                     ('Prob(Omnibus):', "%.3f" % omnipv),
-                     ('Skew:', "%.3f" % skew),
-                     ('Kurtosis:', "%.3f" % kurtosis),
-                     ('Durbin-Watson:', "%.3f" % dw),
-                     ('Jarque-Bera (JB):', "%.3f" % jb),
-                     ('Prob(JB):', "%.3f" % jbpv),
-                     ('Condition No.:', "%.0f" % condno)
-                     ])
+            ('Omnibus:',  "%.3f" % omni),
+            ('Prob(Omnibus):', "%.3f" % omnipv),
+            ('Skew:', "%.3f" % skew),
+            ('Kurtosis:', "%.3f" % kurtosis),
+            ('Durbin-Watson:', "%.3f" % dw),
+            ('Jarque-Bera (JB):', "%.3f" % jb),
+            ('Prob(JB):', "%.3f" % jbpv),
+            ('Condition No.:', "%.0f" % condno)
+            ])
 
         # Summary
         from statsmodels.iolib import summary2
         smry = summary2.Summary()
         smry.add_base(results=self, alpha=alpha, float_format=float_format,
-                xname=xname, yname=yname, title=title)
+                      xname=xname, yname=yname, title=title)
         smry.add_dict(diagnostic)
 
         # Warnings
@@ -2523,8 +2578,8 @@ def outlier_test(self, method='bonf', alpha=.05):
         return outlier_test(self, method, alpha)
 
     def el_test(self, b0_vals, param_nums, return_weights=0,
-                     ret_params=0, method='nm',
-                     stochastic_exog=1, return_params=0):
+                ret_params=0, method='nm',
+                stochastic_exog=1, return_params=0):
         """
         Tests single or joint hypotheses of the regression parameters using
         Empirical Likelihood.
@@ -2582,17 +2637,18 @@ def el_test(self, b0_vals, param_nums, return_weights=0,
         >>> (27.248146353888796, 1.7894660442330235e-07)
         """
         params = np.copy(self.params)
-        opt_fun_inst = _ELRegOpts() # to store weights
+        opt_fun_inst = _ELRegOpts()  # to store weights
         if len(param_nums) == len(params):
-            llr = opt_fun_inst._opt_nuis_regress([],
-                                    param_nums=param_nums,
-                                    endog=self.model.endog,
-                                    exog=self.model.exog,
-                                    nobs=self.model.nobs,
-                                    nvar=self.model.exog.shape[1],
-                                    params=params,
-                                    b0_vals=b0_vals,
-                                    stochastic_exog=stochastic_exog)
+            llr = opt_fun_inst._opt_nuis_regress(
+                [],
+                param_nums=param_nums,
+                endog=self.model.endog,
+                exog=self.model.exog,
+                nobs=self.model.nobs,
+                nvar=self.model.exog.shape[1],
+                params=params,
+                b0_vals=b0_vals,
+                stochastic_exog=stochastic_exog)
             pval = 1 - stats.chi2.cdf(llr, len(param_nums))
             if return_weights:
                 return llr, pval, opt_fun_inst.new_weights
@@ -2603,13 +2659,13 @@ def el_test(self, b0_vals, param_nums, return_weights=0,
                 self.model.nobs, self.model.exog.shape[1], params,
                 b0_vals, stochastic_exog)
         if method == 'nm':
-            llr = optimize.fmin(opt_fun_inst._opt_nuis_regress, x0, maxfun=10000,
-                                 maxiter=10000, full_output=1, disp=0,
-                                 args=args)[1]
+            llr = optimize.fmin(opt_fun_inst._opt_nuis_regress, x0,
+                                maxfun=10000, maxiter=10000, full_output=1,
+                                disp=0, args=args)[1]
         if method == 'powell':
             llr = optimize.fmin_powell(opt_fun_inst._opt_nuis_regress, x0,
-                                 full_output=1, disp=0,
-                                 args=args)[1]
+                                       full_output=1, disp=0,
+                                       args=args)[1]
 
         pval = 1 - stats.chi2.cdf(llr, len(param_nums))
         if ret_params:
@@ -2619,8 +2675,8 @@ def el_test(self, b0_vals, param_nums, return_weights=0,
         else:
             return llr, pval
 
-    def conf_int_el(self, param_num, sig=.05, upper_bound=None, lower_bound=None,
-                    method='nm', stochastic_exog=1):
+    def conf_int_el(self, param_num, sig=.05, upper_bound=None,
+                    lower_bound=None, method='nm', stochastic_exog=1):
         """
         Computes the confidence interval for the parameter given by param_num
         using Empirical Likelihood
@@ -2690,12 +2746,12 @@ def conf_int_el(self, param_num, sig=.05, upper_bound=None, lower_bound=None,
         if lower_bound is None:
             lower_bound = self.conf_int(.01)[param_num][0]
         f = lambda b0: self.el_test(np.array([b0]), np.array([param_num]),
-                                      method=method,
-                                      stochastic_exog=stochastic_exog)[0]-r0
+                                    method=method,
+                                    stochastic_exog=stochastic_exog)[0]-r0
         lowerl = optimize.brenth(f, lower_bound,
-                             self.params[param_num])
+                                 self.params[param_num])
         upperl = optimize.brenth(f, self.params[param_num],
-                             upper_bound)
+                                 upper_bound)
         #  ^ Seems to be faster than brentq in most cases
         return (lowerl, upperl)
 
@@ -2703,17 +2759,17 @@ def conf_int_el(self, param_num, sig=.05, upper_bound=None, lower_bound=None,
 class RegressionResultsWrapper(wrap.ResultsWrapper):
 
     _attrs = {
-        'chisq' : 'columns',
-        'sresid' : 'rows',
-        'weights' : 'rows',
-        'wresid' : 'rows',
-        'bcov_unscaled' : 'cov',
-        'bcov_scaled' : 'cov',
-        'HC0_se' : 'columns',
-        'HC1_se' : 'columns',
-        'HC2_se' : 'columns',
-        'HC3_se' : 'columns',
-        'norm_resid' : 'rows',
+        'chisq': 'columns',
+        'sresid': 'rows',
+        'weights': 'rows',
+        'wresid': 'rows',
+        'bcov_unscaled': 'cov',
+        'bcov_scaled': 'cov',
+        'HC0_se': 'columns',
+        'HC1_se': 'columns',
+        'HC2_se': 'columns',
+        'HC3_se': 'columns',
+        'norm_resid': 'rows',
     }
 
     _wrap_attrs = wrap.union_dicts(base.LikelihoodResultsWrapper._attrs,
@@ -2733,8 +2789,8 @@ class RegressionResultsWrapper(wrap.ResultsWrapper):
     import statsmodels.api as sm
     data = sm.datasets.longley.load()
     data.exog = add_constant(data.exog, prepend=False)
-    ols_results = OLS(data.endog, data.exog).fit() #results
-    gls_results = GLS(data.endog, data.exog).fit() #results
+    ols_results = OLS(data.endog, data.exog).fit()  # results
+    gls_results = GLS(data.endog, data.exog).fit()  # results
     print(ols_results.summary())
     tables = ols_results.summary(returns='tables')
     csv = ols_results.summary(returns='csv')


Test patch:
diff --git a/statsmodels/regression/tests/test_regression.py b/statsmodels/regression/tests/test_regression.py
--- a/statsmodels/regression/tests/test_regression.py
+++ b/statsmodels/regression/tests/test_regression.py
@@ -996,8 +996,7 @@ def test_summary():
 
 class TestRegularizedFit(object):
 
-    # Make sure there are no issues when there are no selected
-    # variables.
+    # Make sure there are no problems when no variables are selected.
     def test_empty_model(self):
 
         np.random.seed(742)
@@ -1005,10 +1004,10 @@ def test_empty_model(self):
         endog = np.random.normal(size=n)
         exog = np.random.normal(size=(n, 3))
 
-        model = OLS(endog, exog)
-        result = model.fit_regularized(alpha=1000)
-
-        assert_equal(result.params, 0.)
+        for cls in OLS, WLS, GLS:
+            model = cls(endog, exog)
+            result = model.fit_regularized(alpha=1000)
+            assert_equal(result.params, 0.)
 
     def test_regularized(self):
 
@@ -1039,16 +1038,49 @@ def test_regularized(self):
             exog = exog - exog.mean(0)
             exog /= exog.std(0, ddof=1)
 
-            mod = OLS(endog, exog)
-            rslt = mod.fit_regularized(L1_wt=L1_wt, alpha=lam)
-            assert_almost_equal(rslt.params, params, decimal=3)
+            for cls in OLS, WLS, GLS:
+                mod = cls(endog, exog)
+                rslt = mod.fit_regularized(L1_wt=L1_wt, alpha=lam)
+                assert_almost_equal(rslt.params, params, decimal=3)
+
+                # Smoke test for summary
+                rslt.summary()
+
+                # Smoke test for profile likeihood
+                mod.fit_regularized(L1_wt=L1_wt, alpha=lam,
+                                    profile_scale=True)
+
+    def test_regularized_weights(self):
+
+        np.random.seed(1432)
+        exog1 = np.random.normal(size=(100, 3))
+        endog1 = exog1[:, 0] + exog1[:, 1] + np.random.normal(size=100)
+        exog2 = np.random.normal(size=(100, 3))
+        endog2 = exog2[:, 0] + exog2[:, 1] + np.random.normal(size=100)
+
+        exog_a = np.vstack((exog1, exog1, exog2))
+        endog_a = np.concatenate((endog1, endog1, endog2))
+
+        # Should be equivalent to exog_a, endog_a.
+        exog_b = np.vstack((exog1, exog2))
+        endog_b = np.concatenate((endog1, endog2))
+        wgts = np.ones(200)
+        wgts[0:100] = 2
+        sigma = np.diag(1/wgts)
+
+        for L1_wt in 0, 0.5, 1:
+            for alpha in 0, 1:
+                mod1 = OLS(endog_a, exog_a)
+                rslt1 = mod1.fit_regularized(L1_wt=L1_wt, alpha=alpha)
+
+                mod2 = WLS(endog_b, exog_b, weights=wgts)
+                rslt2 = mod2.fit_regularized(L1_wt=L1_wt, alpha=alpha)
 
-            # Smoke test for summary
-            rslt.summary()
+                mod3 = GLS(endog_b, exog_b, sigma=sigma)
+                rslt3 = mod3.fit_regularized(L1_wt=L1_wt, alpha=alpha)
 
-            # Smoke test for profile likeihood
-            mod.fit_regularized(L1_wt=L1_wt, alpha=lam,
-                                profile_scale=True)
+                assert_almost_equal(rslt1.params, rslt2.params, decimal=3)
+                assert_almost_equal(rslt1.params, rslt3.params, decimal=3)
 
 
 def test_formula_missing_cat():
@@ -1143,6 +1175,27 @@ def test_regularized_refit():
     assert_allclose(result1.bse, result2.bse)
 
 
+def test_regularized_predict():
+    n = 100
+    p = 5
+    np.random.seed(3132)
+    xmat = np.random.normal(size=(n, p))
+    yvec = xmat.sum(1) + np.random.normal(size=n)
+    wgt = np.random.uniform(1, 2, n)
+
+    for klass in WLS, GLS:
+        model1 = klass(yvec, xmat,  weights=wgt)
+        result1 = model1.fit_regularized(alpha=2., L1_wt=0.5, refit=True)
+
+        params = result1.params
+        fittedvalues = np.dot(xmat, params)
+        pr = model1.predict(result1.params)
+        assert_allclose(fittedvalues, pr)
+        assert_allclose(result1.fittedvalues, pr)
+
+        pr = result1.predict()
+        assert_allclose(fittedvalues, pr)
+
 def test_regularized_options():
     n = 100
     p = 5