a
    Of                     @  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
mZ ddlZddl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 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& ddl'm(Z( ddl)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6m7Z7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@mAZA erddlBmCZCmDZD ddlmEZEmFZFmGZGmHZH ddlImJZJmKZKmLZL i ZMdeNd< dddddZOG dd  d e:ZPG d!d" d"ZQG d#d$ d$ee ZRG d%d de<ZSdS )&z.
Base and utility classes for pandas objects.
    )annotationsN)TYPE_CHECKINGAnyGenericLiteralcastfinaloverload)using_copy_on_write)lib)AxisIntDtypeObj
IndexLabelNDFrameTSelfShapenpt)PYPY)functionAbstractMethodError)cache_readonlydoc)find_stack_level)can_hold_element)is_object_dtype	is_scalar)ExtensionDtype)ABCDataFrameABCIndex	ABCSeries)isnaremove_na_arraylike)
algorithmsnanopsops)DirNamesMixin)OpsMixin)ExtensionArray)ensure_wrapped_if_datetimelikeextract_array)HashableIterator)DropKeepNumpySorterNumpyValueArrayLikeScalarLike_co)	DataFrameIndexSerieszdict[str, str]_shared_docsIndexOpsMixin )klassZinplaceunique
duplicatedc                      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 )zK
        Class constructor (for this class it's just `__class__`).
        )typeself r?   I/var/www/ai-form-bot/venv/lib/python3.9/site-packages/pandas/core/base.py_constructorl   s    zPandasObject._constructorstrreturnc                 C  s
   t | S )zI
        Return a string representation for a particular object.
        )object__repr__r=   r?   r?   r@   rF   s   s    zPandasObject.__repr__Nz
str | NoneNonekeyrD   c                 C  s4   t | dsdS |du r"| j  n| j|d dS )zV
        Reset cached properties. If ``key`` is passed, only clears that key.
        r;   N)hasattrr;   clearpop)r>   rI   r?   r?   r@   _reset_cachez   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)getattrrN   r   sumsuper
__sizeof__)r>   rO   Zmem	__class__r?   r@   rU      s
    
zPandasObject.__sizeof__)N)__name__
__module____qualname____doc____annotations__propertyrA   rF   rM   rU   __classcell__r?   r?   rV   r@   r:   d   s   

r:   c                   @  s.   e Zd ZdZddddZd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)`.
    rG   rC   c                 C  s   t | dd dS )z9
        Prevents setting additional attributes.
        __frozenTN)rE   __setattr__r=   r?   r?   r@   _freeze   s    zNoNewAttributesMixin._freezerB   rH   c                 C  sT   t | ddrB|dksB|t| jv sBt | |d d usBtd| dt| || d S )Nr`   Fr;   z"You cannot add any new attribute '')rR   r<   __dict__AttributeErrorrE   ra   )r>   rI   valuer?   r?   r@   ra      s    z NoNewAttributesMixin.__setattr__N)rX   rY   rZ   r[   rb   ra   r?   r?   r?   r@   r_      s   r_   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e	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]
exclusionsr;   __setstate__c                 C  s&   t | jtttttjfs | jgS | jS N)
isinstanceri   listtupler    r   npndarrayr=   r?   r?   r@   _selection_list   s
    zSelectionMixin._selection_listc                 C  s,   | j d u st| jtr| jS | j| j  S d S rl   )ri   rm   rh   r    r=   r?   r?   r@   _selected_obj   s    zSelectionMixin._selected_objrN   rC   c                 C  s   | j jS rl   )rs   ndimr=   r?   r?   r@   rt      s    zSelectionMixin.ndimc                 C  sV   t | jtr| jS | jd ur*| j| jS t| jdkrL| jj| jdddS | jS d S )Nr      T)axisZ
only_slice)	rm   rh   r    ri   Z_getitem_nocopyrr   lenrj   Z
_drop_axisr=   r?   r?   r@   _obj_with_exclusions   s    
z#SelectionMixin._obj_with_exclusionsc                 C  s   | j d urtd| j  dt|tttttjfrt	| j
j|t	t|krtt|| j
j}tdt|dd  | jt|ddS || j
vrtd| | j
| j}| j||dS d S )	Nz
Column(s) z already selectedzColumns not found: ru      rt   zColumn not found: )ri   
IndexErrorrm   rn   ro   r    r   rp   rq   rw   rh   columnsintersectionset
differenceKeyErrorrB   _gotitemrt   )r>   rI   bad_keysrt   r?   r?   r@   __getitem__   s    

