B
    W0dK                 @  s  U d Z ddlmZ ddlZddlmZmZmZmZm	Z	m
Z
 ddlZddlm  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 ddlmZ dd	lm Z m!Z! dd
l"m#Z#m$Z$m%Z%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>  m?Z? erlddlm@Z@ ddlAmBZB i ZCdeDd< dddddZEe	dddZFG dd de2ZGG dd dZHG d d! d!eIZJG d"d# d#eIZKG d$d% d%ee ZLG d&d de8ZMdS )'z.
Base and utility classes for pandas objects.
    )annotationsN)TYPE_CHECKINGAnyGenericHashableTypeVarcast)	ArrayLikeDtypeDtypeObjFrameOrSeries
IndexLabelShapefinal)PYPY)function)AbstractMethodError)cache_readonlydoc)is_categorical_dtypeis_dict_likeis_extension_array_dtypeis_object_dtype	is_scalar)ABCDataFrameABCIndex	ABCSeries)isnaremove_na_arraylike)
algorithms)DirNamesMixin)
duplicatedunique1dvalue_counts)OpsMixin)ExtensionArray)!create_series_with_explicit_dtype)Literal)Categoricalzdict[str, str]_shared_docsIndexOpsMixin )klassZinplaceuniquer!   _T)boundc                  s\   e Zd ZU dZded< edd Zdddd	ZddddddZdd fddZ	  Z
S )PandasObjectz/
    Baseclass for various pandas objects.
    zdict[str, Any]_cachec             C  s   t | S )zJ
        Class constructor (for this class it's just `__class__`.
        )type)self r4   B/var/www/html/venv/lib/python3.7/site-packages/pandas/core/base.py_constructorZ   s    zPandasObject._constructorstr)returnc             C  s
   t | S )zI
        Return a string representation for a particular object.
        )object__repr__)r3   r4   r4   r5   r:   a   s    zPandasObject.__repr__Nz
str | NoneNone)keyr8   c             C  s4   t | dsdS |dkr"| j  n| j|d dS )zV
        Reset cached properties. If ``key`` is passed, only clears that key.
        r1   N)hasattrr1   clearpop)r3   r<   r4   r4   r5   _reset_cacheh   s
    
zPandasObject._reset_cacheintc               s<   t | dd}|r2|dd}tt|r(|n| S t  S )zx
        Generates the total memory usage for an object that returns
        either a value or Series of values
        memory_usageNT)deep)getattrrA   r   sumsuper
__sizeof__)r3   rB   Zmem)	__class__r4   r5   rG   s   s
    
zPandasObject.__sizeof__)N)__name__
__module____qualname____doc____annotations__propertyr6   r:   r@   rG   __classcell__r4   r4   )rH   r5   r0   R   s   
r0   c               @  s&   e Zd ZdZdd ZddddZdS )	NoNewAttributesMixina  
    Mixin which prevents adding new attributes.

    Prevents additional attributes via xxx.attribute = "something" after a
    call to `self.__freeze()`. Mainly used to prevent the user from using
    wrong attributes on an accessor (`Series.cat/.str/.dt`).

    If you really want to add a new attribute at a later time, you need to use
    `object.__setattr__(self, key, value)`.
    c             C  s   t | dd dS )z9
        Prevents setting additional attributes.
        __frozenTN)r9   __setattr__)r3   r4   r4   r5   _freeze   s    zNoNewAttributesMixin._freezer7   )r<   c             C  sT   t | ddrB|dksB|t| jksBt | |d d k	sBtd| dt| || d S )NrQ   Fr1   z"You cannot add any new attribute '')rD   r2   __dict__AttributeErrorr9   rR   )r3   r<   valuer4   r4   r5   rR      s    z NoNewAttributesMixin.__setattr__N)rI   rJ   rK   rL   rS   rR   r4   r4   r4   r5   rP      s   
rP   c               @  s   e Zd ZdS )	DataErrorN)rI   rJ   rK   r4   r4   r4   r5   rX      s   rX   c               @  s   e Zd ZdS )SpecificationErrorN)rI   rJ   rK   r4   r4   r4   r5   rY      s   rY   c               @  s   e Zd ZU dZded< dZded< ded< d	d
gZeeZe	e
dd Zedd Ze	eddddZe	edd Zdd ZdddddZdd ZeZdS )SelectionMixinz
    mixin implementing the selection & aggregation interface on a group-like
    object sub-classes need to define: obj, exclusions
    r   objNzIndexLabel | None
