U
    Kvf-                      @   s2   d dl Zd dlmZ d dlmZ G dd dZdS )    N)mad)minimize_scalarc                   @   sR   e Zd ZdZdddZdddZdd
dZddddifddZddifddZdS )BoxCoxz<
    Mixin class to allow for a Box-Cox transformation.
    Nguerreroc                 K   sr   t |}t |dkr td|dkr>| j|fd|i|}t |drVt |}nt ||d | }||fS )a  
        Performs a Box-Cox transformation on the data array x. If lmbda is None,
        the indicated method is used to estimate a suitable lambda parameter.

        Parameters
        ----------
        x : array_like
        lmbda : float
            The lambda parameter for the Box-Cox transform. If None, a value
            will be estimated by means of the specified method.
        method : {'guerrero', 'loglik'}
            The method to estimate the lambda parameter. Will only be used if
            lmbda is None, and defaults to 'guerrero', detailed in Guerrero
            (1993). 'loglik' maximizes the profile likelihood.
        **kwargs
            Options for the specified method.
            * For 'guerrero', this entails window_length, the grouping
              parameter, scale, the dispersion measure, and options, to be
              passed to the optimizer.
            * For 'loglik': options, to be passed to the optimizer.

        Returns
        -------
        y : array_like
            The transformed series.
        lmbda : float
            The lmbda parameter used to transform the series.

        References
        ----------
        Guerrero, Victor M. 1993. "Time-series analysis supported by power
        transformations". `Journal of Forecasting`. 12 (1): 37-48.

        Guerrero, Victor M. and Perera, Rafael. 2004. "Variance Stabilizing
        Power Transformation for Time Series," `Journal of Modern Applied
        Statistical Methods`. 3 (2): 357-369.

        Box, G. E. P., and D. R. Cox. 1964. "An Analysis of Transformations".
        `Journal of the Royal Statistical Society`. 26 (2): 211-252.
        r   zNon-positive x.Nmethod              ?)npasarrayany
ValueError_est_lambdaiscloselogpower)selfxlmbdar   kwargsy r   >/tmp/pip-unpacked-wheel-2v6byqio/statsmodels/base/transform.pytransform_boxcox   s    )

zBoxCox.transform_boxcoxnaivec                 C   s^   |  }t|}|dkrLt|dr2t|}qZt|| d d| }ntd||S )a  
        Back-transforms the Box-Cox transformed data array, by means of the
        indicated method. The provided argument lmbda should be the lambda
        parameter that was used to initially transform the data.

        Parameters
        ----------
        x : array_like
            The transformed series.
        lmbda : float
            The lambda parameter that was used to transform the series.
        method : {'naive'}
            Indicates the method to be used in the untransformation. Defaults
            to 'naive', which reverses the transformation.

            NOTE: 'naive' is implemented natively, while other methods may be
            available in subclasses!

        Returns
        -------
        y : array_like
            The untransformed series.
        r   r      r   Method '{0}' not understood.)lowerr	   r
   r   expr   r   format)r   r   r   r   r   r   r   r   untransform_boxcoxF   s    
zBoxCox.untransform_boxcox   c                 K   s   |  }t|dkr(tdt|n|d |d kr@td|dkr`| j|fd|i|}n.|dkr| j|fd|i|}ntd	||S )
a  
        Computes an estimate for the lambda parameter in the Box-Cox
        transformation using method.

        Parameters
        ----------
        x : array_like
            The untransformed data.
        bounds : tuple
            Numeric 2-tuple, that indicate the solution space for the lambda
            parameter. Default (-1, 2).
        method : {'guerrero', 'loglik'}
            The method by which to estimate lambda. Defaults to 'guerrero', but
            the profile likelihood ('loglik') is also available.
        **kwargs
            Options for the specified method.
            * For 'guerrero': window_length (int), the seasonality/grouping
              parameter. Scale ({'mad', 'sd'}), the dispersion measure. Options
              (dict), to be passed to the optimizer.
            * For 'loglik': Options (dict), to be passed to the optimizer.

        Returns
        -------
        lmbda : float
            The lambda parameter.
        r"   z$Bounds of length {0} not understood.r   r   z Lower bound exceeds upper bound.r   boundsZloglikr   )r   lenr   r   _guerrero_cv_loglik_boxcox)r   r   r#   r   r   r   r   r   r   r   k   s    zBoxCox._est_lambda   sdmaxiter   c                    s   t |}t|| }t||||  | ||f}t|d| }|dkrbtj|ddd n$|dkrxt|dd ntd	| fdd}	t
|	|d	|d
}
|
jS )a  
        Computes lambda using guerrero's coefficient of variation. If no
        seasonality is present in the data, window_length is set to 4 (as
        per Guerrero and Perera, (2004)).

        NOTE: Seasonality-specific auxiliaries *should* provide their own
        seasonality parameter.

        Parameters
        ----------
        x : array_like
        bounds : tuple
            Numeric 2-tuple, that indicate the solution space for the lambda
            parameter.
        window_length : int
            Seasonality/grouping parameter. Default 4, as per Guerrero and
            Perera (2004). NOTE: this indicates the length of the individual
            groups, not the total number of groups!
        scale : {'sd', 'mad'}
            The dispersion measure to be used. 'sd' indicates the sample
            standard deviation, but the more robust 'mad' is also available.
        options : dict
            The options (as a dict) to be passed to the optimizer.
        r   r(   Zddofr   )ZaxiszScale '{0}' not understood.c                    s0   t  t d|  }t j|ddt | S )Nr   r+   )r	   divider   stdmean)r   ZratZ
dispersionr.   r   r   optim   s    z"BoxCox._guerrero_cv.<locals>.optimboundedr#   r   options)r$   intr	   Zreshaper.   r   r-   r   r   r   r   r   )r   r   r#   Zwindow_lengthZscaler3   nobsgroupsZgrouped_datar0   resr   r/   r   r%      s&    zBoxCox._guerrero_cvc                    s@   t t t  fdd}t||d|d}|jS )a~  
        Taken from the Stata manual on Box-Cox regressions, where this is the
        special case of 'lhs only'. As an estimator for the variance, the
        sample variance is used, by means of the well-known formula.

        Parameters
        ----------
        x : array_like
        options : dict
            The options (as a dict) to be passed to the optimizer.
        c                    s4    | \}} d|    d tt|  S )Nr   g       @)r   r	   r   var)r   r   r5   r   Zsum_xr   r   r   r0      s    z$BoxCox._loglik_boxcox.<locals>.optimr1   r2   )r	   sumr   r$   r   r   )r   r   r#   r3   r0   r7   r   r9   r   r&      s    zBoxCox._loglik_boxcox)Nr   )r   )r    r   )	__name__
__module____qualname____doc__r   r   r   r%   r&   r   r   r   r   r      s   
;
%
,
4r   )Znumpyr	   Zstatsmodels.robustr   Zscipy.optimizer   r   r   r   r   r   <module>   s   