zSelectionMixin.__getitem__r{   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
        Nr   )r>   rI   rt   subsetr?   r?   r@   r      s    zSelectionMixin._gotitemzSeries | DataFrame)r   c                 C  sV   d}|j dkr0t|r ||v s*t|r0|}n"|j dkrRt|rR||jkrR|}|S )zO
        Infer the `selection` to pass to our constructor in _gotitem.
        Nrz   ru   )rt   r   r   Zis_list_likename)r>   rI   r   Z	selectionr?   r?   r@   _infer_selection  s    
zSelectionMixin._infer_selectionc                 O  s   t | d S rl   r   )r>   funcargskwargsr?   r?   r@   	aggregate  s    zSelectionMixin.aggregate)N)rX   rY   rZ   r[   r\   ri   Z_internal_namesr   Z_internal_names_setr   r]   rr   r   rs   rt   rx   r   r   r   r   Zaggr?   r?   r?   r@   rg      s.   

rg   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
e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edd ZeddddZedddd Zed!dd"d#Zed$d%ejfd&d'd(d)d*d+d,Zeed'dd-d.Zed/d0d1d2dd4d'dd5d6d7Zeed0d/d8d2dd4d'dd5d9d:Zd;d< ZeZd=dd>d?Zed'dd@dAZ edd'dBdCdDZ!edd'd'd'd'dEdFdGdHZ"dIdJ Z#edd'ddKdLdMZ$ed'ddNdOZ%ed'ddPdQZ&ed'ddRdSZ'edd'ddTdUdVZ(ee)j*dWdWdWe+,dXdYdd'd'dZd[d\d]Z*d^e-d_< e.ddadbdcdddedfdgZ/e.ddhdbdcdidedjdgZ/ee-d_ dkdlddndbdodpdedqdgZ/drdsdtdsdudvZ0eddtdwdxdydzZ1d{d| Z2d}d~ Z3d$S )r5   zS
    Common ops mixin to support a unified interface / docs for Series / Index
    i  tolistzfrozenset[str]_hidden_attrsr   rC   c                 C  s   t | d S rl   r   r=   r?   r?   r@   dtype'  s    zIndexOpsMixin.dtypezExtensionArray | np.ndarrayc                 C  s   t | d S rl   r   r=   r?   r?   r@   _values,  s    zIndexOpsMixin._valuesr   c                 O  s   t || | S )zw
        Return the transpose, which is by definition self.

        Returns
        -------
        %(klass)s
        )nvZvalidate_transpose)r>   r   r   r?   r?   r@   	transpose1  s    	zIndexOpsMixin.transposea  
        Return the transpose, which is by definition self.

        Examples
        --------
        For Series:

        >>> s = pd.Series(['Ant', 'Bear', 'Cow'])
        >>> s
        0     Ant
        1    Bear
        2     Cow
        dtype: object
        >>> s.T
        0     Ant
        1    Bear
        2     Cow
        dtype: object

        For Index:

        >>> idx = pd.Index([1, 2, 3])
        >>> idx.T
        Index([1, 2, 3], dtype='int64')
        )r   r   c                 C  s   | j jS )z
        Return a tuple of the shape of the underlying data.

        Examples
        --------
        >>> s = pd.Series([1, 2, 3])
        >>> s.shape
        (3,)
        )r   shaper=   r?   r?   r@   r   Z  s    zIndexOpsMixin.shaperN   c                 C  s   t | d S rl   r   r=   r?   r?   r@   __len__g  s    zIndexOpsMixin.__len__z
Literal[1]c                 C  s   dS )a  
        Number of dimensions of the underlying data, by definition 1.

        Examples
        --------
        >>> s = pd.Series(['Ant', 'Bear', 'Cow'])
        >>> s
        0     Ant
        1    Bear
        2     Cow
        dtype: object
        >>> s.ndim
        1

        For Index:

        >>> idx = pd.Index([1, 2, 3])
        >>> idx
        Index([1, 2, 3], dtype='int64')
        >>> idx.ndim
        1
        ru   r?   r=   r?   r?   r@   rt   k  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 Series or Index.

        Raises
        ------
        ValueError
            If the data is not length = 1.

        Examples
        --------
        >>> s = pd.Series([1])
        >>> s.item()
        1

        For an index:

        >>> s = pd.Series([1], index=['a'])
        >>> s.index.item()
        'a'
        ru   z6can only convert an array of size 1 to a Python scalarN)rw   nextiter
