3
hoT                 @   s   d dl Z d dlmZmZ d dlmZ d dlmZ d dlm	Z	m
Z
mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ d dlZddlmZ ddlmZ d	gZG d
d	 d	e Z!dS )    N)linalgspecial)	logsumexp)check_random_state)asarray
atleast_2dreshapezerosnewaxisdotexppisqrtravelpower
atleast_1dsqueezesum	transposeonescov   )mvn)gaussian_kernel_estimategaussian_kdec               @   s   e Zd ZdZd"ddZdd ZeZdd Zd	d
 Zd#ddZ	dd Z
d$ddZdd Zdd ZeZde_d%ddZdd Zdd Zdd Zedd Zed d! ZdS )&r   a  Representation of a kernel-density estimate using Gaussian kernels.

    Kernel density estimation is a way to estimate the probability density
    function (PDF) of a random variable in a non-parametric way.
    `gaussian_kde` works for both uni-variate and multi-variate data.   It
    includes automatic bandwidth determination.  The estimation works best for
    a unimodal distribution; bimodal or multi-modal distributions tend to be
    oversmoothed.

    Parameters
    ----------
    dataset : array_like
        Datapoints to estimate from. In case of univariate data this is a 1-D
        array, otherwise a 2-D array with shape (# of dims, # of data).
    bw_method : str, scalar or callable, optional
        The method used to calculate the estimator bandwidth.  This can be
        'scott', 'silverman', a scalar constant or a callable.  If a scalar,
        this will be used directly as `kde.factor`.  If a callable, it should
        take a `gaussian_kde` instance as only parameter and return a scalar.
        If None (default), 'scott' is used.  See Notes for more details.
    weights : array_like, optional
        weights of datapoints. This must be the same shape as dataset.
        If None (default), the samples are assumed to be equally weighted

    Attributes
    ----------
    dataset : ndarray
        The dataset with which `gaussian_kde` was initialized.
    d : int
        Number of dimensions.
    n : int
        Number of datapoints.
    neff : int
        Effective number of datapoints.

        .. versionadded:: 1.2.0
    factor : float
        The bandwidth factor, obtained from `kde.covariance_factor`, with which
        the covariance matrix is multiplied.
    covariance : ndarray
        The covariance matrix of `dataset`, scaled by the calculated bandwidth
        (`kde.factor`).
    inv_cov : ndarray
        The inverse of `covariance`.

    Methods
    -------
    evaluate
    __call__
    integrate_gaussian
    integrate_box_1d
    integrate_box
    integrate_kde
    pdf
    logpdf
    resample
    set_bandwidth
    covariance_factor

    Notes
    -----
    Bandwidth selection strongly influences the estimate obtained from the KDE
    (much more so than the actual shape of the kernel).  Bandwidth selection
    can be done by a "rule of thumb", by cross-validation, by "plug-in
    methods" or by other means; see [3]_, [4]_ for reviews.  `gaussian_kde`
    uses a rule of thumb, the default is Scott's Rule.

    Scott's Rule [1]_, implemented as `scotts_factor`, is::

        n**(-1./(d+4)),

    with ``n`` the number of data points and ``d`` the number of dimensions.
    In the case of unequally weighted points, `scotts_factor` becomes::

        neff**(-1./(d+4)),

    with ``neff`` the effective number of datapoints.
    Silverman's Rule [2]_, implemented as `silverman_factor`, is::

        (n * (d + 2) / 4.)**(-1. / (d + 4)).

    or in the case of unequally weighted points::

        (neff * (d + 2) / 4.)**(-1. / (d + 4)).

    Good general descriptions of kernel density estimation can be found in [1]_
    and [2]_, the mathematics for this multi-dimensional implementation can be
    found in [1]_.

    With a set of weighted samples, the effective number of datapoints ``neff``
    is defined by::

        neff = sum(weights)^2 / sum(weights^2)

    as detailed in [5]_.

    References
    ----------
    .. [1] D.W. Scott, "Multivariate Density Estimation: Theory, Practice, and
           Visualization", John Wiley & Sons, New York, Chicester, 1992.
    .. [2] B.W. Silverman, "Density Estimation for Statistics and Data
           Analysis", Vol. 26, Monographs on Statistics and Applied Probability,
           Chapman and Hall, London, 1986.
    .. [3] B.A. Turlach, "Bandwidth Selection in Kernel Density Estimation: A
           Review", CORE and Institut de Statistique, Vol. 19, pp. 1-33, 1993.
    .. [4] D.M. Bashtannyk and R.J. Hyndman, "Bandwidth selection for kernel
           conditional density estimation", Computational Statistics & Data
           Analysis, Vol. 36, pp. 279-298, 2001.
    .. [5] Gray P. G., 1969, Journal of the Royal Statistical Society.
           Series A (General), 132, 272

    Examples
    --------
    Generate some random two-dimensional data:

    >>> from scipy import stats
    >>> def measure(n):
    ...     "Measurement model, return two coupled measurements."
    ...     m1 = np.random.normal(size=n)
    ...     m2 = np.random.normal(scale=0.5, size=n)
    ...     return m1+m2, m1-m2

    >>> m1, m2 = measure(2000)
    >>> xmin = m1.min()
    >>> xmax = m1.max()
    >>> ymin = m2.min()
    >>> ymax = m2.max()

    Perform a kernel density estimate on the data:

    >>> X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
    >>> positions = np.vstack([X.ravel(), Y.ravel()])
    >>> values = np.vstack([m1, m2])
    >>> kernel = stats.gaussian_kde(values)
    >>> Z = np.reshape(kernel(positions).T, X.shape)

    Plot the results:

    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots()
    >>> ax.imshow(np.rot90(Z), cmap=plt.cm.gist_earth_r,
    ...           extent=[xmin, xmax, ymin, ymax])
    >>> ax.plot(m1, m2, 'k.', markersize=2)
    >>> ax.set_xlim([xmin, xmax])
    >>> ax.set_ylim([ymin, ymax])
    >>> plt.show()

    Nc             C   s   t t|| _| jjdks"td| jj\| _| _|d k	rt|j	t
| _|  jt| j  _| jjdkrrtdt| j| jkrtddt| jd  | _| j|d d S )Nr   z.`dataset` input should have multiple elements.z*`weights` input should be one-dimensional.z%`weights` input should be of length n   )	bw_method)r   r   datasetsize
ValueErrorshapednr   Zastypefloat_weightsr   weightsndimlen_neffset_bandwidth)selfr   r   r%    r+   0/tmp/pip-build-riy7u7_k/scipy/scipy/stats/kde.py__init__   s    zgaussian_kde.__init__c       	      C   s   t t|}|j\}}|| jkr^|dkrH|| jkrHt|| jdf}d}nd|| jf }t|tj| j|}tj	|j
}|dkrd}n,|dkrd}n|dkrd	}ntd
||f t| | jj| jdddf |j| j|}|dddf S )a  Evaluate the estimated pdf on a set of points.

        Parameters
        ----------
        points : (# of dimensions, # of points)-array
            Alternatively, a (# of dimensions,) vector can be passed in and
            treated as a single point.

        Returns
        -------
        values : (# of points,)-array
            The values at each point.

        Raises
        ------
        ValueError : if the dimensionality of the input points is different than
                     the dimensionality of the KDE.

        r   z2points have dimension %s, dataset has dimension %s   r#      double      zlong doublez%s has unexpected item size %dNr   )r1   r2   )r   r   r    r!   r   r   npZcommon_type
covariancedtypeitemsize	TypeErrorr   r   Tr%   inv_cov)	r*   pointsr!   mmsgZoutput_dtyper6   specresultr+   r+   r,   evaluate   s,    


zgaussian_kde.evaluatec             C   s   t t|}t|}|j| jfkr0td| j |j| j| jfkrPtd| j |ddtf }| j| }tj	|}| j
| }tj||}tjtj|d }tdt |jd d | }t|| ddd }	tt|	 | j dd| }
|
S )aW  
        Multiply estimated density by a multivariate Gaussian and integrate
        over the whole space.

        Parameters
        ----------
        mean : aray_like
            A 1-D array, specifying the mean of the Gaussian.
        cov : array_like
            A 2-D array, specifying the covariance matrix of the Gaussian.

        Returns
        -------
        result : scalar
            The value of the integral.

        Raises
        ------
        ValueError
            If the mean or covariance of the input Gaussian differs from
            the KDE's dimensionality.

        zmean does not have dimension %sz%covariance does not have dimension %sNr   r   g       @)axis)r   r   r   r    r!   r   r
   r4   r   