_selectionzfrozenset[Hashable]
exclusionsr1   __setstate__c             C  s&   t | jtttttjfs | jgS | jS )N)
isinstancer\   listtupler   r   npndarray)r3   r4   r4   r5   _selection_list   s    zSelectionMixin._selection_listc             C  s,   | j d kst| jtr| jS | j| j  S d S )N)r\   r_   r[   r   )r3   r4   r4   r5   _selected_obj   s    zSelectionMixin._selected_objrA   )r8   c             C  s   | j jS )N)re   ndim)r3   r4   r4   r5   rf      s    zSelectionMixin.ndimc             C  sL   | j d k	r"t| jtr"| j| j S t| jdkrB| jj| jddS | jS d S )Nr      )axis)r\   r_   r[   r   rd   lenr]   Zdrop)r3   r4   r4   r5   _obj_with_exclusions   s
    z#SelectionMixin._obj_with_exclusionsc             C  s   | j d k	rtd| j  dt|tttttjfrt	| j
j|t	|kr|tt|| j
j}tdt|dd  | jt|ddS t| dd	s|| j
jkrtd
| | j|ddS || j
krtd
| | j
| }|j}| j|||dS d S )Nz
Column(s) z already selectedzColumns not found: rg      )rf   Zas_indexFzColumn not found: )rf   subset)r\   
IndexErrorr_   r`   ra   r   r   rb   rc   ri   r[   columnsintersectionset
differenceKeyErrorr7   _gotitemrD   rf   )r3   r<   bad_keysrm   rf   r4   r4   r5   __getitem__   s     


zSelectionMixin.__getitem__)rf   c             C  s   t | dS )a  
        sub-classes to define
        return a sliced object

        Parameters
        ----------
        key : str / list of selections
        ndim : {1, 2}
            requested ndim of result
        subset : object, default None
            subset to act on
        N)r   )r3   r<   rf   rm   r4   r4   r5   rt      s    zSelectionMixin._gotitemc             O  s   t | d S )N)r   )r3   funcargskwargsr4   r4   r5   	aggregate   s    zSelectionMixin.aggregate)N)rI   rJ   rK   rL   rM   r\   Z_internal_namesrq   Z_internal_names_setr   rN   rd   r   re   rf   rj   rv   rt   rz   Zaggr4   r4   r4   r5   rZ      s"   

rZ   c               @  s  e Zd ZU dZdZedgZded< edddd	Z	ed
dddZ
dddddZeeddZeddddZddddZeddddZdd ZeddddZedddd Zed!dd"d#Zd$d%ejfd&d'd(d)d*d+Zed'dd,d-Zdwd'd/d0d1Zed2d3d4d5dxd'dd6d7d8Zdyd'd/d9d:Zeed3d2d;d5dzddd<d=Zd>d? ZeZd@dA Ze d'ddBdCZ!dDdE Z"dFd.d$d$dGdHdIdJdKZ#d{dLdMZ$d|d'd'd'd'dNdOdPZ%dQdR Z&d}d'ddSdTdUZ'ed'ddVdWZ(ed'ddXdYZ)ed'ddZd[Z*ed'dd\d]Z+d~d'dd^d_d`Z,ee-j.dadadae/0dbdcdd'dedfdgdhZ.die1dj< ee1dj dkdldd(ddndoZ2ddqdrZ3e4ddsd(dtdudvZ5d$S )r*   zS
    Common ops mixin to support a unified interface / docs for Series / Index
    i  tolistzfrozenset[str]_hidden_attrsr   )r8   c             C  s   t | d S )N)r   )r3   r4   r4   r5   dtype  s    zIndexOpsMixin.dtypezExtensionArray | np.ndarrayc             C  s   t | d S )N)r   )r3   r4   r4   r5   _values  s    zIndexOpsMixin._valuesr.   )r3   r8   c             O  s   t || | S )zw
        Return the transpose, which is by definition self.

        Returns
        -------
        %(klass)s
        )nvZvalidate_transpose)r3   rx   ry   r4   r4   r5   	transpose  s    zIndexOpsMixin.transposezD
        Return the transpose, which is by definition self.
        )r   r   c             C  s   | j jS )zE
        Return a tuple of the shape of the underlying data.
        )r~   shape)r3   r4   r4   r5   r   )  s    zIndexOpsMixin.shaperA   c             C  s   t | d S )N)r   )r3   r4   r4   r5   __len__0  s    zIndexOpsMixin.__len__c             C  s   dS )zO
        Number of dimensions of the underlying data, by definition 1.
        rg   r4   )r3   r4   r4   r5   rf   4  s    zIndexOpsMixin.ndimc             C  s$   t | dkrtt| S tddS )a  
        Return the first element of the underlying data as a Python scalar.

        Returns
        -------
        scalar
            The first element of %(klass)s.

        Raises
        ------
        ValueError
            If the data is not length-1.
        rg   z6can only convert an array of size 1 to a Python scalarN)ri   nextiter