ValueErrorr=   r?   r?   r@   item  s    zIndexOpsMixin.itemc                 C  s   | j jS )a  
        Return the number of bytes in the underlying data.

        Examples
        --------
        For Series:

        >>> s = pd.Series(['Ant', 'Bear', 'Cow'])
        >>> s
        0     Ant
        1    Bear
        2     Cow
        dtype: object
        >>> s.nbytes
        24

        For Index:

        >>> idx = pd.Index([1, 2, 3])
        >>> idx
        Index([1, 2, 3], dtype='int64')
        >>> idx.nbytes
        24
        )r   nbytesr=   r?   r?   r@   r     s    zIndexOpsMixin.nbytesc                 C  s
   t | jS )a  
        Return the number of elements in the underlying data.

        Examples
        --------
        For Series:

        >>> s = pd.Series(['Ant', 'Bear', 'Cow'])
        >>> s
        0     Ant
        1    Bear
        2     Cow
        dtype: object
        >>> s.size
        3

        For Index:

        >>> idx = pd.Index([1, 2, 3])
        >>> idx
        Index([1, 2, 3], dtype='int64')
        >>> idx.size
        3
        )rw   r   r=   r?   r?   r@   size  s    zIndexOpsMixin.sizer(   c                 C  s   t | dS )ac  
        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 from ``.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 NumpyExtensionArray
        is returned.

        >>> pd.Series([1, 2, 3]).array
        <NumpyExtensionArray>
        [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']
        Nr   r=   r?   r?   r@   array  s    ?zIndexOpsMixin.arrayNFznpt.DTypeLike | NoneboolrE   z
np.ndarray)r   copyna_valuerD   c           	      K  s  t | jtr&| jj|f||d|S |rJtt| }td| d|t	j
uon|tju olt| jtj }| j}|rt||stj||d}n| }||tt| < tj||d}|r|r|st rt| jdd |dd rt r|s| }d|j_n| }|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.
        **kwargs
            Additional keywords passed through to the ``to_numpy`` method
            of the underlying array (for extension arrays).

        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   r   z/to_numpy() got an unexpected keyword argument 'rc   )r   Nrz   F)rm   r   r   r   to_numpyr   r   keys	TypeErrorr   
no_defaultrp   nanZ
issubdtypeZfloatingr   r   Zasarrayr   Z
asanyarrayr!   r
   Zshares_memoryviewflagsZ	writeable)	r>   r   r   r   r   r   Zfillnavaluesresultr?   r?   r@   r     s0    _


 
zIndexOpsMixin.to_numpyc                 C  s   | j  S rl   )r   r=   r?   r?   r@   empty  s    zIndexOpsMixin.emptymaxminZlargest)opZopposerf   TzAxisInt | None)rv   skipnarD   c                 O  s   | j }t| t|||}t|trf|s\|  r\tj	dt
| j dtt d dS | S n:tj||d}|dkrtj	dt
| j dtt d |S dS )ab  
        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}}
            Unused. Parameter needed for compatibility with DataFrame.
        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.
        The behavior of x.argmax/argmin with skipna=False and NAs, or with all-NAs is deprecated. In a future version this will raise ValueError.
stacklevelry   r   N)r   r   validate_minmax_axisZvalidate_argmax_with_skipnarm   r(   r!   anywarningswarnr<   rX   FutureWarningr   argmaxr$   Z	nanargmaxr>   rv   r   r   r   Zdelegater   r?   r?   r@   r     s(    6


	zIndexOpsMixin.argmaxZsmallestc                 O  s   | j }t| t|||}t|trf|s\|  r\tj	dt
