o
    0Gf                      @   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   sx   t |}t |dkrtd|du r| j|fd|i|}t |dr.t |}||fS 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   :lib/python3.10/site-packages/statsmodels/base/transform.pytransform_boxcox   s   
)

zBoxCox.transform_boxcoxnaivec                 C   s`   |  }t|}|dkr(t|drt|}|S t|| d d| }|S td| d)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 '' not understood.)lowerr	   r
   r   Zexpr   r   )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||d |d krtd|dkr0| j|fd|i|}|S |dkrA| j|fd|i|}|S td	| d
)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 {} not understood.r   r   z Lower bound exceeds upper bound.r   boundsZloglikr   r   )r   lenr   format_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r1tj|ddd n|dkr<t|dd ntd| 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 'r   c                    s0   t  t d|  }t j|ddt | S )Nr   r+   )r	   Z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"   Zwindow_lengthZscaler2   nobsgroupsZgrouped_datar/   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   r4   r   Zsum_xr   r   r   r/      s   $z$BoxCox._loglik_boxcox.<locals>.optimr0   r1   )r	   sumr   r#   r   r   )r   r   r"   r2   r/   r6   r   r8   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    