U
    ÃmœdŠ  ã                   @   s^   d Z ddlZddlmZ ddd„ZG dd„ dƒZG d	d
„ d
eƒZG dd„ deƒZddd„Z	dS )z
Empirical CDF Functions
é    N)Úinterp1dçš™™™™™©?c                 C   sP   t | ƒ}t t d| ¡d|  ¡}t | | dd¡}t | | dd¡}||fS )aü  
    Constructs a Dvoretzky-Kiefer-Wolfowitz confidence band for the eCDF.

    Parameters
    ----------
    F : array_like
        The empirical distributions
    alpha : float
        Set alpha for a (1 - alpha) % confidence band.

    Notes
    -----
    Based on the DKW inequality.

    .. math:: P \left( \sup_x \left| F(x) - \hat(F)_n(X) \right| >
       \epsilon \right) \leq 2e^{-2n\epsilon^2}

    References
    ----------
    Wasserman, L. 2006. `All of Nonparametric Statistics`. Springer.
    g       @é   r   é   )ÚlenÚnpÚsqrtÚlogZclip)ÚFÚalphaÚnobsÚepsilonÚlowerÚupper© r   úi/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/statsmodels/distributions/empirical_distribution.pyÚ	_conf_set   s
    r   c                   @   s"   e Zd ZdZd
dd„Zdd„ Zd	S )ÚStepFunctiona>  
    A basic step function.

    Values at the ends are handled in the simplest way possible:
    everything to the left of x[0] is set to ival; everything
    to the right of x[-1] is set to y[-1].

    Parameters
    ----------
    x : array_like
    y : array_like
    ival : float
        ival is the value given to the values to the left of x[0]. Default
        is 0.
    sorted : bool
        Default is False.
    side : {'left', 'right'}, optional
        Default is 'left'. Defines the shape of the intervals constituting the
        steps. 'right' correspond to [a, b) intervals and 'left' to (a, b].

    Examples
    --------
    >>> import numpy as np
    >>> from statsmodels.distributions.empirical_distribution import (
    >>>     StepFunction)
    >>>
    >>> x = np.arange(20)
    >>> y = np.arange(20)
    >>> f = StepFunction(x, y)
    >>>
    >>> print(f(3.2))
    3.0
    >>> print(f([[3.2,4.5],[24,-3.1]]))
    [[  3.   4.]
     [ 19.   0.]]
    >>> f2 = StepFunction(x, y, side='right')
    >>>
    >>> print(f(3.0))
    2.0
    >>> print(f2(3.0))
    3.0
    ç        FÚleftc           
      C   sÎ   |  ¡ dkrd}t|ƒ‚|| _t |¡}t |¡}|j|jkrJd}t|ƒ‚t|jƒdkrdd}t|ƒ‚tjtj |f | _	tj||f | _
|s¼t | j	¡}	t | j	|	d¡| _	t | j
|	d¡| _
| j	jd | _d S )N)Úrightr   z*side can take the values 'right' or 'left'z"x and y do not have the same shaper   zx and y must be 1-dimensionalr   )r   Ú
ValueErrorÚsider   ÚasarrayÚshaper   Zr_ÚinfÚxÚyÚargsortZtakeÚn)
Úselfr   r   ZivalÚsortedr   ÚmsgÚ_xZ_yZasortr   r   r   Ú__init__Q   s&    