| j dtt d dS | S n:tj||d}|dkrtj	dt
| j dtt d |S d S )Nr   r   r   ry   r   )r   r   r   Zvalidate_argmin_with_skipnarm   r(   r!   r   r   r   r<   rX   r   r   argminr$   Z	nanargminr   r?   r?   r@   r     s(    


	zIndexOpsMixin.argminc                 C  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.

        Examples
        --------
        For Series

        >>> s = pd.Series([1, 2, 3])
        >>> s.to_list()
        [1, 2, 3]

        For Index:

        >>> idx = pd.Index([1, 2, 3])
        >>> idx
        Index([1, 2, 3], dtype='int64')

        >>> idx.to_list()
        [1, 2, 3]
        )r   r   r=   r?   r?   r@   r     s    "zIndexOpsMixin.tolistr,   c                 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

        Examples
        --------
        >>> s = pd.Series([1, 2, 3])
        >>> for x in s:
        ...     print(x)
        1
        2
        3
        N)	rm   r   rp   rq   r   mapr   ranger   r=   r?   r?   r@   __iter__D  s    
zIndexOpsMixin.__iter__c                 C  s   t t|  S )ak  
        Return True if there are any NaNs.

        Enables various performance speedups.

        Returns
        -------
        bool

        Examples
        --------
        >>> s = pd.Series([1, 2, 3, None])
        >>> s
        0    1.0
        1    2.0
        2    3.0
        3    NaN
        dtype: float64
        >>> s.hasnans
        True
        )r   r!   r   r=   r?   r?   r@   hasnans`  s    zIndexOpsMixin.hasnans)convertc                 C  s0   | j }t|tr|j||dS tj||||d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
        convert : bool, default True
            Try to find better dtype for elementwise function results. If
            False, leave as dtype=object. Note that the dtype is always
            preserved for some extension array dtypes, such as Categorical.

        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.
        )	na_action)r   r   )r   rm   r(   r   r#   Z	map_array)r>   Zmapperr   r   arrr?   r?   r@   _map_values{  s    
zIndexOpsMixin._map_valuesr3   )	normalizesort	ascendingdropnarD   c                 C  s   t j| |||||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 when True. Preserve the order of the data when False.
        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
        Name: count, 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
        Name: proportion, 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
        Name: count, 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
        Name: count, dtype: int64
        )r   r   r   binsr   )r#   Zvalue_counts_internal)r>   r   r   r   r   r   r?   r?   r@   value_counts  s    WzIndexOpsMixin.value_countsc                 C  s*   | j }t|tjs| }n
t|}|S rl   )r   rm   rp   rq   r8   r#   Zunique1d)r>   r   r   r?   r?   r@   r8     s
    

zIndexOpsMixin.unique)r   rD   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
        )r8   r"   rw   )r>   r   Zuniqsr?   r?   r@   nunique  s    #zIndexOpsMixin.nuniquec                 C  s   | j ddt| kS )a.  
        Return boolean if values in the object are unique.

        Returns
        -------
        bool

        Examples
        --------
        >>> s = pd.Series([1, 2, 3])
        >>> s.is_unique
        True

        >>> s = pd.Series([1, 2, 3, 1])
        >>> s.is_unique
        False
        F)r   )r   rw   r=   r?   r?   r@   	is_unique,  s    zIndexOpsMixin.is_uniquec                 C  s   ddl m} || jS )aY  
        Return boolean if values in the object are monotonically increasing.

        Returns
        -------
        bool

        Examples
        --------
        >>> s = pd.Series([1, 2, 2])
        >>> s.is_monotonic_increasing
        True

        >>> s = pd.Series([3, 2, 1])
        >>> s.is_monotonic_increasing
        False
        r   r2   )pandasr2   is_monotonic_increasingr>   r2   r?   r?   r@   r   A  s    z%IndexOpsMixin.is_monotonic_increasingc                 C  s   ddl m} || jS )a\  
        Return boolean if values in the object are monotonically decreasing.

        Returns
        -------
        bool

        Examples
        --------
        >>> s = pd.Series([3, 2, 2, 1])
        >>> s.is_monotonic_decreasing
        True

        >>> s = pd.Series([1, 2, 3])
        >>> s.is_monotonic_decreasing
        False
        r   r   )r   r2   is_monotonic_decreasingr   r?   r?   r@   r   X  s    z%IndexOpsMixin.is_monotonic_decreasing)rQ   rD   c                 C  sT   t | jdr| jj|dS | jj}|rPt| jrPtsPttj	| j
}|t|7 }|S )a  
        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

        Examples
        --------
        >>> idx = pd.Index([1, 2, 3])
        >>> idx.memory_usage()
        24
        rO   rP   )rJ   r   rO   r   r   r   r   r   rp   rq   r   r   Zmemory_usage_of_objects)r>   rQ   vr   r?   r?   r@   _memory_usageo  s    zIndexOpsMixin._memory_usager6   z            sort : bool, default False
                Sort `uniques` and shuffle `codes` to maintain the
                relationship.
            )r   orderZ	size_hintr   z"tuple[npt.NDArray[np.intp], Index])r   use_na_sentinelrD   c                 C  s`   t j| j||d\}}|jtjkr.|tj}t| t	rD| 
