U
    sVc                     @  s  d dl mZ d dlZd dlZd dlZd dlmZmZmZ d dl	Z	d dl
Zd dlmZ d dlmZmZmZmZ d dlmZmZmZmZmZmZ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+ d d	l,m-Z- d d
l.m/Z/m0Z0m1Z1 d dl2m3Z3 edddZ4e4dk	Z5da6ddddddZ7e7ed G dd dZ8G dd dZ9ddddddZ:dd d!d"Z;ddd#d$d%d&Z<d'dd(d(d)d*d+Z=dd'dd,d-d(d.d/d0d1Z>ddd2d3d4Z?dd5d6d7d8Z@d9d9d:d;d<ZAd'd=d>d?d@dAZBd9d9d:dBdCZCddddDd'd=dd(ddEdFdGZDddddDd'd=dd(ddEdHdIZEe8dJeAeCddd ddKd'd=ddLd(dMdNdOdPZFdQd=dRd'dSdTdUdVZGe8e-e9 eAddddDd'd=dd(dMdEdWdXZHe9 ddddDdYdZZId[dLd\d,d'd]d^d_ZJeKejLfd`d(d=dLd5dadbdcddZMe9dedfdddeddgdhdiZNe8dJdje9dedfdddeddgdkdlZOe8dJdjdddeddgd'd=ddLd(dMdmdndoZPdpdq ZQeQdrdsdtZReQdudvdtZSe8dwddddDd'd=dd(dxdEdydzZTe8dwddddDd'd=dd(dxdEd{d|ZUe8dJdjeCddddDd'd=dd(dMdEd}d~ZVe8dJdjeCddddDd'd=dd(dMdEddZWe8dJdjeCddd ddKd'd=ddLd(dMdNddZXd'd=d(dddddZYeKejLfd`d(d=d5ddddZZddd=d(d[dLddddZ[d[d(dLddddZ\dd Z]e8dJdjdddd'd'd=dMdddZ^dd ddZ_e8dJdjddedd'd'd=d=dMdddZ`dd Zadd ZbebejcZdebejeZfebejgZhebejiZjebejkZlebejmZnddddddZodS )    )annotationsN)AnyCallablecast)
get_option)NaTNaTTypeiNaTlib)	ArrayLikeDtypeDtypeObjFScalarShapenpt)import_optional_dependency)is_any_int_dtypeis_bool_dtype
is_complexis_datetime64_any_dtypeis_floatis_float_dtype
is_integeris_integer_dtypeis_numeric_dtypeis_object_dtype	is_scalaris_timedelta64_dtypeneeds_i8_conversionpandas_dtype)PeriodDtype)isnana_value_for_dtypenotna)extract_arrayZ
bottleneckwarn)errorsFTboolNone)vreturnc                 C  s   t r| ad S N)_BOTTLENECK_INSTALLED_USE_BOTTLENECK)r*    r/   6/tmp/pip-unpacked-wheel-xj8nt62q/pandas/core/nanops.pyset_use_bottleneck@   s    r1   zcompute.use_bottleneckc                      sB   e Zd Zddd fddZdddd	Zd
d
dddZ  ZS )disallowr   r)   )dtypesr+   c                   s"   t    tdd |D | _d S )Nc                 s  s   | ]}t |jV  qd S r,   )r    type).0dtyper/   r/   r0   	<genexpr>M   s     z$disallow.__init__.<locals>.<genexpr>)super__init__tupler3   )selfr3   	__class__r/   r0   r9   K   s    
zdisallow.__init__r(   r+   c                 C  s   t |dot|jj| jS )Nr6   )hasattr
issubclassr6   r4   r3   )r;   objr/   r/   r0   checkO   s    zdisallow.checkr   )fr+   c                   s"   t   fdd}tt|S )Nc               
     s   t | | }tfdd|D rD jdd}td| dz0tjdd  | |W  5 Q R  W S Q R X W n: t	k