ValueError)r3   r4   r4   r5   item;  s    zIndexOpsMixin.itemc             C  s   | j jS )zD
        Return the number of bytes in the underlying data.
        )r~   nbytes)r3   r4   r4   r5   r   M  s    zIndexOpsMixin.nbytesc             C  s
   t | jS )zG
        Return the number of elements in the underlying data.
        )ri   r~   )r3   r4   r4   r5   sizeT  s    zIndexOpsMixin.sizer%   c             C  s   t | dS )aM  
        The ExtensionArray of the data backing this Series or Index.

        Returns
        -------
        ExtensionArray
            An ExtensionArray of the values stored within. For extension
            types, this is the actual array. For NumPy native types, this
            is a thin (no copy) wrapper around :class:`numpy.ndarray`.

            ``.array`` differs ``.values`` which may require converting the
            data to a different form.

        See Also
        --------
        Index.to_numpy : Similar method that always returns a NumPy array.
        Series.to_numpy : Similar method that always returns a NumPy array.

        Notes
        -----
        This table lays out the different array types for each extension
        dtype within pandas.

        ================== =============================
        dtype              array type
        ================== =============================
        category           Categorical
        period             PeriodArray
        interval           IntervalArray
        IntegerNA          IntegerArray
        string             StringArray
        boolean            BooleanArray
        datetime64[ns, tz] DatetimeArray
        ================== =============================

        For any 3rd-party extension types, the array type will be an
        ExtensionArray.

        For all remaining dtypes ``.array`` will be a
        :class:`arrays.NumpyExtensionArray` wrapping the actual ndarray
        stored within. If you absolutely need a NumPy array (possibly with
        copying / coercing data), then use :meth:`Series.to_numpy` instead.

        Examples
        --------
        For regular NumPy types like int, and float, a PandasArray
        is returned.

        >>> pd.Series([1, 2, 3]).array
        <PandasArray>
        [1, 2, 3]
        Length: 3, dtype: int64

        For extension types, like Categorical, the actual ExtensionArray
        is returned

        >>> ser = pd.Series(pd.Categorical(['a', 'b', 'a']))
        >>> ser.array
        ['a', 'b', 'a']
        Categories (2, object): ['a', 'b']
        N)r   )r3   r4   r4   r5   array[  s    ?zIndexOpsMixin.arrayNFzDtype | Noneboolz
np.ndarray)r}   copyr8   c             K  s   t | jr$| jj|f||d|S |rHt| d }td| dtj| j	|d}|sf|t
jk	r| }|t
jk	r|||  < |S )a  
        A NumPy ndarray representing the values in this Series or Index.

        Parameters
        ----------
        dtype : str or numpy.dtype, optional
            The dtype to pass to :meth:`numpy.asarray`.
        copy : bool, default False
            Whether to ensure that the returned value is not a view on
            another array. Note that ``copy=False`` does not *ensure* that
            ``to_numpy()`` is no-copy. Rather, ``copy=True`` ensure that
            a copy is made, even if not strictly necessary.
        na_value : Any, optional
            The value to use for missing values. The default value depends
            on `dtype` and the type of the array.

            .. versionadded:: 1.0.0

        **kwargs
            Additional keywords passed through to the ``to_numpy`` method
            of the underlying array (for extension arrays).

            .. versionadded:: 1.0.0

        Returns
        -------
        numpy.ndarray

        See Also
        --------
        Series.array : Get the actual data stored within.
        Index.array : Get the actual data stored within.
        DataFrame.to_numpy : Similar method for DataFrame.

        Notes
        -----
        The returned array will be the same up to equality (values equal
        in `self` will be equal in the returned array; likewise for values
        that are not equal). When `self` contains an ExtensionArray, the
        dtype may be different. For example, for a category-dtype Series,
        ``to_numpy()`` will return a NumPy array and the categorical dtype
        will be lost.

        For NumPy dtypes, this will be a reference to the actual data stored
        in this Series or Index (assuming ``copy=False``). Modifying the result
        in place will modify the data stored in the Series or Index (not that
        we recommend doing that).

        For extension types, ``to_numpy()`` *may* require copying data and
        coercing the result to a NumPy type (possibly object), which may be
        expensive. When you need a no-copy reference to the underlying data,
        :attr:`Series.array` should be used instead.

        This table lays out the different dtypes and default return types of
        ``to_numpy()`` for various dtypes within pandas.

        ================== ================================
        dtype              array type
        ================== ================================
        category[T]        ndarray[T] (same dtype as input)
        period             ndarray[object] (Periods)
        interval           ndarray[object] (Intervals)
        IntegerNA          ndarray[object]
        datetime64[ns]     datetime64[ns]
        datetime64[ns, tz] ndarray[object] (Timestamps)
        ================== ================================

        Examples
        --------
        >>> ser = pd.Series(pd.Categorical(['a', 'b', 'a']))
        >>> ser.to_numpy()
        array(['a', 'b', 'a'], dtype=object)

        Specify the `dtype` to control how datetime-aware data is represented.
        Use ``dtype=object`` to return an ndarray of pandas :class:`Timestamp`
        objects, each with the correct ``tz``.

        >>> ser = pd.Series(pd.date_range('2000', periods=2, tz="CET"))
        >>> ser.to_numpy(dtype=object)
        array([Timestamp('2000-01-01 00:00:00+0100', tz='CET'),
               Timestamp('2000-01-02 00:00:00+0100', tz='CET')],
              dtype=object)

        Or ``dtype='datetime64[ns]'`` to return an ndarray of native
        datetime64 values. The values are converted to UTC and the timezone
        info is dropped.

        >>> ser.to_numpy(dtype="datetime64[ns]")
        ... # doctest: +ELLIPSIS
        array(['1999-12-31T23:00:00.000000000', '2000-01-01T23:00:00...'],
              dtype='datetime64[ns]')
        )r   na_valuer   z/to_numpy() got an unexpected keyword argument 'rT   )r}   )r   r}   r   to_numpyr`   keys	TypeErrorrb   asarrayr~   lib
