o
    Û­j¨¡  ã                   @  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/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œZPG dd „ d e;ƒZQG d!d"„ d"ƒZRG d#d$„ d$ee ƒZSG d%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                      sN   e Zd ZU dZded< edd„ ƒZddd	„Zdddd„Z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© rA   úM/var/www/html/CropPilot/venv/lib/python3.10/site-packages/pandas/core/base.pyÚ_constructorm   ó   zPandasObject._constructorÚreturnÚstrc                 C  s
   t  | ¡S )zI
        Return a string representation for a particular object.
        )ÚobjectÚ__repr__r?   rA   rA   rB   rH   t   s   
zPandasObject.__repr__NÚkeyú
str | NoneÚNonec                 C  s6   t | dƒsdS |du r| j ¡  dS | j |d¡ dS )zV
        Reset cached properties. If ``key`` is passed, only clears that key.
        r=   N)Úhasattrr=   ÚclearÚpop)r@   rI   rA   rA   rB   Ú_reset_cache{   s
   
zPandasObject._reset_cacheÚintc                   s>   t | ddƒ}|r|dd�}tt|ƒr|ƒS | ¡ ƒS tƒ  ¡ S )zx
        Generates the total memory usage for an object that returns
        either a value or Series of values
        Úmemory_usageNT©Údeep)ÚgetattrrP   r   ÚsumÚsuperÚ
__sizeof__)r@   rQ   Úmem©Ú	__class__rA   rB   rW   †   s
   

zPandasObject.__sizeof__)rE   rF   ©N)rI   rJ   rE   rK   ©rE   rP   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__ÚpropertyrC   rH   rO   rW   Ú__classcell__rA   rA   rY   rB   r<   e   s   
 

r<   c                   @  s$   e Zd ZdZddd„Z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)`.
    rE   rK   c                 C  s   t  | dd¡ dS )z9
        Prevents setting additional attributes.
        Ú__frozenTN)rG   Ú__setattr__r?   rA   rA   rB   Ú_freeze    s   zNoNewAttributesMixin._freezerI   rF   c                 C  sT   t | ddƒr!|dks!|t| ƒjv s!t | |d ƒd us!td|› d�ƒ‚t | ||¡ d S )Nre   Fr=   z"You cannot add any new attribute 'ú')rT   r>   Ú__dict__ÚAttributeErrorrG   rf   )r@   rI   ÚvaluerA   rA   rB   rf   §   s   z NoNewAttributesMixin.__setattr__N)rE   rK   )rI   rF   rE   rK   )r]   r^   r_   r`   rg   rf   rA   rA   rA   rB   rd   ”   s    
rd   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„ƒƒZe	edd„ ƒƒZdd„ Zd!d"dd„Ze	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 r[   )Ú
isinstancern   ÚlistÚtupler!   r   ÚnpÚndarrayr?   rA   rA   rB   Ú_selection_listÂ   s
   ÿzSelectionMixin._selection_listc                 C  s(   | j d u st| jtƒr| jS | j| j  S r[   )rn   rq   rm   r!   r?   rA   rA   rB   Ú_selected_objË   s   zSelectionMixin._selected_objrE   rP   c                 C  ó   | j jS r[   )rw   Úndimr?   rA   rA   rB   ry   Ò   ó   zSelectionMixin.ndimc                 C  sR   t | jtƒr	| jS | jd ur| j | j¡S t| jƒdkr&| jj| jddd�S | jS )Nr   é   T)ÚaxisÚ
only_slice)	rq   rm   r!   rn   Ú_getitem_nocopyrv   Úlenro   Ú
_drop_axisr?   rA   rA   rB   Ú_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ƒrIt	| j
j |¡ƒt	t|ƒƒkr@tt|ƒ | j
j¡ƒ}tdt|ƒdd… › �ƒ‚| jt|ƒdd�S || j
vrUtd|› �ƒ‚| j
| j}| j||d�S )	Nz
Column(s) z already selectedzColumns not found: r{   éÿÿÿÿé   )ry   zColumn not found: )rn   Ú
IndexErrorrq   rr   rs   r!   r   rt   ru   r   rm   ÚcolumnsÚintersectionÚsetÚ
differenceÚKeyErrorrF   Ú_gotitemry   )r@   rI   Úbad_keysry   rA   rA   rB   Ú__getitem__é   s   