r } zt
| d	 rt|| W 5 d }~X Y nX d S )
Nc                 3  s   | ]}  |V  qd S r,   )rB   )r5   rA   )r;   r/   r0   r7   V   s     z0disallow.__call__.<locals>._f.<locals>.<genexpr>nan zreduction operation 'z' not allowed for this dtypeignoreinvalidr   )	itertoolschainvaluesany__name__replace	TypeErrornperrstate
ValueErrorr   )argskwargsZobj_iterf_nameerC   r;   r/   r0   _fS   s    
"
zdisallow.__call__.<locals>._f	functoolswrapsr   r   )r;   rC   rX   r/   rW   r0   __call__R   s    zdisallow.__call__)rM   
__module____qualname__r9   rB   r\   __classcell__r/   r/   r<   r0   r2   J   s   r2   c                   @  s,   e Zd Zd
ddddZddddd	ZdS )bottleneck_switchNr)   r>   c                 K  s   || _ || _d S r,   )namerT   )r;   ra   rT   r/   r/   r0   r9   k   s    zbottleneck_switch.__init__r   )altr+   c              	     sp   j p
 jzttW n ttfk
r6   d Y nX t d dddddd fdd}tt	|S )	NTaxisskipna
np.ndarray
int | Noner(   )rK   rd   re   c                  s   t jdkr2j D ]\}}||kr|||< q| jdkrT|dd krTt| |S tr|rt| jr|dd d kr|	dd  | fd|i|}t
|rΈ | f||d|}q | f||d|}n | f||d|}|S )Nr   	min_countmaskrd   rc   )lenrT   itemssizeget_na_for_min_countr.   _bn_ok_dtyper6   pop	_has_infs)rK   rd   re   kwdskr*   resultrb   Zbn_funcZbn_namer;   r/   r0   rC   w   s    

z%bottleneck_switch.__call__.<locals>.f)
ra   rM   getattrbnAttributeError	NameErrorrZ   r[   r   r   )r;   rb   rC   r/   ru   r0   r\   o   s    
"'zbottleneck_switch.__call__)N)rM   r]   r^   r9   r\   r/   r/   r/   r0   r`   j   s   r`   r   str)r6   ra   r+   c                 C  s   t | st| s|dkS dS )N)nansumnanprodnanmeanF)r   r   )r6   ra   r/   r/   r0   ro      s    ro   r>   c              	   C  s`   t | tjr0| jdks | jdkr0t| dS zt|  W S  t	t
fk
rZ   Y dS X d S )Nf8Zf4KF)
isinstancerP   ndarrayr6   r
   Zhas_infsZravelisinfrL   rO   NotImplementedError)rt   r/   r/   r0   rq      s    rq   zScalar | None)r6   
fill_valuec                 C  sP   |dk	r|S t | r:|dkr"tjS |dkr0tjS tj S n|dkrHtjS tS dS )z9return the correct fill value for the dtype of the valuesN+inf)_na_ok_dtyperP   rD   infr
   i8maxr	   )r6   r   fill_value_typr/   r/   r0   _get_fill_value   s    
r   rf   npt.NDArray[np.bool_] | None)rK   re   ri   r+   c                 C  s:   |dkr6t | jst| jr dS |s.t| jr6t| }|S )a  
    Compute a mask if and only if necessary.

    This function will compute a mask iff it is necessary. Otherwise,
    return the provided mask (potentially None) when a mask does not need to be
    computed.

    A mask is never necessary if the values array is of boolean or integer
    dtypes, as these are incapable of storing NaNs. If passing a NaN-capable
    dtype that is interpretable as either boolean or integer data (eg,
    timedelta64), a mask must be provided.

    If the skipna parameter is False, a new mask will not be computed.

    The mask is computed using isna() by default. Setting invert=True selects
    notna() as the masking function.

    Parameters
    ----------
    values : ndarray
        input array to potentially compute mask for
    skipna : bool
        boolean for whether NaNs should be skipped
    mask : Optional[ndarray]
        nan-mask if known

    Returns
    -------
    Optional[np.ndarray[bool]]
    N)r   r6   r   r   r"   )rK   re   ri   r/   r/   r0   _maybe_get_mask   s    !r   r   z