cho_factorr   	cho_solver3   proddiagonalr   r   r   r   r%   )r*   meanr   sum_covsum_cov_choldifftdiffsqrt_det
norm_constenergiesr>   r+   r+   r,   integrate_gaussian  s     


zgaussian_kde.integrate_gaussianc             C   sl   | j dkrtdtt| jd }t|| j | }t|| j | }tj| jt	j
|t	j
|  }|S )a  
        Computes the integral of a 1D pdf between two bounds.

        Parameters
        ----------
        low : scalar
            Lower bound of integration.
        high : scalar
            Upper bound of integration.

        Returns
        -------
        value : scalar
            The result of the integral.

        Raises
        ------
        ValueError
            If the KDE is over more than one dimension.

        r   z'integrate_box_1d() only handles 1D pdfsr   )r!   r   r   r   r4   r   r3   r   r%   r   Zndtr)r*   lowhighZstdevZnormalized_lowZnormalized_highvaluer+   r+   r,   integrate_box_1d7  s    
zgaussian_kde.integrate_box_1dc             C   sV   |dk	rd|i}ni }t j||| j| j| jf|\}}|rRd| jd  }tj| |S )a  Computes the integral of a pdf over a rectangular interval.

        Parameters
        ----------
        low_bounds : array_like
            A 1-D array containing the lower bounds of integration.
        high_bounds : array_like
            A 1-D array containing the upper bounds of integration.
        maxpts : int, optional
            The maximum number of points to use for integration.

        Returns
        -------
        value : scalar
            The result of the integral.

        Nmaxptsz5An integral in mvn.mvnun requires more points than %si  )r   Zmvnun_weightedr   r%   r4   r!   warningswarn)r*   Z