zSelectionMixin.__getitem__ry   c                 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   )r@   rI   ry   ÚsubsetrA   rA   rB   rŠ   ù   s   zSelectionMixin._gotitemrŽ   úSeries | DataFramec                 C  sX   d}|j dkrt |¡r||v st |¡r|}|S |j dkr*t |¡r*||jkr*|}|S )zO
        Infer the `selection` to pass to our constructor in _gotitem.
        Nrƒ   r{   )ry   r   r   Úis_list_likeÚname)r@   rI   rŽ   Ú	selectionrA   rA   rB   Ú_infer_selection  s   
ÿþzSelectionMixin._infer_selectionc                 O  r�   r[   r   )r@   ÚfuncÚargsÚkwargsrA   rA   rB   Ú	aggregate  s   zSelectionMixin.aggregater\   r[   )ry   rP   )rŽ   r�   )r]   r^   r_   r`   ra   rn   Ú_internal_namesr‡   Ú_internal_names_setr   rb   rv   r   rw   ry   r�   rŒ   rŠ   r“   r—   ÚaggrA   rA   rA   rB   rl   ¶   s0   
 
rl   c                   @  sh  e Zd ZU dZdZedgƒZded< ed…dd	„ƒZ	ed†dd„ƒZ
ed‡dd„ƒZeedd�Zedˆdd„ƒZd‰dd„Zed‰dd„ƒZedd„ ƒZed‰dd„ƒZed‰dd„ƒZedŠd!d"„ƒZed#d$ejfd‹d,d-„ƒZeedŒd.d/„ƒƒZed0d1d2d3�	4d�dŽd8d9„ƒZeed1d0d:d3�	4d�dŽd;d<„ƒZd=d>„ ZeZd�d@dA„ZedŒdBdC„ƒZ ed�d�dEdF„ƒZ!e	$	4	$	#	4d‘d’dLdM„ƒZ"dNdO„ Z#ed“d”dPdQ„ƒZ$edŒdRdS„ƒZ%edŒdTdU„ƒZ&edŒdVdW„ƒZ'ed•d–dYdZ„ƒZ(ee)j*d[d[d[e+ ,d\¡d]�	$	4d—d˜d`da„ƒZ*dbe-dc< e.	d	dd™dšdldm„ƒZ/e.	d	dd™d›dpdm„ƒZ/ee-dc dqdr�	s	#dœd�dwdm„ƒZ/dxdyœdžd|d}„Z0edŸd dd€„ƒZ1d�d‚„ Z2dƒd„„ Z3d#S )¡r6   zS
    Common ops mixin to support a unified interface / docs for Series / Index
    iè  Útolistzfrozenset[str]Ú_hidden_attrsrE   r   c                 C  r�   r[   r   r?   rA   rA   rB   Údtype(  rz   zIndexOpsMixin.dtypeúExtensionArray | np.ndarrayc                 C  r�   r[   r   r?   rA   rA   rB   Ú_values-  rz   zIndexOpsMixin._valuesr   c                 O  s   t  ||¡ | S )zw
        Return the transpose, which is by definition self.

        Returns
        -------
        %(klass)s
        )ÚnvÚvalidate_transpose)r@   r•   r–   rA   rA   rB   Ú	transpose2  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  rx   )z®
        Return a tuple of the shape of the underlying data.

        Examples
        --------
        >>> s = pd.Series([1, 2, 3])
        >>> s.shape
        (3,)
        )rŸ   Úshaper?   rA   rA   rB   r£   [  s   zIndexOpsMixin.shaperP   c                 C  r�   r[   r   r?   rA   rA   rB   Ú__len__h  s   zIndexOpsMixin.__len__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
        r{   rA   r?   rA   rA   rB   ry   o  s   zIndexOpsMixin.ndimc                 C  s    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Ú
ValueErrorr?   rA   rA   rB   Úitem‰  s   zIndexOpsMixin.itemc                 C  rx   )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?   rA   rA   rB   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
        )r   rŸ   r?   rA   rA   rB   ÚsizeÄ  s   
zIndexOpsMixin.sizer)   c                 C  r�   )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   r?   rA   rA   rB   Úarrayà  s   ?zIndexOpsMixin.arrayNFr�   únpt.DTypeLike | NoneÚcopyÚboolÚna_valuerG   ú
np.ndarrayc           	      K  s  t | jtƒr| jj|f||dœ|¤ŽS |r%tt| ¡ ƒƒ}td|› d�ƒ‚|t	j
uo7|tju o6t | jtj¡ }| j}|rWt||ƒsJtj||d�}n| ¡ }||t t| ƒ¡< tj||d�}|rb|rg|s‰tƒ r‰t | jdd… |dd… ¡r‰tƒ r…|s…| ¡ }d|j_|S | ¡ }|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 'rh   ©r�   Nrƒ   F)rq   r�   r   r«   Úto_numpyr¥   r¦   ÚkeysÚ	TypeErrorr   Ú
no_defaultrt   ÚnanÚ
issubdtypeÚfloatingrŸ   r   Úasarrayr­   Ú
asanyarrayr"   r
   Úshares_memoryÚviewÚflagsÚ	writeable)	r@   r�   r­   r¯   r–   r‹   ÚfillnaÚvaluesÚresultrA   rA   rB   r²   !  s2   _