no_defaultr   r   )r3   r}   r   r   ry   ru   resultr4   r4   r5   r     s    c

zIndexOpsMixin.to_numpyc             C  s   | j  S )N)r   )r3   r4   r4   r5   empty  s    zIndexOpsMixin.emptyT)skipnac             O  s&   t | t || tj| j|dS )a  
        Return the maximum value of the Index.

        Parameters
        ----------
        axis : int, optional
            For compatibility with NumPy. Only 0 or None are allowed.
        skipna : bool, default True
            Exclude NA/null values when showing the result.
        *args, **kwargs
            Additional arguments and keywords for compatibility with NumPy.

        Returns
        -------
        scalar
            Maximum value.

        See Also
        --------
        Index.min : Return the minimum value in an Index.
        Series.max : Return the maximum value in a Series.
        DataFrame.max : Return the maximum values in a DataFrame.

        Examples
        --------
        >>> idx = pd.Index([3, 2, 1])
        >>> idx.max()
        3

        >>> idx = pd.Index(['c', 'b', 'a'])
        >>> idx.max()
        'c'

        For a MultiIndex, the maximum is determined lexicographically.

        >>> idx = pd.MultiIndex.from_product([('a', 'b'), (2, 1)])
        >>> idx.max()
        ('b', 2)
        )r   )r   validate_minmax_axisZvalidate_maxnanopsZnanmaxr~   )r3   rh   r   rx   ry   r4   r4   r5   max  s    (
zIndexOpsMixin.maxr   minlargest)opZopposerW   )r   r8   c             O  sX   | j }t| t|||}t|trF|s<|  r<dS | S nt	j
||dS dS )aS  
        Return int position of the {value} value in the Series.

        If the {op}imum is achieved in multiple locations,
        the first row position is returned.

        Parameters
        ----------
        axis : {{None}}
            Dummy argument for consistency with Series.
        skipna : bool, default True
            Exclude NA/null values when showing the result.
        *args, **kwargs
            Additional arguments and keywords for compatibility with NumPy.

        Returns
        -------
        int
            Row position of the {op}imum value.

        See Also
        --------
        Series.arg{op} : Return position of the {op}imum value.
        Series.arg{oppose} : Return position of the {oppose}imum value.
        numpy.ndarray.arg{op} : Equivalent method for numpy arrays.
        Series.idxmax : Return index label of the maximum values.
        Series.idxmin : Return index label of the minimum values.

        Examples
        --------
        Consider dataset containing cereal calories

        >>> s = pd.Series({{'Corn Flakes': 100.0, 'Almond Delight': 110.0,
        ...                'Cinnamon Toast Crunch': 120.0, 'Cocoa Puff': 110.0}})
        >>> s
        Corn Flakes              100.0
        Almond Delight           110.0
        Cinnamon Toast Crunch    120.0
        Cocoa Puff               110.0
        dtype: float64

        >>> s.argmax()
        2
        >>> s.argmin()
        0

        The maximum cereal calories is the third element and
        the minimum cereal calories is the first element,
        since series is zero-indexed.
        rk   )r   N)r~   r   r   Zvalidate_argmax_with_skipnar_   r%   r   anyargmaxr   Z	nanargmax)r3   rh   r   rx   ry   delegater4   r4   r5   r   G  s    4