str | NonezHtuple[np.ndarray, npt.NDArray[np.bool_] | None, np.dtype, np.dtype, Any])rK   re   r   r   ri   r+   c           	      C  s   t |stt| dd} t| ||}| j}d}t| jrLt| d} d}t	|}t
|||d}|r|dk	r|dk	r| r|s|r|  } t| || nt| | |} |}t|st|rttj}nt|rttj}| ||||fS )a7  
    Utility to get the values view, mask, dtype, dtype_max, and fill_value.

    If both mask and fill_value/fill_value_typ are not None and skipna is True,
    the values array will be copied.

    For input arrays of boolean or integer dtypes, copies will only occur if a
    precomputed mask, a fill_value/fill_value_typ, and skipna=True are
    provided.

    Parameters
    ----------
    values : ndarray
        input array to potentially compute mask for
    skipna : bool
        boolean for whether NaNs should be skipped
    fill_value : Any
        value to fill NaNs with
    fill_value_typ : str
        Set to '+inf' or '-inf' to handle dtype-specific infinities
    mask : Optional[np.ndarray[bool]]
        nan-mask if known

    Returns
    -------
    values : ndarray
        Potential copy of input value array
    mask : Optional[ndarray[bool]]
        Mask for values, if deemed necessary to compute
    dtype : np.dtype
        dtype for values
    dtype_max : np.dtype
        platform independent dtype
    fill_value : Any
        fill value used
    TZextract_numpyFi8)r   r   N)r   AssertionErrorr%   r   r6   r   rP   asarrayviewr   r   rL   copyputmaskwherer   r   int64r   float64)	rK   re   r   r   ri   r6   datetimelikeZdtype_ok	dtype_maxr/   r/   r0   _get_values  s4    .
  r   )r6   r+   c                 C  s   t | rdS t| jtj S )NF)r   r@   r4   rP   integerr6   r/   r/   r0   r   ^  s    r   znp.dtyper   c                 C  s  | t kr
nt|r|dkrt}t| tjs~t|r:td| |krHtj} t| r^t	dd} nt
| d} | j|dd} n
| |} nzt|rt| tjs| |kst| rtd|} n.t| tjkrtdnt
| j|dd} n| d	|} | S )
zwrap our results if neededNzExpected non-null fill_valuer   nszdatetime64[ns]Fr   zoverflow in timedelta operationm8[ns])r   r   r	   r   rP   r   r"   r   rD   Z
datetime64r   r   astyper   isnanZtimedelta64fabsr
   r   rR   )rt   r6   r   r/   r/   r0   _wrap_resultsd  s.    