ÿ
ý

þzIndexOpsMixin.to_numpyc                 C  s   | j  S r[   )rª   r?   rA   rA   rB   Úempty§  rz   zIndexOpsMixin.emptyÚmaxÚminÚlargest)ÚopÚopposerk   Tr|   úAxisInt | NoneÚskipnac                 O  óž   | j }t |¡ t |||¡}t|tƒr2|s.| ¡  ¡ r.tj	dt
| ƒj› d�ttƒ d� dS | ¡ S tj||d�}|dkrMtj	dt
| ƒj› d�ttƒ 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.©Ú
stacklevelr‚   ©rÉ   )rŸ   r    Úvalidate_minmax_axisÚvalidate_argmax_with_skipnarq   r)   r"   ÚanyÚwarningsÚwarnr>   r]   ÚFutureWarningr   Úargmaxr%   Ú	nanargmax©r@   r|   rÉ   r•   r–   ÚdelegaterÁ   rA   rA   rB   rÖ   ¬  s(   6

ûû	zIndexOpsMixin.argmaxÚsmallestc                 O  rÊ   )NrË   rÌ   rÍ   r‚   rÏ   )rŸ   r    rÐ   Úvalidate_argmin_with_skipnarq   r)   r"   rÒ   rÓ   rÔ   r>   r]   rÕ   r   Úargminr%   Ú	nanargminrØ   rA   rA   rB   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?   rA   rA   rB   r›   "  s   
"zIndexOpsMixin.tolistr-   c                 C  s.   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
        )	rq   rŸ   rt   ru   r¦   Úmapr¨   Úrangerª   r?   rA   rA   rB   Ú__iter__H  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?   rA   rA   rB   Úhasnansd  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Ÿ   rq   r)   rÞ   r$   Ú	map_array)r@   Úmapperrã   râ   ÚarrrA   rA   rB   Ú_map_values  s   
zIndexOpsMixin._map_valuesÚ	normalizeÚsortÚ	ascendingÚdropnar4   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$   Úvalue_counts_internal)r@   rè   ré   rê   rì   rë   rA   rA   rB   Úvalue_countsŸ  s   WúzIndexOpsMixin.value_countsc                 C  s,   | j }t|tjƒs| ¡ }|S t |¡}|S r[   )rŸ   rq   rt   ru   r:   r$   Úunique1d)r@   rÀ   rÁ   rA   rA   rB   r:   ÿ  s   
ÿzIndexOpsMixin.uniquec                 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#   r   )r@   rë   ÚuniqsrA   rA   rB   Ú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ñ   r   r?   rA   rA   rB   Ú	is_unique0  s   zIndexOpsMixin.is_uniquec                 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   ©r3   )Úpandasr3   Úis_monotonic_increasing©r@   r3   rA   rA   rB   rö   E  ó   
z%IndexOpsMixin.is_monotonic_increasingc                 C  ró   )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õ   r3   Úis_monotonic_decreasingr÷   rA   rA   rB   rù   \  rø   z%IndexOpsMixin.is_monotonic_decreasingrS   c                 C  sT   t | jdƒr| jj|d�S | jj}|r(t| jƒr(ts(t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
        rQ   rR   )rL   r«   rQ   r©   r   r�   r   r   rt   ru   rŸ   r   Úmemory_usage_of_objects)r@   rS   ÚvrÀ   rA   rA   rB   Ú_memory_usages  s   ÿzIndexOpsMixin._memory_usager7   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                 C  s�   t j| j||d�\}}|jtjkr| tj¡}t| t	ƒr%|  