zIndexOpsMixin.argmaxc             O  s&   t | t || tj| j|dS )a  
        Return the minimum value of the Index.

        Parameters
        ----------
        axis : {None}
            Dummy argument for consistency with Series.
        skipna : bool, default True
            Exclude NA/null values when showing the result.
        *args, **kwargs
            Additional arguments and keywords for compatibility with NumPy.

        Returns
        -------
        scalar
            Minimum value.

        See Also
        --------
        Index.max : Return the maximum value of the object.
        Series.min : Return the minimum value in a Series.
        DataFrame.min : Return the minimum values in a DataFrame.

        Examples
        --------
        >>> idx = pd.Index([3, 2, 1])
        >>> idx.min()
        1

        >>> idx = pd.Index(['c', 'b', 'a'])
        >>> idx.min()
        'a'

        For a MultiIndex, the minimum is determined lexicographically.

        >>> idx = pd.MultiIndex.from_product([('a', 'b'), (2, 1)])
        >>> idx.min()
        ('a', 1)
        )r   )r   r   Zvalidate_minr   Znanminr~   )r3   rh   r   rx   ry   r4   r4   r5   r     s    (
zIndexOpsMixin.minsmallestc             O  sX   | j }t| t|||}t|trF|s<|  r<dS | S nt	j
||dS d S )Nrk   )r   )r~   r   r   Zvalidate_argmin_with_skipnar_   r%   r   r   argminr   Z	nanargmin)r3   rh   r   rx   ry   r   r4   r4   r5   r     s    