r   r   )funcr+   c                   s6   t  ddddddddd fd	d
}tt|S )z
    If we have datetime64 or timedelta64 values, ensure we have a correct
    mask before calling the wrapped function, then cast back afterwards.
    NTrd   re   ri   rf   rg   r(   r   )rK   rd   re   ri   c                  sr   | }| j jdk}|r$|d kr$t| } | f|||d|}|rnt||j td}|sn|d k	s`tt||||}|S )NmMr   )r   )r6   kindr"   r   r	   r   _mask_datetimelike_result)rK   rd   re   ri   rT   orig_valuesr   rt   r   r/   r0   new_func  s    	z&_datetimelike_compat.<locals>.new_funcrY   )r   r   r/   r   r0   _datetimelike_compat  s    r   rg   zScalar | np.ndarray)rK   rd   r+   c                 C  sl   t | r| d} t| j}| jdkr*|S |dkr6|S | jd| | j|d d  }tj||| jdS dS )a  
    Return the missing value for `values`.

    Parameters
    ----------
    values : ndarray
    axis : int or None
        axis for the reduction, required if values.ndim > 1.

    Returns
    -------
    result : scalar or ndarray
        For 1-D values, returns a scalar of the correct missing type.
        For 2-D values, returns a 1-D array where each element is missing.
    r      Nr   )r   r   r#   r6   ndimshaperP   full)rK   rd   r   Zresult_shaper/   r/   r0   rn     s    


 rn   c                   s.   t  ddddd fdd}tt|S )z
    NumPy operations on C-contiguous ndarrays with axis=1 can be
    very slow if axis 1 >> axis 0.
    Operate row-by-row and concatenate the results.
    Nrd   rf   rg   )rK   rd   c                  s   |dkr| j dkr| jd r| jd d | jd kr| jtkr| jtkrt|  dd k	rd fddt	t
 D }nfd	d D }t|S | fd
|iS )Nr      ZC_CONTIGUOUSi  r   ri   c                   s(   g | ] } | fd | iqS ri   r/   )r5   i)arrsr   rT   ri   r/   r0   
<listcomp>  s    z:maybe_operate_rowwise.<locals>.newfunc.<locals>.<listcomp>c                   s   g | ]} |fqS r/   r/   )r5   x)r   rT   r/   r0   r     s     rd   )r   flagsr   r6   objectr(   listrm   rp   rangerj   rP   array)rK   rd   rT   resultsr   )r   rT   ri   r0   newfunc  s*    



z&maybe_operate_rowwise.<locals>.newfuncrY   )r   r   r/   r   r0   maybe_operate_rowwise  s    r   r   rK   rd   re   ri   r+   c                C  s6   t | |d|d\} }}}}t| r,| t} | |S )a  
    Check if any elements along an axis evaluate to True.

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : bool

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, 2])
    >>> nanops.nanany(s)
    True

    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([np.nan])
    >>> nanops.nanany(s)
    False
    Fr   ri   )r   r   r   r(   rL   rK   rd   re   ri   _r/   r/   r0   nanany  s    "
r   c                C  s6   t | |d|d\} }}}}t| r,| t} | |S )a  
    Check if all elements along an axis evaluate to True.

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : bool

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, 2, np.nan])
    >>> nanops.nanall(s)
    True

    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, 0])
    >>> nanops.nanall(s)
    False
    Tr   )r   r   r   r(   allr   r/   r/   r0   nanall  s    "
r   ZM8)rd   re   rh   ri   intfloat)rK   rd   re   rh   ri   r+   c          
      C  sf   t | |d|d\} }}}}|}t|r,|}nt|r@ttj}| j||d}	t|	||| j|d}	|	S )a  
    Sum the elements along an axis ignoring NaNs

    Parameters
    ----------
    values : ndarray[dtype]
    axis : int, optional
    skipna : bool, default True
    min_count: int, default 0
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : dtype

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, 2, np.nan])
    >>> nanops.nansum(s)
    3.0
    r   r   r   rh   )	r   r   r   rP   r6   r   sum_maybe_null_outr   )
rK   rd   re   rh   ri   r6   r   r   	dtype_sumthe_sumr/   r/   r0   r{   L  s    "   r{   z+np.ndarray | np.datetime64 | np.timedelta64znpt.NDArray[np.bool_]z5np.ndarray | np.datetime64 | np.timedelta64 | NaTType)rt   rd   ri   r   r+   c                 C  sR   t | tjr4| d|j} |j|d}t| |< n| rNtt|jS | S )Nr   r   )	r   rP   r   r   r   r6   rL   r	   r   )rt   rd   ri   r   Z	axis_maskr/   r/   r0   r   }  s    
r   c             	   C  s  t | |d|d\} }}}}|}ttj}|jdkrBttj}n&t|rXttj}nt|rh|}|}t| j|||d}	t	| j
||d}
|dk	rt|
ddrttj|	}	tjdd	 |
|	 }W 5 Q R X |	dk}| rtj||< n|	dkr|
|	 ntj}|S )
a	  
    Compute the mean of the element along an axis ignoring NaNs

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    float
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, 2, np.nan])
    >>> nanops.nanmean(s)
    1.5
    r   r   r   r   Nr   FrF   r   )r   rP   r6   r   r   r   r   _get_countsr   _ensure_numericr   rv   r   r   rQ   rL   rD   )rK   rd   re   ri   r6   r   r   r   Zdtype_countcountr   Zthe_meanZct_maskr/   r/   r0   r}     s4    "   
r}   c          
   
     s   fdd}t |  |d\} }}}}t| jsz| d} W n0 tk
rl } ztt||W 5 d}~X Y nX |dk	rtj| |< | j	}| j
dkr|dk	r|rވ st||| }	qt  tdd t| |}	W 5 Q R X nt| j|tjtj}	n|r|| ntj}	t|	|S )	a  
    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : float
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, np.nan, 2, 2])
    >>> nanops.nanmedian(s)
    2.0
    c              	     sL   t | } s| stjS t   tdd t| | }W 5 Q R X |S )NrF   All-NaN slice encountered)r$   r   rP   rD   warningscatch_warningsfilterwarnings	nanmedian)r   ri   resre   r/   r0   
get_median  s    
znanmedian.<locals>.get_medianr   r~   Nr   rF   r   )r   r   r6   r   rR   rO   rz   rP   rD   rl   r   Zapply_along_axisr   r   r   r   get_empty_reduction_resultr   Zfloat_r   )
rK   rd   re   ri   r   r6   r   errZnotemptyr   r/   r   r0   r     s(    

 

r   ztuple[int, ...]znp.dtype | type[np.floating])r   rd   r6   r   r+   c                 C  s<   t | }t t| }t j|||k |d}|| |S )z
    The result from a reduction on an empty ndarray.

    Parameters
    ----------
    shape : Tuple[int]
    axis : int
    dtype : np.dtype
    fill_value : Any

    Returns
    -------
    np.ndarray
    r   )rP   r   Zarangerj   emptyfill)r   rd   r6   r   ZshpZdimsretr/   r/   r0   r     s
    

r   r   z-tuple[float | np.ndarray, float | np.ndarray])values_shaperi   rd   ddofr6   r+   c                 C  s   t | |||d}||| }t|r<||krxtj}tj}n<ttj|}||k}| rxt||tj t||tj ||fS )a:  
    Get the count of non-null values along an axis, accounting
    for degrees of freedom.

    Parameters
    ----------
    values_shape : Tuple[int, ...]
        shape tuple from values ndarray, used if mask is None
    mask : Optional[ndarray[bool]]
        locations in values that should be considered missing
    axis : Optional[int]
        axis to count along
    ddof : int
        degrees of freedom
    dtype : type, optional
        type to use for count

    Returns
    -------
    count : int, np.nan or np.ndarray
    d : int, np.nan or np.ndarray
    r   )	r   r4   r   rP   rD   r   r   rL   r   )r   ri   rd   r   r6   r   dr/   r/   r0   _get_counts_nanvar8  s    r   r   r   rd   re   r   ri   c             	   C  sT   | j dkr| d} | j }t| ||d\} }}}}tt| ||||d}t||S )a  
    Compute the standard deviation along given axis while ignoring NaNs

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    ddof : int, default 1
        Delta Degrees of Freedom. The divisor used in calculations is N - ddof,
        where N represents the number of elements.
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : float
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, np.nan, 2, 3])
    >>> nanops.nanstd(s)
    1.0
    M8[ns]r   r   r   )r6   r   r   rP   sqrtnanvarr   )rK   rd   re   r   ri   
orig_dtyper   rt   r/   r/   r0   nanstdg  s    

r   Zm8c                C  s  t | dd} | j}t| ||}t|rB| d} |dk	rBtj| |< t| jrft| j	|||| j\}}nt| j	|||\}}|r|dk	r| 
 } t| |d t| j|tjd| }|dk	rt||}t||  d }	|dk	rt|	|d |	j|tjd| }
t|r|
j|dd	}
|
S )
a  
    Compute the variance along given axis while ignoring NaNs

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    ddof : int, default 1
        Delta Degrees of Freedom. The divisor used in calculations is N - ddof,
        where N represents the number of elements.
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : float
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, np.nan, 2, 3])
    >>> nanops.nanvar(s)
    1.0
    Tr   r~   Nr   )rd   r6   r   Fr   )r%   r6   r   r   r   rP   rD   r   r   r   r   r   r   r   r   expand_dims)rK   rd   re   r   ri   r6   r   r   avgZsqrrt   r/   r/   r0   r     s.    



r   )rK   rd   re   r   ri   r+   c                C  sn   t | ||||d t| ||}t| js2| d} t| j|||| j\}}t | |||d}t|t| S )a  
    Compute the standard error in the mean along given axis while ignoring NaNs

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    ddof : int, default 1
        Delta Degrees of Freedom. The divisor used in calculations is N - ddof,
        where N represents the number of elements.
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : float64
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, np.nan, 2, 3])
    >>> nanops.nansem(s)
     0.5773502691896258
    r   r~   )rd   re   r   )	r   r   r   r6   r   r   r   rP   r   )rK   rd   re   r   ri   r   r   varr/   r/   r0   nansem  s    &

r   c              	     s<   t d dtd dd dddddd	d
 fdd}|S )NrD   )ra   Tr   rf   rg   r(   r   r   r   c             
     s   t | | |d\} }}}}|d k	r0| j| dks:| jdkrz"t| ||d}|tj W q ttt	fk
r|   tj}Y qX nt| |}t
|||| j}|S )Nr   ri   r   r   )r   r   rl   rv   r   rP   rD   rx   rO   rR   r   )rK   rd   re   ri   r6   r   r   rt   r   methr/   r0   	reduction  s    
    z_nanminmax.<locals>.reduction)r`   r   )r   r   r   r/   r   r0   