|¡}||fS ddlm} z||| jd�}W ||fS  tyG   ||ƒ}Y ||fS w )N)ré   rÿ   r   rô   r±   )r$   Ú	factorizerŸ   r�   rt   Úfloat16ÚastypeÚfloat32rq   r    rC   rõ   r3   ÚNotImplementedError)r@   ré   rÿ   ÚcodesÚuniquesr3   rA   rA   rB   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.rk   r1   ÚsideúLiteral['left', 'right']Úsorterr/   únp.intpc                 C  ó   d S r[   rA   ©r@   rk   r	  r  rA   rA   rB   r  ,  ó   zIndexOpsMixin.searchsortedúnpt.ArrayLike | ExtensionArrayúnpt.NDArray[np.intp]c                 C  r  r[   rA   r  rA   rA   rB   r  5  r  r3   )r8   Úleftú$NumpyValueArrayLike | ExtensionArrayúNumpySorter | Noneúnpt.NDArray[np.intp] | np.intpc                 C  sX   t |tƒrdt|ƒj› d�}t|ƒ‚| j}t |tjƒs#|j|||d�S t	j||||d�S )Nz(Value must be 1-D array-like or scalar, z is not supported)r	  r  )
rq   r   r>   r]   r§   rŸ   rt   ru   r  r$   )r@   rk   r	  r  ÚmsgrÀ   rA   rA   rB   r  >  s   
ÿÿüÚfirst©Úkeepr  r.   c                C  s   | j |d�}| |  S ©Nr  )Ú_duplicated)r@   r  r;   rA   rA   rB   Údrop_duplicatesX  s   
zIndexOpsMixin.drop_duplicatesúnpt.NDArray[np.bool_]c                 C  s*   | j }t|tƒr|j|d�S tj||d�S r  )rŸ   rq   r)   r;   r$   )r@   r  ræ   rA   rA   rB   r  ]  s   
zIndexOpsMixin._duplicatedc                 C  sœ   t  | |¡}| j}t|ddd�}t  ||j¡}t|ƒ}t|tƒr*t	 
|j|j|j¡}t	jdd�� t  |||¡}W d   ƒ n1 sBw   Y  | j||d�S )NT)Úextract_numpyÚextract_rangeÚignore)Úall)r‘   )r&   Úget_op_result_namerŸ   r+   Úmaybe_prepare_scalar_for_opr£   r*   rq   rß   rt   ÚarangeÚstartÚstopÚstepÚerrstateÚarithmetic_opÚ_construct_result)r@   ÚotherrÆ   Úres_nameÚlvaluesÚrvaluesrÁ   rA   rA   rB   Ú_arith_methodd  s   
ÿzIndexOpsMixin._arith_methodc                 C  r�   )z~
        Construct an appropriately-wrapped result from the ArrayLike result
        of an arithmetic-like operation.
        r   )r@   rÁ   r‘   rA   rA   rB   r*  s  rD   zIndexOpsMixin._construct_result)rE   r   )rE   rž   )rE   r   )rE   r   r\   )rE   r)   )r�   r¬   r­   r®   r¯   rG   rE   r°   )rE   r®   )NT)r|   rÈ   rÉ   r®   rE   rP   )rE   r-   )râ   r®   )FTFNT)
rè   r®   ré   r®   rê   r®   rë   r®   rE   r4   )T)rë   r®   rE   rP   )F)rS   r®   rE   rP   )FT)ré   r®   rÿ   r®   rE   r   )..)rk   r1   r	  r
  r  r/   rE   r  )rk   r  r	  r
  r  r/   rE   r  )r  N)rk   r  r	  r
  r  r  rE   r  )r  r.   )r  )r  r.   rE   r  )4r]   r^   r_   r`   Ú__array_priority__Ú	frozensetrœ   ra   rb   r�   rŸ   r   r¢   ÚTr£   r¤   ry   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Údedentr5   r	   r  r  r  r/  r*  rA   rA   rA   rB   r6     sÌ   
 ÿþ

@ü ÿSÿ!$
ú_	')ÿûýþÿiüüü)Ur`   Ú
__future__r   r4  Útypingr   r   r   r   r   r   r	   rÓ   Únumpyrt   Ú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.   r/   r0   r1   rõ   r2   r3   r4   r5   ra   Ú_indexops_doc_kwargsr<   rd   rl   r6   rA   rA   rA   rB   Ú<module>   sL    $	$	ü/"g