low_boundsZhigh_boundsrR   Z
extra_kwdsrP   Zinformr<   r+   r+   r,   integrate_boxZ  s    

zgaussian_kde.integrate_boxc             C   s   |j | j krtd|j| jk r*|}| }n| }|}|j|j }tj|}d}xvt|jD ]h}|jdd|tf }|j| }	tj	||	}
t
|	|
 ddd }|t
t| |j dd|j|  7 }qXW tjtj|d }tdt |jd d | }|| }|S )a  
        Computes the integral of the product of this  kernel density estimate
        with another.

        Parameters
        ----------
        other : gaussian_kde instance
            The other kde.

        Returns
        -------
        value : scalar
            The result of the integral.

        Raises
        ------
        ValueError
            If the KDEs have different dimensionality.

        z$KDEs are not the same dimensionalityg        Nr   )r@   g       @r   )r!   r   r"   r4   r   rA   ranger   r
   rB   r   r   r%   r3   rC   rD   r   r   r    )r*   othersmallZlargerF   rG   r>   irE   rH   rI   rL   rJ   rK   r+   r+   r,   integrate_kde{  s(    

*zgaussian_kde.integrate_kdec             C   sh   |dkrt | j}t|}t|jt| jft| j|d}|j	| j
|| jd}| jdd|f }|| S )a  
        Randomly sample a dataset from the estimated pdf.

        Parameters
        ----------
        size : int, optional
            The number of samples to draw.  If not provided, then the size is
            the same as the effective number of samples in the underlying
            dataset.
        seed : {None, int, `~np.random.RandomState`, `~np.random.Generator`}, optional
            This parameter defines the object to use for drawing random
            variates.
            If `seed` is `None` the `~np.random.RandomState` singleton is used.
            If `seed` is an int, a new ``RandomState`` instance is used, seeded
            with seed.
            If `seed` is already a ``RandomState`` or ``Generator`` instance,
            then that object is used.
            Default is None.
            Specify `seed` for reproducible drawing of random variates.

        Returns
        -------
        resample : (self.d, `size`) ndarray
            The sampled dataset.

        N)r   )r   p)intneffr   r   Zmultivariate_normalr	   r!   r#   r4   choicer"   r%   r   )r*   r   seedZrandom_stateZnormindicesZmeansr+   r+   r,   resample  s    
zgaussian_kde.resamplec             C   s   t | jd| jd  S )zoCompute Scott's factor.

        Returns
        -------
        s : float
            Scott's factor.
        g      ?r.   g      )r   r]   r!   )r*   r+   r+   r,   scotts_factor  s    zgaussian_kde.scotts_factorc             C   s$   t | j| jd  d d| jd  S )z{Compute the Silverman factor.

        Returns
        -------
        s : float
            The silverman factor.
        g       @g      @g      ?r.   g      )r   r]   r!   )r*   r+   r+   r,   silverman_factor  s    zgaussian_kde.silverman_factora0  Computes the coefficient (`kde.factor`) that
        multiplies the data covariance matrix to obtain the kernel covariance
        matrix. The default is `scotts_factor`.  A subclass can overwrite this
        method to provide a different method, or set it through a call to
        `kde.set_bandwidth`.c                s    dkr