_nanminmax  s    $r   minr   )r   max-infOzint | np.ndarrayc                C  s6   t | dd|d\} }}}}| |}t||||}|S )a  
    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : int or ndarray[int]
        The index/indices  of max value in specified axis or -1 in the NA case

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> arr = np.array([1, 2, 3, np.nan, 4])
    >>> nanops.nanargmax(arr)
    4

    >>> arr = np.array(range(12), dtype=np.float64).reshape(4, 3)
    >>> arr[2:, 2] = np.nan
    >>> arr
    array([[ 0.,  1.,  2.],
           [ 3.,  4.,  5.],
           [ 6.,  7., nan],
           [ 9., 10., nan]])
    >>> nanops.nanargmax(arr, axis=1)
    array([2, 2, 1, 1])
    Tr   r   )r   Zargmax_maybe_arg_null_outrK   rd   re   ri   r   rt   r/   r/   r0   	nanargmax'  s    '
r   c                C  s6   t | dd|d\} }}}}| |}t||||}|S )a  
    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : int or ndarray[int]
        The index/indices of min value in specified axis or -1 in the NA case

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> arr = np.array([1, 2, 3, np.nan, 4])
    >>> nanops.nanargmin(arr)
    0

    >>> arr = np.array(range(12), dtype=np.float64).reshape(4, 3)
    >>> arr[2:, 0] = np.nan
    >>> arr
    array([[ 0.,  1.,  2.],
           [ 3.,  4.,  5.],
           [nan,  7.,  8.],
           [nan, 10., 11.]])
    >>> nanops.nanargmin(arr, axis=1)
    array([0, 0, 1, 1])
    Tr   r   )r   Zargminr   r   r/   r/   r0   	nanargminU  s    '