|}nddlm} ||}||fS )N)r   r   r   r   )r#   	factorizer   r   rp   Zfloat16ZastypeZfloat32rm   r   rA   r   r2   )r>   r   r   codesZuniquesr2   r?   r?   r@   r     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 or scalar
            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
        searchsorted.r0   zLiteral['left', 'right']r.   znp.intp)rf   sidesorterrD   c                 C  s   d S rl   r?   r>   rf   r   r   r?   r?   r@   r   #  s    zIndexOpsMixin.searchsortedznpt.ArrayLike | ExtensionArrayznpt.NDArray[np.intp]c                 C  s   d S rl   r?   r   r?   r?   r@   r   ,  s    r2   )r7   leftz$NumpyValueArrayLike | ExtensionArrayzNumpySorter | Noneznpt.NDArray[np.intp] | np.intpc                 C  sX   t |tr$dt|j d}t|| j}t |tjsF|j|||dS t	j||||dS )Nz(Value must be 1-D array-like or scalar, z is not supported)r   r   )
rm   r   r<   rX   r   r   rp   rq   r   r#   )r>   rf   r   r   msgr   r?   r?   r@   r   5  s    
firstkeepr-   c                C  s   | j |d}| |  S Nr   )_duplicated)r>   r   r9   r?   r?   r@   drop_duplicatesO  s    zIndexOpsMixin.drop_duplicatesznpt.NDArray[np.bool_])r   rD   c                 C  s*   | j }t|tr|j|dS tj||dS r   )r   rm   r(   r9   r#   )r>   r   r   r?   r?   r@   r   T  s    
zIndexOpsMixin._duplicatedc                 C  s   t | |}| j}t|ddd}t ||j}t|}t|trTt	
|j|j|j}t	jdd t |||}W d    n1 s0    Y  | j||dS )NT)Zextract_numpyZextract_rangeignore)all)r   )r%   Zget_op_result_namer   r*   Zmaybe_prepare_scalar_for_opr   r)   rm   r   rp   ZarangestartstopstepZerrstateZarithmetic_op_construct_result)r>   otherr   Zres_nameZlvaluesZrvaluesr   r?   r?   r@   _arith_method[  s    
,zIndexOpsMixin._arith_methodc                 C  s   t | dS )z~
        Construct an appropriately-wrapped result from the ArrayLike result
        of an arithmetic-like operation.
        Nr   )r>   r   r   r?   r?   r@   r   j  s    zIndexOpsMixin._construct_result)NT)NT)NT)FTFNT)T)F)FT)..)..)r   N)r   )4rX   rY   rZ   r[   Z__array_priority__	frozensetr   r\   r]   r   r   r   r   Tr   r   rt   r   r   r   r   r   r   r   r   r   r   r   r   Zto_listr   r   r   r   r   r8   r   r   r   r   r   r#   r   textwrapdedentr4   r	   r   r   r   r   r   r?   r?   r?   r@   r5     s   

@  S !$     _	')  i      )Tr[   
__future__r   r   typingr   r   r   r   r   r   r	   r   numpyrp   Zpandas._configr
   Zpandas._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.util._exceptionsr   Zpandas.core.dtypes.castr   Zpandas.core.dtypes.commonr   r   Zpandas.core.dtypes.dtypesr   Zpandas.core.dtypes.genericr   r   r    Zpandas.core.dtypes.missingr!   r"   Zpandas.corer#   r$   r%   Zpandas.core.accessorr&   Zpandas.core.arrayliker'   Zpandas.core.arraysr(   Zpandas.core.constructionr)   r*   collections.abcr+   r,   r-   r.   r/   r0   r   r1   r2   r3   r4   r\   Z_indexops_doc_kwargsr:   r_   rg   r5   r?   r?   r?   r@   <module>   sJ   $	$	/"g