nz dkrj _nh dkr.j_nVtj rZt t rZd_ fdd_n*t rx _fdd_nd}t	|j
  dS )	a9  Compute the estimator bandwidth with given method.

        The new bandwidth calculated after a call to `set_bandwidth` is used
        for subsequent evaluations of the estimated density.

        Parameters
        ----------
        bw_method : str, scalar or callable, optional
            The method used to calculate the estimator bandwidth.  This can be
            'scott', 'silverman', a scalar constant or a callable.  If a
            scalar, this will be used directly as `kde.factor`.  If a callable,
            it should take a `gaussian_kde` instance as only parameter and
            return a scalar.  If None (default), nothing happens; the current
            `kde.covariance_factor` method is kept.

        Notes
        -----
        .. versionadded:: 0.11

        Examples
        --------
        >>> import scipy.stats as stats
        >>> x1 = np.array([-7, -5, 1, 4, 5.])
        >>> kde = stats.gaussian_kde(x1)
        >>> xs = np.linspace(-10, 10, num=50)
        >>> y1 = kde(xs)
        >>> kde.set_bandwidth(bw_method='silverman')
        >>> y2 = kde(xs)
        >>> kde.set_bandwidth(bw_method=kde.factor / 3.)
        >>> y3 = kde(xs)

        >>> import matplotlib.pyplot as plt
        >>> fig, ax = plt.subplots()
        >>> ax.plot(x1, np.full(x1.shape, 1 / (4. * x1.size)), 'bo',
        ...         label='Data points (rescaled)')
        >>> ax.plot(xs, y1, label='Scott (default)')
        >>> ax.plot(xs, y2, label='Silverman')
        >>> ax.plot(xs, y3, label='Const (1/3 * Silverman)')
        >>> ax.legend()
        >>> plt.show()

        NZscottZ	silvermanzuse constantc                  s    S )Nr+   r+   )r   r+   r,   <lambda>#  s    z,gaussian_kde.set_bandwidth.<locals>.<lambda>c                  s
    j  S )N)
_bw_methodr+   )r*   r+   r,   rd   &  s    zC`bw_method` should be 'scott', 'silverman', a scalar or a callable.)rb   covariance_factorrc   r3   Zisscalar
isinstancestrre   callabler   _compute_covariance)r*   r   r<   r+   )r   r*   r,   r)     s    +

zgaussian_kde.set_bandwidthc             C   s   | j  | _t| ds<tt| jdd| jd| _tj	| j| _
| j| jd  | _| j
| jd  | _tj| jd t }dtjtj|j  | _dS )zcComputes the covariance matrix for each Gaussian kernel using
        covariance_factor().
        _data_inv_covr   F)ZrowvarZbiasZaweightsr   N)rf   Zfactorhasattrr   r   r   r%   Z_data_covariancer   invrk   r4   r9   Zcholeskyr   r3   logZdiagr   log_det)r*   Lr+   r+   r,   rj   .  s    


z gaussian_kde._compute_covariancec             C   s
   | j |S )z
        Evaluate the estimated pdf on a provided set of points.

        Notes
        -----
        This is an alias for `gaussian_kde.evaluate`.  See the ``evaluate``
        docstring for more details.

        )r?   )r*   xr+   r+   r,   pdf?  s    
zgaussian_kde.pdfc             C   st  t |}|j\}}|| jkrZ|dkrD|| jkrDt|| jdf}d}nd|| jf }t||| jkrt| j|ftd}xJt| jD ]<}| j	dd|t
f | }t| j|}	t||	 dd||< qW dtj| j | j |j }
td|
 dd}nt|ftd}xpt|D ]d}| j	|dd|t
f  }t| j|}	t||	 dd}dtj| j | j | }
td|
 ||< qW |S )	zT
        Evaluate the log of the estimated pdf on a provided set of points.
        r   z2points have dimension %s, dataset has dimension %s)r5   Nr   )r@   g       @g      ?)r   r    r!   r   r   r"   r	   r#   rV   r   r
   r   r9   r   r3   rn   r%   ro   r8   r   )r*   rq   r:   r!   r;   r<   ZenergyrY   rH   rI   Z
log_to_sumr>   r+   r+   r,   logpdfK  s2    



zgaussian_kde.logpdfc             C   s4   y| j S  tk
r.   t| j| j | _ | j S X d S )N)r$   AttributeErrorr   r"   )r*   r+   r+   r,   r%   r  s
    zgaussian_kde.weightsc             C   s6   y| j S  tk
r0   dt| jd  | _ | j S X d S )Nr   r   )r(   rt   r   r%   )r*   r+   r+   r,   r]   z  s
    zgaussian_kde.neff)NN)N)NN)N)__name__
__module____qualname____doc__r-   r?   __call__rM   rQ   rU   rZ   ra   rb   rc   rf   r)   rj   rr   rs   propertyr%   r]   r+   r+   r+   r,   r   )   s(    
05#
!2
'

>')"rS   Zscipyr   r   Zscipy.specialr   Zscipy._lib._utilr   Znumpyr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r3    r   Z_statsr   __all__objectr   r+   r+   r+   r,   <module>   s   L