r   c             	   C  s  t | dd} t| ||}t| js<| d} t| j||}nt| j||| jd}|rr|dk	rr|  } t	| |d | j
|tjd| }|dk	rt||}| | }|r|dk	rt	||d |d }|| }|j
|tjd}	|j
|tjd}
t|	}	t|
}
tjddd	* ||d
 d  |d  |
|	d   }W 5 Q R X | j}t|rX|j|dd}t|tjrt|	dkd|}tj||dk < n"|	dkrdn|}|dk rtjS |S )a  
    Compute the sample skewness.

    The statistic computed here is the adjusted Fisher-Pearson standardized
    moment coefficient G1. The algorithm computes this coefficient directly
    from the second and third central moment.

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : float64
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, np.nan, 1, 2])
    >>> nanops.nanskew(s)
    1.7320508075688787
    Tr   r~   r   Nr   r   rF   rH   divider   g      ?g      ?Fr      )r%   r   r   r6   r   r   r   r   rP   r   r   r   r   _zero_out_fperrrQ   r   r   r   rD   )rK   rd   re   ri   r   meanadjusted	adjusted2Z	adjusted3m2Zm3rt   r6   r/   r/   r0   nanskew  sB    '

.

r  c             	   C  s  t | dd} t| ||}t| js<| d} t| j||}nt| j||| jd}|rr|dk	rr|  } t	| |d | j
|tjd| }|dk	rt||}| | }|r|dk	rt	||d |d }|d }|j
|tjd}	|j
|tjd}
tjddd	V d
|d d  |d |d
   }||d  |d  |
 }|d |d
  |	d  }W 5 Q R X t|}t|}t|tjs|dk rtjS |dkrdS tjddd	 || | }W 5 Q R X | j}t|r|j|dd}t|tjrt|dkd|}tj||dk < |S )a  
    Compute the sample excess kurtosis

    The statistic computed here is the adjusted Fisher-Pearson standardized
    moment coefficient G2, computed directly from the second and fourth
    central moment.

    Parameters
    ----------
    values : ndarray
    axis : int, optional
    skipna : bool, default True
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    result : float64
        Unless input is a float array, in which case use the same
        precision as the input array.

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, np.nan, 1, 3, 2])
    >>> nanops.nankurt(s)
    -1.2892561983471076
    Tr   r~   r   Nr   r   rF   r   r   r      Fr   )r%   r   r   r6   r   r   r   r   rP   r   r   r   r   rQ   r   r   r   rD   r   )rK   rd   re   ri   r   r   r  r  Z	adjusted4r  Zm4Zadj	numeratordenominatorrt   r6   r/   r/   r0   nankurt  sN    '

 "


