
    bMh                    >   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/m0Z0m1Z1m2Z2 ddl3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9 ddl:m;Z; ddl<m=Z= ddl>m?Z? ddl@mAZAmBZB erddlCmDZDmEZE ddlmFZFmGZGmHZHmIZI ddlJmKZKmLZLmMZM i ZNdeOd<   dddddZP G d d e;          ZQ G d! d"          ZR G d# d$ee                   ZS G d% de=          ZTd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ABCMultiIndex	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 )klassinplaceunique
duplicatedc                  X     e Zd ZU dZded<   ed             ZddZdddZd fdZ	 xZ
S )PandasObjectz/
    Baseclass for various pandas objects.
    zdict[str, Any]_cachec                     t          |           S )zK
        Class constructor (for this class it's just `__class__`).
        )typeselfs    P/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/pandas/core/base.py_constructorzPandasObject._constructorm   s    
 Dzz    returnstrc                6    t                               |           S )zI
        Return a string representation for a particular object.
        )object__repr__rB   s    rD   rK   zPandasObject.__repr__t   s    
 t$$$rF   Nkey
str | NoneNonec                    t          | d          sdS || j                                         dS | j                            |d           dS )zV
        Reset cached properties. If ``key`` is passed, only clears that key.
        r?   N)hasattrr?   clearpop)rC   rL   s     rD   _reset_cachezPandasObject._reset_cache{   sV     tX&& 	F;KKOOC&&&&&rF   intc                    t          | dd          }|r> |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)getattrrT   r   sumsuper
__sizeof__)rC   rV   mem	__class__s      rD   r\   zPandasObject.__sizeof__   sm    
 t^T:: 	=,D)))Cinn;ss#''))<<< ww!!###rF   )rG   rH   N)rL   rM   rG   rN   rG   rT   )__name__
__module____qualname____doc____annotations__propertyrE   rK   rS   r\   __classcell__)r^   s   @rD   r>   r>   e   s          
   X% % % %	' 	' 	' 	' 	'$ $ $ $ $ $ $ $ $ $rF   r>   c                  "    e Zd ZdZd	dZ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   rN   c                >    t                               | dd           dS )z9
        Prevents setting additional attributes.
        __frozenTN)rJ   __setattr__rB   s    rD   _freezezNoNewAttributesMixin._freeze   s"     	4T22222rF   rL   rH   c                    t          | dd          r@|dk    s:|t          |           j        v s$t          | |d           t          d| d          t                              | ||           d S )Nrk   Fr?   z"You cannot add any new attribute '')rY   rA   __dict__AttributeErrorrJ   rl   )rC   rL   values      rD   rl   z NoNewAttributesMixin.__setattr__   s     4U++ 	N8OOd4jj)))tS$''3 !Lc!L!L!LMMM4e,,,,,rF   N)rG   rN   )rL   rH   rG   rN   )ra   rb   rc   rd   rm   rl    rF   rD   ri   ri      sF        	 	3 3 3 3- - - - - -rF   ri   c                     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                         Zed             Ze	edd                        Ze	ed                         Zd ZdddZe	dd            Z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                    t          | j        t          t          t          t
          t          j        f          s| j        gS | j        S r_   )
isinstancerw   listtupler"   r    npndarrayrB   s    rD   _selection_listzSelectionMixin._selection_list   s?     OdE9h
K
 
 	% O$$rF   c                v    | j         t          | j        t                    r| j        S | j        | j                  S r_   )rw   r{   rv   r"   rB   s    rD   _selected_objzSelectionMixin._selected_obj   s1    ?"j9&E&E"8O8DO,,rF   rG   rT   c                    | j         j        S r_   )r   ndimrB   s    rD   r   zSelectionMixin.ndim   s     !&&rF   c                   t          | j        t                    r| j        S | j        | j                            | j                  S t          | j                  dk    r"| j                            | j        dd          S | j        S )Nr      T)axis
