# -*- coding: utf-8 -*-

"""This module contains core classes for regression models."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from sklearn import linear_model as lm
from sklearn import preprocessing
from sklearn import decomposition as dcomp
import numpy as np
import pandas as pd
from sklearn import linear_model as lm

supported_linear_models = (lm.LinearRegression, lm.Lasso, lm.Ridge,
                           lm.ElasticNet)


class PCR(object):
    """Principle components regression models.

    This model solves a regression model after standard scaling the X
    data and performing PCA to reduce the dimensionality of X. This class
    simply creates a pipeline that utilizes:

    1. sklearn.preprocessing.StandardScaler
    2. sklearn.decomposition.PCA
    3. a supported sklearn.linear_model

    Attributes of the class mimic what is provided by scikit-learn's PCA and
    linear model classes. Additional attributes specifically relevant to PCR
    are also provided, such as :func:`.PCR.get_beta_params`.

    Parameters
    ----------
    n_components : int, float, None, str
        Number of components to keep when performing PCA. If n_components
        is not set all components are kept::

            n_components == min(n_samples, n_features)

        If n_components == 'mle', Minka\'s MLE is used to guess the
        dimension. If ``0 < n_components < 1``, selects the number of
        components such that the amount of variance that needs to be
        explained is greater than the percentage specified by n_components.
    regression_type : str
        The type of regression classifier to use. Must be one of 'ols',
        'lasso', 'ridge', or 'elasticnet'.

    n_jobs : int (optional)
        The number of jobs to use for the computation. If ``n_jobs=-1``, all
        CPUs are used. This will only increase speed of computation for
        n_targets > 1 and sufficiently large problems.
    alpha : float (optional)
        Used when regression_type is 'lasso', 'ridge', or 'elasticnet'.
        Represents the constant that multiplies the penalty terms. Setting
        ``alpha=0`` is equivalent to ordinary least square and it is advised
        in that case to instead use ``regression_type='ols'``. See the
        scikit-learn documentation for the chosen regression model for more
        information in this parameter.
    l1_ratio : float (optional)
        Used when regression_type is 'elasticnet'. The ElasticNet mixing
        parameter, with ``0 <= l1_ratio <= 1``. For ``l1_ratio = 0`` the
        penalty is an L2 penalty. ``For l1_ratio = 1`` it is an L1 penalty.
        For ``0 < l1_ratio < 1``, the penalty is a combination of L1 and L2.

    Attributes
    ----------
    scaler : sklearn.preprocessing.StandardScaler
        The StandardScaler object used to scale the X data.
    prcomp : sklearn.decomposition.PCA
        The PCA object use to perform PCA.
    regression : sklearn.linear_model
        The linear model object used to perform regression.
    """

    def __init__(self, n_components=None, regression_type='ols',
                 alpha=1.0, l1_ratio=0.5, n_jobs=1):
        # Store class parameters
        self.n_components = n_components
        self.n_jobs = n_jobs
        # Create scaler and PCA models
        self.scaler = preprocessing.StandardScaler()
        self.prcomp = dcomp.PCA()
        # Create regression classifier
        regression_class = {'ols': lm.LinearRegression, 'lasso': lm.Lasso,
                            'ridge': lm.Ridge, 'elasticnet': lm.ElasticNet}
        self.regression = regression_class[regression_type]()

    @property
    def beta_coef_(self):
        """
        Returns
        -------
        numpy.ndarray
            Beta coefficients, corresponding to coefficients in the original
            space and dimension of X. These are calculated as
            :math:`B = A \cdot P`, where :math:`A` is a vector of the
            coefficients obtained from regression on the principle components
            and :math:`P` is the matrix of loadings from PCA.
        """
        pass

    def fit(self):
        pass

    def predict(self):
        pass

    def score(self):
        pass


class LinearRegression(lm.LinearRegression):

    def __init__(self, fit_intercept=True, normalize=False, copy_X=True,
                 n_jobs=1):
        self.fit_intercept = fit_intercept
        self.normalize = normalize
        self.copy_X = copy_X
        self.n_jobs = n_jobs
        self.xlabels = None

    def fit(self, *args, **kwargs):
        """Hijacks :py:class:`skleanr.linear_model.LinearRegression` to accept
        an extra parameter _xlabels_.

        Parameters
        ----------
        xlabels : list, tuple, numpy.ndarray
            Optional labels for the coefficients, corresponding to columns of X.
        """
        # Try to get xlabels from *args or **kwargs
        xlabels = kwargs.get('xlabels')  # Get xlabels or None if not in kwargs
        if xlabels is None:
            try:
                xlabels = args[2]
                args = list(args)
                args.pop()  # Remove xlabels from args
            except IndexError:
                # No xlabels in args, either
                pass
        else:
            del kwargs['xlabels']  # Remove xlabels from kwargs
        # Get X matrix
        try:
            X = kwargs['X']
        except KeyError:
            X = args[0]
        # Make xlabels if none were passed
        ncols = X.shape[1]
        if xlabels is None:
            xlabels = np.array(
                ['x{0}'.format(i) for i in range(ncols)], dtype='str')
        elif isinstance(xlabels, (tuple, list)):
            xlabels = np.array(xlabels, dtype='str')
        # Make sure dims of xlabels matches dims of X
        if xlabels.shape[0] != ncols:
            raise AssertionError(
                "Dimension of xlabels {0} does not match "
                "X {1}.".format(xlabels.shape, X.shape))
        self.xlabels = xlabels
        # Call parent .fit() method
        super(LinearRegression, self).fit(*args, **kwargs)

    def summary(self):
        """Return summary results of fitted model."""
        coeffs = np.concatenate((np.array([self.intercept_]), self.coef_))
        labels = np.concatenate((np.array(['_intercept']), self.xlabels))
        summary = {'coef': pd.Series(coeffs, index=labels)}
        df = pd.DataFrame(summary)
        return df

@@ -4324,2245 +4324,132 @@
 s%0A%0A%0A
-class LinearRegression(lm.LinearRegression):%0A%0A    def __init__(self, fit_intercept=True, normalize=False, copy_X=True,%0A                 n_jobs=1):%0A        self.fit_intercept = fit_intercept%0A        self.normalize = normalize%0A        self.copy_X = copy_X%0A        self.n_jobs = n_jobs%0A        self.xlabels = None%0A%0A    def fit(self, *args, **kwargs):%0A        %22%22%22Hijacks :py:class:%60skleanr.linear_model.LinearRegression%60 to accept%0A        an extra parameter _xlabels_.%0A%0A        Parameters%0A        ----------%0A        xlabels : list, tuple, numpy.ndarray%0A            Optional labels for the coefficients, corresponding to columns of X.%0A        %22%22%22%0A        # Try to get xlabels from *args or **kwargs%0A        xlabels = kwargs.get('xlabels')  # Get xlabels or None if not in kwargs%0A        if xlabels is None:%0A            try:%0A                xlabels = args%5B2%5D%0A                args = list(args)%0A                args.pop()  # Remove xlabels from args%0A            except IndexError:%0A                # No xlabels in args, either%0A                pass%0A        else:%0A            del kwargs%5B'xlabels'%5D  # Remove xlabels from kwargs%0A        # Get X matrix%0A        try:%0A            X = kwargs%5B'X'%5D%0A        except KeyError:%0A            X = args%5B0%5D%0A        # Make xlabels if none were passed%0A        ncols = X.shape%5B1%5D%0A        if xlabels is None:%0A            xlabels = np.array(%0A                %5B'x%7B0%7D'.format(i) for i in range(ncols)%5D, dtype='str')%0A        elif isinstance(xlabels, (tuple, list)):%0A            xlabels = np.array(xlabels, dtype='str')%0A   
+def summary(clf, X_train, y_train):%0A    sse = stats.sse(clf, X_train, y_train)%0A%0A
     
- 
 # 
-Make sure dims of xlabels matches dims of X%0A        if xlabels.shape%5B0%5D != ncols:%0A            raise AssertionError(%0A                %22Dimension of xlabels %7B0%7D does not match %22%0A                %22X %7B1%7D.%22.format(xlabels.shape, X.shape))%0A        self.xlabels = xlabels%0A        # Call parent .fit() method%0A        super(LinearRegression, self).fit(*args, **kwargs)%0A%0A    def summary(self):%0A        %22%22%22Return summary results of fitted model.%22%22%22%0A        coeffs = np.concatenate((np.array(%5Bself.intercept_%5D), self.coef_))%0A        labels = np.concatenate((np.array(%5B'_intercept'%5D), self.xlabels))%0A        summary = %7B'coef': pd.Series(coeffs, index=labels)%7D%0A        df = pd.DataFrame(summary)%0A        return df
+Put into pandas data frame%0A    return sse
 %0A

Remove old an unnecessary hijack of scikit-learn class