r  c                C  sF   t | ||}|r(|dk	r(|  } d| |< | |}t|||| j|dS )a  
    Parameters
    ----------
    values : ndarray[dtype]
    axis : int, optional
    skipna : bool, default True
    min_count: int, default 0
    mask : ndarray[bool], optional
        nan-mask if known

    Returns
    -------
    Dtype
        The product of all elements on a given axis. ( NaNs are treated as 1)

    Examples
    --------
    >>> import pandas.core.nanops as nanops
    >>> s = pd.Series([1, 2, 3, np.nan])
    >>> nanops.nanprod(s)
    6.0
    Nr   r   )r   r   prodr   r   )rK   rd   re   rh   ri   rt   r/   r/   r0   r|   <  s     
    r|   znp.ndarray | int)rt   rd   ri   re   r+   c                 C  sn   |d kr| S |d ks t | dds@|r2| r>dS qj| rjdS n*|rP||}n
||}| rjd| |< | S )Nr   F)rv   r   rL   )rt   rd   ri   re   Zna_maskr/   r/   r0   r   i  s    
r   zfloat | np.ndarray)r   ri   rd   r6   r+   c                 C  sz   |dkr4|dk	r |j |  }n
t| }||S |dk	rR|j| || }n| | }t|rl||S |j|ddS )a  
    Get the count of non-null values along an axis

    Parameters
    ----------
    values_shape : tuple of int
        shape tuple from values ndarray, used if mask is None
    mask : Optional[ndarray[bool]]
        locations in values that should be considered missing
    axis : Optional[int]
        axis to count along
    dtype : type, optional
        type to use for count

    Returns
    -------
    count : scalar or array
    NFr   )rl   r   rP   r	  r4   r   r   r   )r   ri   rd   r6   nr   r/   r/   r0   r     s    


r   znp.ndarray | float | NaTType)rt   rd   ri   r   rh   r+   c                 C  s   |dk	rt | tjr|dk	r:|j| || | dk }n8|| | dk }|d| ||d d  }t||}t|rt| rt| r| 	d} nt
| s| j	ddd} tj| |< qd| |< n| tk	rt|||rtj} | S )zu
    Returns
    -------
    Dtype
        The product of all elements on a given axis. ( NaNs are treated as 1)
    Nr   r   Zc16r~   Fr   )r   rP   r   r   r   Zbroadcast_torL   r   Ziscomplexobjr   r   rD   r   check_below_min_count)rt   rd   ri   r   rh   Z	null_maskZbelow_countZ	new_shaper/   r/   r0   r     s$    