only_slice)	r{   rv   r"   rw   _getitem_nocopyr   lenrx   
_drop_axisrB   s    rD   _obj_with_exclusionsz#SelectionMixin._obj_with_exclusions   s}     dh	** 	8O?&8++D,@AAAt!##
 8&&tQ4&PPP8OrF   c                   | j         t          d| j          d          t          |t          t          t
          t          t          j        f          rt          | j
        j                            |                    t          t          |                    k    r`t          t          |                              | j
        j                            }t          dt!          |          dd                    |                     t          |          d          S || j
        vrt          d|           | j
        |         j        }|                     ||          S )	Nz
Column(s) z already selectedzColumns not found: r      )r   zColumn not found: )rw   
IndexErrorr{   r|   r}   r"   r    r~   r   r   rv   columnsintersectionset
differenceKeyErrorrH   _gotitemr   )rC   rL   bad_keysr   s       rD   __getitem__zSelectionMixin.__getitem__   s)   ?&L$/LLLMMMcD%HbjIJJ 
	148#005566#c#hh--GGC 3 3DH4D E EFFJS]]1R45HJJKKK==c=333 $(""9C99:::8C=%D==4=000rF   r   c                     t          |           )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
        r   )rC   rL   r   subsets       rD   r   zSelectionMixin._gotitem   s     "$'''rF   r   Series | DataFramec                    d}|j         dk    r/t          j        |          r||v st          j        |          r|}n,|j         dk    r!t          j        |          r||j        k    r|}|S )zO
        Infer the `selection` to pass to our constructor in _gotitem.
        Nr   r   )r   r   r   is_list_likename)rC   rL   r   	selections       rD   _infer_selectionzSelectionMixin._infer_selection  sz     	;!]3 $'6MMc6Fs6K6KMII[A#-"4"49K9KIrF   c                     t          |           r_   r   )rC   funcargskwargss       rD   	aggregatezSelectionMixin.aggregate  s    !$'''rF   r`   r_   )r   rT   )r   r   )ra   rb   rc   rd   re   rw   _internal_namesr   _internal_names_setr	   rf   r   r   r   r   r   r   r   r   r   aggrs   rF   rD   ru   ru      sG         
 MMM$(J((((####0O#o..
  X U - - ^- ' ' ' ^ U'   ^ U 1 1 1 ( ( ( ( (    U( ( ( CCCrF   ru   c            	         e Zd ZU dZdZ edg          Zded<   edfd            Z	edgd
            Z
edhd            Z eed          Zedid            ZdjdZedjd            Zed             Zedjd            Zedjd            Zedkd            Zeddej        fdld"            Zeedmd#                        Z ed$d%d&'          	 dndod,            Z eed%d$d-'          	 dndod.            Zd/ ZeZdpd1Zedmd2            Z edndqd4            Z!e	 	 	 	 	 drdsd:            Z"d; Z#edtdud<            Z$edmd=            Z%edmd>            Z&edmd?            Z'edvdwdA            Z( ee)j*        dBdBdB e+j,        dC          D          	 	 dxdydG            Z*dHe-dI<   e.	 	 dzd{dR            Z/e.	 	 dzd|dU            Z/ ee-dI         dVW          	 	 d}d~d\            Z/d]d^ddaZ0edddc            Z1dd Z2de Z3dS )r7   zS
    Common ops mixin to support a unified interface / docs for Series / Index
    i  tolistzfrozenset[str]_hidden_attrsrG   r   c                     t          |           r_   r   rB   s    rD   dtypezIndexOpsMixin.dtype(       "$'''rF   ExtensionArray | np.ndarrayc                     t          |           r_   r   rB   s    rD   _valueszIndexOpsMixin._values-  r   rF   r   c                0    t          j        ||           | S )zw
        Return the transpose, which is by definition self.

        Returns
        -------
        %(klass)s
        )nvvalidate_transpose)rC   r   r   s      rD   	transposezIndexOpsMixin.transpose2  s     	dF+++rF   a  
        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                    | 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   shaperB   s    rD   r   zIndexOpsMixin.shape[  s     |!!rF   rT   c                     t          |           r_   r   rB   s    rD   __len__zIndexOpsMixin.__len__h  s    !$'''rF   c                    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
        r   rs   rB   s    rD   r   zIndexOpsMixin.ndimo  s	    0 qrF   c                ~    t          |           dk    rt          t          |                     S t          d          )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'
        r   z6can only convert an array of size 1 to a Python scalar)r   nextiter
ValueErrorrB   s    rD   itemzIndexOpsMixin.item  s6    6 t99>>T

###QRRRrF   c                    | 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   nbytesrB   s    rD   r   zIndexOpsMixin.nbytes  s    4 |""rF   c                *    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
        )r   r   rB   s    rD   sizezIndexOpsMixin.size  s    4 4<   rF   r*   c                     t          |           )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']
        r   rB   s    rD   arrayzIndexOpsMixin.array  s    ~ "$'''rF   NFr   npt.DTypeLike | Nonecopyboolna_valuerJ   
np.ndarrayc                p   t          | j        t                    r | j        j        |f||d|S |rAt          t          |                                                    }t          d| d          |t          j
        uo2|t          j        u o#t          j        | j        t          j                   }| j        }|r_t!          ||          st          j        ||          }n|                                }||t          j        t)          |                     <   t          j        ||          }|r|r|s}t+                      rot          j        | j        dd         |dd                   rEt+                      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 'ro   r   Nr   F)r{   r   r   r   to_numpyr   r   keys	TypeErrorr   
no_defaultr~   nan
issubdtypefloatingr   r   asarrayr   
asanyarrayr#   r   shares_memoryviewflags	writeable)	rC   r   r   r   r   r   fillnavaluesresults	            rD   r   zIndexOpsMixin.to_numpy!  s   ~ dj.11 	&4:&uU4(UUfUUU 	D//00HM(MMM  
 CN* T'RBM$*bk,R,RS 	  		9#FH55 ' F%88808F2=d,,-F%000 	+ 	+ 	+2E2G2G 	+RaR 0&!*== +&(( + +#[[]]F-2FL**#[[]]FrF   c                    | j          S r_   )r   rB   s    rD   emptyzIndexOpsMixin.empty  s     9}rF   maxminlargest)opopposerr   Tr   AxisInt | Noneskipnac                >   | j         }t          j        |           t          j        |||          }t	          |t
                    r||sf|                                                                r@t          j	        dt          |           j         dt          t                                 dS |                                S t          j        ||          }|dk    r>t          j	        dt          |           j         dt          t                                 |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.
stacklevelr   r   )r   r   validate_minmax_axisvalidate_argmax_with_skipnar{   r*   r#   anywarningswarnrA   ra   FutureWarningr   argmaxr&   	nanargmaxrC   r   r   r   r   delegater   s          rD   r   zIndexOpsMixin.argmax  s6   l <
%%%/fEEh// 	 
)hmmoo1133 
)FtDzz': F F F "/11    r(((%hv>>>F||FtDzz': F F F "/11    MrF   smallestc                >   | j         }t          j        |           t          j        |||          }t	          |t
                    r||sf|                                                                r@t          j	        dt          |           j         dt          t                                 dS |                                S t          j        ||          }|dk    r>t          j	        dt          |           j         dt          t                                 |S )Nr   r   r   r   r   )r   r   r   validate_argmin_with_skipnar{   r*   r#   r   r   r   rA   ra   r   r   argminr&   	nanargminr   s          rD   r   zIndexOpsMixin.argmin   s5    <
%%%/fEEh// 	 
)hmmoo1133 
)FtDzz': F F F "/11    r(((%hv>>>F||FtDzz': F F F "/11    MrF   c                4    | 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   rB   s    rD   r   zIndexOpsMixin.tolist"  s    D |""$$$rF   r.   c                    t          | j        t          j                  st	          | j                  S t          | j        j        t          | j        j                            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
        )	r{   r   r~   r   r   mapr   ranger   rB   s    rD   __iter__zIndexOpsMixin.__iter__H  sM    , $,
33 	D%%%t|(%0A*B*BCCCrF   c                ^    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   rB   s    rD   hasnanszIndexOpsMixin.hasnansd  s"    2 DJJNN$$%%%rF   convertc                    | j         }t          |t                    r|                    ||          S t	          j        ||||          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   r{   r*   r   r%   	map_array)rC   mapperr  r  arrs        rD   _map_valueszIndexOpsMixin._map_values  sM    2 lc>** 	8776Y7777#C9gVVVVrF   	normalizesort	ascendingdropnar5   c                6    t          j        | |||||          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%   value_counts_internal)rC   r	  r
  r  r  r  s         rD   value_countszIndexOpsMixin.value_counts  s1    n /
 
 
 	
rF   c                    | j         }t          |t          j                  s|                                }nt          j        |          }|S r_   )r   r{   r~   r   r;   r%   unique1d)rC   r   r   s      rD   r;   zIndexOpsMixin.unique  sA    &"*-- 	1]]__FF(00FrF   c                j    |                                  }|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$   r   )rC   r  uniqss      rD   nuniquezIndexOpsMixin.nunique  s3    F  	/'..E5zzrF   c                P    |                      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  r   rB   s    rD   	is_uniquezIndexOpsMixin.is_unique0  s#    & ||5|))SYY66rF   c                .    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   r4   )pandasr4   is_monotonic_increasingrC   r4   s     rD   r  z%IndexOpsMixin.is_monotonic_increasingE  '    & 	!     uT{{22rF   c                .    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  r4   is_monotonic_decreasingr  s     rD   r  z%IndexOpsMixin.is_monotonic_decreasing\  r  rF   rX   c                $   t          | j        d          r| j                            |          S | j        j        }|rQt	          | j                  r=t          s6t          t          j	        | j
                  }|t          j        |          z  }|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
        rV   rW   )rP   r   rV   r   r   r   r   r   r~   r   r   r   memory_usage_of_objects)rC   rX   vr   s       rD   _memory_usagezIndexOpsMixin._memory_usages  s    > 4:~.. 	:** +    J 	5ODJ// 	5 	5"*dl33F,V444ArF   r8   z            sort : bool, default False
                Sort `uniques` and shuffle `codes` to maintain the
                relationship.
            )r   order	size_hintr
  use_na_sentinel"tuple[npt.NDArray[np.intp], Index]c                p   t          j        | j        ||          \  }}|j        t          j        k    r|                    t          j                  }t          | t                    r| 
                    |          }n5ddlm} 	  ||| j                  }n# t          $ r  ||          }Y nw xY w||fS )N)r
  r&  r   r  r   )r%   	factorizer   r   r~   float16astypefloat32r{   r!   rE   r  r4   NotImplementedError)rC   r
  r&  codesuniquesr4   s         rD   r)  zIndexOpsMixin.factorize  s    $ $-Lt_
 
 