zIndexOpsMixin.argminc             C  s"   t | jtjst| jS | j S )a  
        Return a list of the values.

        These are each a scalar type, which is a Python scalar
        (for str, int, float) or a pandas scalar
        (for Timestamp/Timedelta/Interval/Period)

        Returns
        -------
        list

        See Also
        --------
        numpy.ndarray.tolist : Return the array as an a.ndim-levels deep
            nested list of Python scalars.
        )r_   r~   rb   rc   r`   r{   )r3   r4   r4   r5   r{     s    
zIndexOpsMixin.tolistc             C  s2   t | jtjst| jS t| jjt| jjS dS )a  
        Return an iterator of the values.

        These are each a scalar type, which is a Python scalar
        (for str, int, float) or a pandas scalar
        (for Timestamp/Timedelta/Interval/Period)

        Returns
        -------
        iterator
        N)	r_   r~   rb   rc   r   mapr   ranger   )r3   r4   r4   r5   __iter__  s    
zIndexOpsMixin.__iter__c             C  s   t t|  S )zK
        Return if I have any nans; enables various perf speedups.
        )r   r   r   )r3   r4   r4   r5   hasnans  s    zIndexOpsMixin.hasnansc             C  s
   t | jS )N)r   r~   )r3   r4   r4   r5   r     s    zIndexOpsMixin.isnar   )rh   r   numeric_onlyfilter_typer7   )namec      	      K  s>   t | |d}|dkr,tt| j d| |f d|i|S )zA
        Perform the reduction type operation if we can.
        Nz cannot perform the operation r   )rD   r   r2   rI   )	r3   r   r   rh   r   r   r   kwdsrw   r4   r4   r5   _reduce  s
    zIndexOpsMixin._reducec       	        s  t |r<t|tr.t|dr.|  fdd}nt|tjd}t|trt| j	rft
d| j}||S | j}|j|}t|j|}|S t| j	rt| jdr| j}|dk	rtdd }nB| jt}|d	krd
d }n$|dkrtj}nd| d}t||||}|S )a  
        An internal function that maps values using the input
        correspondence (which can be a dict, Series, or function).

        Parameters
        ----------
        mapper : function, dict, or Series
            The input correspondence object
        na_action : {None, 'ignore'}
            If 'ignore', propagate NA values, without passing them to the
            mapping function

        Returns
        -------
        Union[Index, MultiIndex], inferred
            The output of the mapping function applied to the index.
            If the function returns a tuple with more than one element
            a MultiIndex will be returned.
        __missing__c               s    |  S )Nr4   )x)dict_with_defaultr4   r5   <lambda>/      z+IndexOpsMixin._map_values.<locals>.<lambda>)Zdtype_if_emptyr(   r   Nc             S  s
   |  |S )N)r   )valuesfr4   r4   r5   r   U  r   ignorec             S  s   t | |t| tjS )N)r   Zmap_infer_maskr   viewrb   Zuint8)r   r   r4   r4   r5   r   Y  s   z+na_action must either be 'ignore' or None, z was passed)r   r_   dictr=   r&   rb   Zfloat64r   r   r}   r   r~   r   indexZget_indexerr   Ztake_ndr   NotImplementedErrorZastyper9   r   Z	map_inferr   )	r3   ZmapperZ	na_actioncatr   Zindexer
new_valuesZmap_fmsgr4   )r   r5   _map_values  s8    





zIndexOpsMixin._map_values)	normalizesort	ascendingdropnac             C  s   t | |||||dS )a  
        Return a Series containing counts of unique values.

        The resulting object will be in descending order so that the
        first element is the most frequently-occurring element.
        Excludes NA values by default.

        Parameters
        ----------
        normalize : bool, default False
            If True then the object returned will contain the relative
            frequencies of the unique values.
        sort : bool, default True
            Sort by frequencies.
        ascending : bool, default False
            Sort in ascending order.
        bins : int, optional
            Rather than count values, group them into half-open bins,
            a convenience for ``pd.cut``, only works with numeric data.
        dropna : bool, default True
            Don't include counts of NaN.

        Returns
        -------
        Series

        See Also
        --------
        Series.count: Number of non-NA elements in a Series.
        DataFrame.count: Number of non-NA elements in a DataFrame.
        DataFrame.value_counts: Equivalent method on DataFrames.

        Examples
        --------
        >>> index = pd.Index([3, 1, 2, 3, 4, np.nan])
        >>> index.value_counts()
        3.0    2
        1.0    1
        2.0    1
        4.0    1
        dtype: int64

        With `normalize` set to `True`, returns the relative frequency by
        dividing all values by the sum of values.

        >>> s = pd.Series([3, 1, 2, 3, 4, np.nan])
        >>> s.value_counts(normalize=True)
        3.0    0.4
        1.0    0.2
        2.0    0.2
        4.0    0.2
        dtype: float64

        **bins**

        Bins can be useful for going from a continuous variable to a
        categorical variable; instead of counting unique
        apparitions of values, divide the index in the specified
        number of half-open bins.

        >>> s.value_counts(bins=3)
        (0.996, 2.0]    2
        (2.0, 3.0]      2
        (3.0, 4.0]      1
        dtype: int64

        **dropna**

        With `dropna` set to `False` we can also see NaN index values.

        >>> s.value_counts(dropna=False)
        3.0    2
        1.0    1
        2.0    1
        4.0    1
        NaN    1
        dtype: int64
        )r   r   r   binsr   )r#   )r3   r   r   r   r   r   r4   r4   r5   r#   j  s    VzIndexOpsMixin.value_countsc             C  sZ   | j }t|tjsN| }| jjdkrVt| trVt| jdd d krVt	|}nt
|}|S )N)mMtz)r~   r_   rb   rc   r-   r}   kindr   rD   r   r"   )r3   r   r   r4   r4   r5   r-     s    zIndexOpsMixin.unique)r   r8   c             C  s   |   }|rt|}t|S )a  
        Return number of unique elements in the object.

        Excludes NA values by default.

        Parameters
        ----------
        dropna : bool, default True
            Don't include NaN in the count.

        Returns
        -------
        int

        See Also
        --------
        DataFrame.nunique: Method nunique for DataFrame.
        Series.count: Count non-NA/null observations in the Series.

        Examples
        --------
        >>> s = pd.Series([1, 3, 5, 7, 7])
        >>> s
        0    1
        1    3
        2    5
        3    7
        4    7
        dtype: int64

        >>> s.nunique()
        4
        )r-   r   ri   )r3   r   Zuniqsr4   r4   r5   nunique  s    "zIndexOpsMixin.nuniquec             C  s   | j ddt| kS )zr
        Return boolean if values in the object are unique.

        Returns
        -------
        bool
        F)r   )r   ri   )r3   r4   r4   r5   	is_unique  s    	zIndexOpsMixin.is_uniquec             C  s   ddl m} || jS )z
        Return boolean if values in the object are
        monotonic_increasing.

        Returns
        -------
        bool
        r   )Index)pandasr   is_monotonic)r3   r   r4   r4   r5   r   	  s    
zIndexOpsMixin.is_monotonicc             C  s   | j S )z)
        Alias for is_monotonic.
        )r   )r3   r4   r4   r5   is_monotonic_increasing  s    z%IndexOpsMixin.is_monotonic_increasingc             C  s   ddl m} || jS )z
        Return boolean if values in the object are
        monotonic_decreasing.

        Returns
        -------
        bool
        r   )r   )r   r   is_monotonic_decreasing)r3   r   r4   r4   r5   r     s    
z%IndexOpsMixin.is_monotonic_decreasing)rC   r8   c             C  sR   t | jdr| jj|dS | jj}|rNt| rNtsNttj| j	}|t
|7 }|S )aN  
        Memory usage of the values.

        Parameters
        ----------
        deep : bool, default False
            Introspect the data deeply, interrogate
            `object` dtypes for system-level memory consumption.

        Returns
        -------
        bytes used

        See Also
        --------
        numpy.ndarray.nbytes : Total bytes consumed by the elements of the
            array.

        Notes
        -----
        Memory usage does not include memory consumed by elements that
        are not components of the array if deep=False or if used on PyPy
        rB   )rC   )r=   r   rB   r   r   r   r   rb   rc   r~   r   Zmemory_usage_of_objects)r3   rC   vr   r4   r4   r5   _memory_usage-  s    zIndexOpsMixin._memory_usager+   z            sort : bool, default False
                Sort `uniques` and shuffle `codes` to maintain the
                relationship.
            )r   orderZ	size_hintr   rk   z
int | None)r   na_sentinelc             C  s   t j| ||dS )N)r   r   )r   	factorize)r3   r   r   r4   r4   r5   r   O  s    zIndexOpsMixin.factorizea
  
        Find indices where elements should be inserted to maintain order.

        Find the indices into a sorted {klass} `self` such that, if the
        corresponding elements in `value` were inserted before the indices,
        the order of `self` would be preserved.

        .. note::

            The {klass} *must* be monotonically sorted, otherwise
            wrong locations will likely be returned. Pandas does *not*
            check this for you.

        Parameters
        ----------
        value : array-like
            Values to insert into `self`.
        side : {{'left', 'right'}}, optional
            If 'left', the index of the first suitable location found is given.
            If 'right', return the last such index.  If there is no suitable
            index, return either 0 or N (where N is the length of `self`).
        sorter : 1-D array-like, optional
            Optional array of integer indices that sort `self` into ascending
            order. They are typically the result of ``np.argsort``.

        Returns
        -------
        int or array of int
            A scalar or array of insertion points with the
            same shape as `value`.

        See Also
        --------
        sort_values : Sort by the values along either axis.
        numpy.searchsorted : Similar method from NumPy.

        Notes
        -----
        Binary search is used to find the required insertion points.

        Examples
        --------
        >>> ser = pd.Series([1, 2, 3])
        >>> ser
        0    1
        1    2
        2    3
        dtype: int64

        >>> ser.searchsorted(4)
        3

        >>> ser.searchsorted([0, 4])
        array([0, 3])

        >>> ser.searchsorted([1, 3], side='left')
        array([0, 2])

        >>> ser.searchsorted([1, 3], side='right')
        array([1, 3])

        >>> ser = pd.Series(pd.to_datetime(['3/11/2000', '3/12/2000', '3/13/2000']))
        >>> ser
        0   2000-03-11
        1   2000-03-12
        2   2000-03-13
        dtype: datetime64[ns]

        >>> ser.searchsorted('3/14/2000')
        3

        >>> ser = pd.Categorical(
        ...     ['apple', 'bread', 'bread', 'cheese', 'milk'], ordered=True
        ... )
        >>> ser
        ['apple', 'bread', 'bread', 'cheese', 'milk']
        Categories (4, object): ['apple' < 'bread' < 'cheese' < 'milk']

        >>> ser.searchsorted('bread')
        1

        >>> ser.searchsorted(['bread'], side='right')
        array([3])

        If the values are not monotonically sorted, wrong locations
        may be returned:

        >>> ser = pd.Series([2, 1, 3])
        >>> ser
        0    2
        1    1
        2    3
        dtype: int64

        >>> ser.searchsorted(1)  # doctest: +SKIP
        0  # wrong result, correct would be 1
        searchsortedr   )r,   leftc             C  s   t j| j|||dS )N)sidesorter)r   r   r~   )r3   rW   r   r   r4   r4   r5   r     s    zIndexOpsMixin.searchsortedfirstc             C  s   | j |d}| |  S )N)keep)_duplicated)r3   r   r!   r4   r4   r5   drop_duplicates  s    zIndexOpsMixin.drop_duplicatesz!Literal[('first', 'last', False)])r   r8   c             C  s   t | j|dS )N)r   )r!   r~   )r3   r   r4   r4   r5   r     s    zIndexOpsMixin._duplicated)NT)NT)NT)NT)N)FTFNT)T)F)Frk   )r   N)r   )r   )6rI   rJ   rK   rL   Z__array_priority__	frozensetr|   rM   rN   r}   r~   r   Tr   r   rf   r   r   r   r   r   r   r   r   r   r   r   r   r   r{   Zto_listr   r   r   r   r   r   r#   r-   r   r   r   r   r   r   r   r   textwrapdedentr)   r   r   r   r   r4   r4   r4   r5   r*     s~   
Cw,C,
Y    Y'"e
)NrL   
__future__r   r   typingr   r   r   r   r   r   numpyrb   Zpandas._libs.libZ_libsr   Zpandas._typingr	   r
   r   r   r   r   r   Zpandas.compatr   Zpandas.compat.numpyr   r   Zpandas.errorsr   Zpandas.util._decoratorsr   r   Zpandas.core.dtypes.commonr   r   r   r   r   Zpandas.core.dtypes.genericr   r   r   Zpandas.core.dtypes.missingr   r   Zpandas.corer   Zpandas.core.accessorr    Zpandas.core.algorithmsr!   r"   r#   Zpandas.core.arrayliker$   Zpandas.core.arraysr%   Zpandas.core.constructionr&   Zpandas.core.nanopscorer   r'   r   r(   r)   rM   Z_indexops_doc_kwargsr.   r0   rP   	ExceptionrX   rY   rZ   r*   r4   r4   r4   r5   <module>   sF    	$	/"W