zStepFunction.__init__c                 C   s    t  | j|| j¡d }| j| S )Nr   )r   Zsearchsortedr   r   r   )r    ÚtimeZtindr   r   r   Ú__call__k   s    zStepFunction.__call__N)r   Fr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r$   r&   r   r   r   r   r   %   s   +
r   c                       s"   e Zd ZdZd‡ fdd„	Z‡  ZS )ÚECDFa…  
    Return the Empirical CDF of an array as a step function.

    Parameters
    ----------
    x : array_like
        Observations
    side : {'left', 'right'}, optional
        Default is 'right'. Defines the shape of the intervals constituting the
        steps. 'right' correspond to [a, b) intervals and 'left' to (a, b].

    Returns
    -------
    Empirical CDF as a step function.

    Examples
    --------
    >>> import numpy as np
    >>> from statsmodels.distributions.empirical_distribution import ECDF
    >>>
    >>> ecdf = ECDF([3, 3, 1, 4])
    >>>
    >>> ecdf([3, 55, 0.5, 1.5])
    array([ 0.75,  1.  ,  0.  ,  0.25])
    r   c                    sL   t j|dd�}| ¡  t|ƒ}t  d| d|¡}tt| ƒj|||dd� d S )NT)Úcopyg      ð?r   ©r   r!   )r   ÚarrayÚsortr   ZlinspaceÚsuperr+   r$   )r    r   r   r   r   ©Ú	__class__r   r   r$   ‹   s
    zECDF.__init__)r   ©r'   r(   r)   r*   r$   Ú__classcell__r   r   r1   r   r+   q   s   r+   c                       s"   e Zd ZdZd‡ fdd„	Z‡  ZS )ÚECDFDiscreteaZ  
    Return the Empirical Weighted CDF of an array as a step function.

    Parameters
    ----------
    x : array_like
        Data values. If freq_weights is None, then x is treated as observations
        and the ecdf is computed from the frequency counts of unique values
        using nunpy.unique.
        If freq_weights is not None, then x will be taken as the support of the
        mass point distribution with freq_weights as counts for x values.
        The x values can be arbitrary sortable values and need not be integers.
    freq_weights : array_like
        Weights of the observations.  sum(freq_weights) is interpreted as nobs
        for confint.
        If freq_weights is None, then the frequency counts for unique values
        will be computed from the data x.
    side : {'left', 'right'}, optional
        Default is 'right'. Defines the shape of the intervals constituting the
        steps. 'right' correspond to [a, b) intervals and 'left' to (a, b].

    Returns
    -------
    Weighted ECDF as a step function.

    Examples
    --------
    >>> import numpy as np
    >>> from statsmodels.distributions.empirical_distribution import (
    >>>     ECDFDiscrete)
    >>>
    >>> ewcdf = ECDFDiscrete([3, 3, 1, 4])
    >>> ewcdf([3, 55, 0.5, 1.5])
    array([0.75, 1.  , 0.  , 0.25])
    >>>
    >>> ewcdf = ECDFDiscrete([3, 1, 4], [1.25, 2.5, 5])
    >>>
    >>> ewcdf([3, 55, 0.5, 1.5])
    array([0.42857143, 1., 0. , 0.28571429])
    >>> print('e1 and e2 are equivalent ways of defining the same ECDF')
    e1 and e2 are equivalent ways of defining the same ECDF
    >>> e1 = ECDFDiscrete([3.5, 3.5, 1.5, 1, 4])
    >>> e2 = ECDFDiscrete([3.5, 1.5, 1, 4], freq_weights=[2, 1, 1, 1])
    >>> print(e1.x, e2.x)
    [-inf  1.   1.5  3.5  4. ] [-inf  1.   1.5  3.5  4. ]
    >>> print(e1.y, e2.y)
    [0.  0.2 0.4 0.8 1. ] [0.  0.2 0.4 0.8 1. ]
    Nr   c                    sœ   |d krt j|dd�\}}n
t  |¡}t|ƒt|ƒks:t‚t  |¡}t  |¡}|dksZt‚| ¡ }|| }t  || ¡}|| }tt	| ƒj
|||dd� d S )NT)Zreturn_countsr   r-   )r   Úuniquer   r   ÚAssertionErrorÚsumr   Zcumsumr0   r5   r$   )r    r   Zfreq_weightsr   ÚwÚswZaxr   r1   r   r   r$   Ê   s    


zECDFDiscrete.__init__)Nr   r3   r   r   r1   r   r5   ™   s   0r5   Tc                 K   sb   t  |¡}|r| |f|Ž}n*g }|D ]}| | |f|Ž¡ q$t  |¡}t  |¡}t|| || ƒS )zÅ
    Given a monotone function fn (no checking is done to verify monotonicity)
    and a set of x values, return an linearly interpolated approximation
    to its inverse from its values on x.
    )r   r   Úappendr.   r   r   )Úfnr   Z
vectorizedÚkeywordsr   r#   Úar   r   r   Úmonotone_fn_inverterÚ   s    


r?   )r   )T)
r*   Únumpyr   Zscipy.interpolater   r   r   r+   r5   r?   r   r   r   r   Ú<module>   s   
L(A