w =BJ&&nnRZ00GdM** 	)''00GG$$$$$$)%tz:::& ) ) )  %..) g~s   B B10B1a  
        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.rr   r2   sideLiteral['left', 'right']sorterr0   np.intpc                    d S r_   rs   rC   rr   r1  r3  s       rD   r0  zIndexOpsMixin.searchsorted,  	     	rF   npt.ArrayLike | ExtensionArraynpt.NDArray[np.intp]c                    d S r_   rs   r6  s       rD   r0  zIndexOpsMixin.searchsorted5  r7  rF   r4   )r9   left$NumpyValueArrayLike | ExtensionArrayNumpySorter | Nonenpt.NDArray[np.intp] | np.intpc                   t          |t                    r'dt          |          j         d}t	          |          | j        }t          |t          j                  s|                    |||          S t          j        ||||          S )Nz(Value must be 1-D array-like or scalar, z is not supported)r1  r3  )
r{   r   rA   ra   r   r   r~   r   r0  r%   )rC   rr   r1  r3  msgr   s         rD   r0  zIndexOpsMixin.searchsorted>  s     e\** 	";;;'; ; ;  S//!&"*-- 	H&&u4&GGG&	
 
 
 	
rF   firstkeeprC  r/   c               @    |                      |          }| |          S NrB  )_duplicated)rC   rC  r<   s      rD   drop_duplicateszIndexOpsMixin.drop_duplicatesX  s%    %%4%00
ZK  rF   npt.NDArray[np.bool_]c                    | j         }t          |t                    r|                    |          S t	          j        ||          S rE  )r   r{   r*   r<   r%   )rC   rC  r  s      rD   rF  zIndexOpsMixin._duplicated]  sE    lc>** 	->>t>,,,$St4444rF   c                   t          j        | |          }| j        }t          |dd          }t          j        ||j                  }t          |          }t          |t                    r%t          j
        |j        |j        |j                  }t          j        d          5  t          j        |||          }d d d            n# 1 swxY w Y   |                     ||          S )NT)extract_numpyextract_rangeignore)all)r   )r'   get_op_result_namer   r,   maybe_prepare_scalar_for_opr   r+   r{   r   r~   arangestartstopsteperrstatearithmetic_op_construct_result)rC   otherr   res_namelvaluesrvaluesr   s          rD   _arith_methodzIndexOpsMixin._arith_methodd  s   )$66,TNNN1'7=II099gu%% 	Kiw|W\JJG[X&&& 	= 	=&w<<F	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= %%f8%<<<s   'C