r   )r   ri   rh   r+   c                 C  s:   |dkr6|dkrt | }n|j|  }||k r6dS dS )a  
    Check for the `min_count` keyword. Returns True if below `min_count` (when
    missing value should be returned from the reduction).

    Parameters
    ----------
    shape : tuple
        The shape of the values (`values.shape`).
    mask : ndarray[bool] or None
        Boolean numpy array (typically of same shape as `shape`) or None.
    min_count : int
        Keyword passed through from sum/prod call.

    Returns
    -------
    bool
    r   NTF)rP   r	  rl   r   )r   ri   rh   Z	non_nullsr/   r/   r0   r    s    r  c              
   C  sh   t | tjrFtjdd& tt| dk d| W  5 Q R  S Q R X nt| dk r`| jdS | S d S )NrF   rG   g+=r   )r   rP   r   rQ   r   absr6   r4   )argr/   r/   r0   r     s    ,r   pearson)methodmin_periods)abr  r+   c                C  sp   t | t |krtd|dkr$d}t| t|@ }| sL| | } || }t | |k r^tjS t|}|| |S )z
    a, b: ndarrays
    z'Operands to nancorr must have same sizeNr   )rj   r   r$   r   rP   rD   get_corr_func)r  r  r  r  validrC   r/   r/   r0   nancorr  s    r  z)Callable[[np.ndarray, np.ndarray], float]c                   s|   | dkr$ddl m   fdd}|S | dkrHddl m fdd}|S | d	kr\d
d }|S t| rh| S td|  dd S )NZkendallr   
kendalltauc                   s    | |d S Nr   r/   r  r  r  r/   r0   r     s    zget_corr_func.<locals>.funcZspearman	spearmanrc                   s    | |d S r  r/   r  r  r/   r0   r      s    r  c                 S  s   t | |d S )Nr   r   )rP   Zcorrcoefr  r/   r/   r0   r   &  s    zUnknown method 'z@', expected one of 'kendall', 'spearman', 'pearson', or callable)Zscipy.statsr  r  callablerR   )r  r   r/   )r  r  r0   r    s     
r  )r  r   )r  r  r  r   r+   c                C  sr   t | t |krtd|d kr$d}t| t|@ }| sL| | } || }t | |k r^tjS tj| ||dd S )Nz&Operands to nancov must have same sizer   r   r  )rj   r   r$   r   rP   rD   Zcov)r  r  r  r   r  r/   r/   r0   nancov3  s    r  c                 C  sH  t | tjrt| st| r*| tj} nt| rz| tj} W n^ t	t
fk
r   z| tj} W n4 t
k
r } zt	d|  d|W 5 d }~X Y nX Y nX tt| s| j} nt| sDt| sDt| sDzt| } W n^ t	t
fk
rB   zt| } W n6 t
k
r< } zt	d|  d|W 5 d }~X Y nX Y nX | S )NzCould not convert z to numeric)r   rP   r   r   r   r   r   r   Z
complex128rO   rR   rL   imagrealr   r   r   r   complex)r   r   r/   r/   r0   r   L  s,    **r   c                   s    fdd}|S )Nc              	     sh   t | }t |}||B }tjdd  | |}W 5 Q R X | rdt|rT|d}t||tj |S )NrF   r   r   )r"   rP   rQ   rL   r   r   r   rD   )r   yZxmaskZymaskri   rt   opr/   r0   rC   m  s    
zmake_nancomp.<locals>.fr/   )r%  rC   r/   r$  r0   make_nancompl  s    r&  r   )rK   re   r+   c             	   C  s  t jdt jft jjt j t jft jdt jft jjt jt jfi| \}}| jj	dkr8| j}t
| }| d}|t jjk}z|rtj||< ||dd}	W 5 |rt||< X |rt|	|< n8|t jjkrt |  d }
t|
rt|	d|
d < t| jt jr|	|}	n.t|t jr|nd}t| j|	||d	}	nX|rt| jjt jt jfs|  }t
|}|||< ||dd}	||	|< n|| dd}	|	S )
a  
    Cumulative function with skipna support.

    Parameters
    ----------
    values : np.ndarray or ExtensionArray
    accum_func : {np.cumprod, np.maximum.accumulate, np.cumsum, np.minimum.accumulate}
    skipna : bool

    Returns
    -------
    np.ndarray or ExtensionArray
    g      ?g        r   r   r   r   Nr   r   )rP   ZcumprodrD   maximum
accumulater   ZcumsumZminimumr6   r   r"   r   r	   r
   r   r   Znonzerorj   r   r4   Z_simple_newr@   r   Zbool_r   )rK   Z
accum_funcre   Zmask_aZmask_br   ri   r#  changedrt   ZnzZnpdtypevalsr/   r/   r0   na_accum_func  sV        




 
r+  )T)NN)NNN)N)r   )p
__future__r   rZ   rI   operatortypingr   r   r   r   ZnumpyrP   Zpandas._configr   Zpandas._libsr   r   r	   r
   Zpandas._typingr   r   r   r   r   r   r   Zpandas.compat._optionalr   Zpandas.core.dtypes.commonr   r   r   r   r   r   r   r   r   r   r   r   r   r    Zpandas.core.dtypes.dtypesr!   Zpandas.core.dtypes.missingr"   r#   r$   Zpandas.core.constructionr%   rw   r-   r.   r1   r2   r`   ro   rq   r   r   r   r   r   r   rn   r   r   r   r{   r   r}   r   r   r6   r   r   r   r   r   r   ZnanminZnanmaxr   r   r  r  r|   r   r   r   r  r   r  r  r  r   r&  gtZnangtgeZnangeltZnanltleZnanleeqZnaneqneZnanner+  r/   r/   r/   r0   <module>   s
  $	@ 8   /   Y)"%1.". ?J 
/&C1--V_ +
. '	  