CCc                     t          |           )z~
        Construct an appropriately-wrapped result from the ArrayLike result
        of an arithmetic-like operation.
        r   )rC   r   r   s      rD   rW  zIndexOpsMixin._construct_results  s    
 "$'''rF   )rG   r   )rG   r   )rG   r   )rG   r   r`   )rG   r*   )r   r   r   r   r   rJ   rG   r   )rG   r   )NT)r   r   r   r   rG   rT   )rG   r.   )r  r   )FTFNT)
r	  r   r
  r   r  r   r  r   rG   r5   )T)r  r   rG   rT   )F)rX   r   rG   rT   )FT)r
  r   r&  r   rG   r'  )..)rr   r2   r1  r2  r3  r0   rG   r4  )rr   r8  r1  r2  r3  r0   rG   r9  )r;  N)rr   r<  r1  r2  r3  r=  rG   r>  )rC  r/   )rA  )rC  r/   rG   rH  )4ra   rb   rc   rd   __array_priority__	frozensetr   re   rf   r   r   r	   r   Tr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   to_listr   r   r  r  r  r;   r  r  r  r  r#  r%   r)  textwrapdedentr6   r
   r0  rG  rF  r\  rW  rs   rF   rD   r7   r7     sp         
 $-I	
% %M     ( ( ( X( ( ( ( X( 	 	 	 U	 		 	 	A: 
" 
" 
" X
"( ( ( (    X2 S S US< # # # X#6 ! ! ! X!6 >( >( >( X>(@  '+>	C C C C UCJ    X U 	SE%y111:>Q Q Q Q 21Qf 	SE%z::::>    ;:B"% "% "%H GD D D D8 & & & ^&4 W W W W UW>   ]
 ]
 ]
 ]
 U]
~   % % % % U%N 7 7 7 X7( 3 3 3 X3, 3 3 3 X3, ' ' ' ' U'R 	SX_
 
    $    6`	 R  *-!	    X  *-!	    X 	Sn	%W555 *0%)	
 
 
 
 65
2 3: ! ! ! ! ! !
 5 5 5 5 U5= = =( ( ( ( (rF   )Urd   
__future__r   rb  typingr   r   r   r   r   r	   r
   r   numpyr~   pandas._configr   pandas._libsr   pandas._typingr   r   r   r   r   r   r   pandas.compatr   pandas.compat.numpyr   r   pandas.errorsr   pandas.util._decoratorsr   r   pandas.util._exceptionsr   pandas.core.dtypes.castr   pandas.core.dtypes.commonr   r   pandas.core.dtypes.dtypesr   pandas.core.dtypes.genericr   r    r!   r"   pandas.core.dtypes.missingr#   r$   pandas.corer%   r&   r'   pandas.core.accessorr(   pandas.core.arrayliker)   pandas.core.arraysr*   pandas.core.constructionr+   r,   collections.abcr-   r.   r/   r0   r1   r2   r  r3   r4   r5   r6   re   _indexops_doc_kwargsr>   ri   ru   r7   rs   rF   rD   <module>r{     sn     # " " " " "                        . . . . . .                              . . . . . . - - - - - -        5 4 4 4 4 4 4 4 4 4 4 4        5 4 4 4 4 4                  
         
 / . . . . . * * * * * * - - - - - -       
         
                      " ! ! ! !!	  ,$ ,$ ,$ ,$ ,$= ,$ ,$ ,$^- - - - - - - -Dd d d d dWX& d d dN[( [( [( [( [(H [( [( [( [( [(rF   