+
    xȇi                   Z   ^ RI Ht ^ RIHtHtHtHtHtHt ^ RI	H
t
 ^ RIHt ^ RIHt ^ RIHtHtHtHtHt ^ RIt^ RIt^ RIHt ^ R	IHtHtHt ^ R
I H!t! ^ RI"H#t#H$t$H%t%H&t&H't'H(t(H)t)H*t*H+t+H,t,H-t-H.t.H/t/ ^ RI0H1t2 ^ RI3H4t4H5t5H6t6 ^ RI7H8t8H9t9 ^ RI:H;t; ^ RI<H=t=H>t> ^ RI?H@t@HAtAHBtBHCtCHDtDHEtEHFtFHGtGHHtHHItI ^ RIJHKtKHLtL ^ RIMHNtNHOtO ^ RIPHQtQ ^ RIRHStSHTtT ^ RIUHVu HWt ^ RIXHYtY ^ RIZH[t[H\t\ ^ RI]H^t^H_t_ ^ RI`HVu Hatb ^ RIcHdtd ^ RIeHVu Hfu Hgth ^ RIeHitiHjtjHktk ^ RIlHmtm ^ RInHoto ^ RIpHqtqHrtr ^ RIsHttt ]'       d   ^ RIuHvtvHwtwHxtx  ! R  R!]P                  ]P                  4      t{ ! R" R#]P                  ]P                  4      t} ! R$ R%]P                  ]P                  4      t ! R& R']P                  ]EP                   4      t ! R( R)]P                  ]EP                  4      tR* R+ lt]9! R,4       ! R- R.]i4      4       tR/ R0 ltR=R1 R2 lltR3 R4 ltR5 R6 ltR>R7 R8 lltR9 R: ltR; R< ltR# )?    )annotations)Callable
Collection	GeneratorHashableIterableSequence)wraps)zip_longest	getsizeof)TYPE_CHECKINGAnyLiteralSelfcastN)
get_option)algosindexlib)
duplicated)AnyAllAnyArrayLikeAxisDropKeepDtypeObjFIgnoreRaise
IndexLabelIndexT
NaPositionScalarShapenpt)function)InvalidIndexErrorPerformanceWarningUnsortedIndexError)cache_readonly
set_module)find_stack_level)coerce_indexer_dtypemaybe_unbox_numpy_scalar)
ensure_int64ensure_platform_intis_hashable
is_integeris_iteratoris_list_likeis_object_dtype	is_scalaris_string_dtypepandas_dtype)CategoricalDtypeExtensionDtype)ABCDataFrame	ABCSeries)is_array_like)array_equivalentisna)validate_putmask)CategoricalExtensionArray)factorize_from_iterablesrecode_for_categories)sanitize_array)Indexensure_indexget_unanimous_names)
FrozenList)make_invalid_op)get_group_indexlexsort_indexer)pprint_thing)CategoricalIndex	DataFrameSeriesc                  6    ] tR t^}tRt]P                  tRtRt	R# )MultiIndexUInt64EnginezManages a MultiIndex by mapping label combinations to positive integers.

The number of possible label combinations must not overflow the 64 bits integers.
uint64 N)
__name__
__module____qualname____firstlineno____doc__libindexUInt64Engine_base_codes_dtype__static_attributes__rS       i/Users/max/.openclaw/workspace/postharvest/venv/lib/python3.14/site-packages/pandas/core/indexes/multi.pyrQ   rQ   }       
 !!ELr^   rQ   c                  6    ] tR t^tRt]P                  tRtRt	R# )MultiIndexUInt32EnginezManages a MultiIndex by mapping label combinations to positive integers.

The number of possible label combinations must not overflow the 32 bits integers.
uint32rS   N)
rT   rU   rV   rW   rX   rY   UInt32Enginer[   r\   r]   rS   r^   r_   rb   rb      r`   r^   rb   c                  6    ] tR t^tRt]P                  tRtRt	R# )MultiIndexUInt16EnginezManages a MultiIndex by mapping label combinations to positive integers.

The number of possible label combinations must not overflow the 16 bits integers.
uint16rS   N)
rT   rU   rV   rW   rX   rY   UInt16Enginer[   r\   r]   rS   r^   r_   rf   rf      r`   r^   rf   c                  6    ] tR t^tRt]P                  tRtRt	R# )MultiIndexUInt8EnginezManages a MultiIndex by mapping label combinations to positive integers.

The number of possible label combinations must not overflow the 8 bits integers.
uint8rS   N)
rT   rU   rV   rW   rX   rY   UInt8Enginer[   r\   r]   rS   r^   r_   rj   rj      s    
   ELr^   rj   c                  6    ] tR t^tRt]P                  tRtRt	R# )MultiIndexPyIntEnginezManages a MultiIndex by mapping label combinations to positive integers.

This class manages those (extreme) cases in which the number of possible
label combinations overflows the 64 bits integers, and uses an ObjectEngine
containing Python integers.
objectrS   N)
rT   rU   rV   rW   rX   rY   ObjectEnginer[   r\   r]   rS   r^   r_   rn   rn      s     !!ELr^   rn   c                    V ^8  d   QhRRRR/# )   methr   returnrS   )formats   "r_   __annotate__rv      s      q Q r^   c                L   a  \        S 4      V 3R l4       p\        \        V4      # )zz
A decorator to allow either `name` or `names` keyword but not both.

This makes it easier to share code with base class.
c                   < R V9   d   RV9   d   \        R4      hR V9   d   VP                  R 4      VR&   S! V .VO5/ VB # )namenamesz*Can only provide one of `names` and `name`)	TypeErrorpop)self_or_clsargskwargsrs   s   &*,r_   new_methnames_compat.<locals>.new_meth   sM    V6 1HIIV$jj0F7OK1$1&11r^   )r
   r   r   )rs   r   s   f r_   names_compatr      s*     4[2 2 8r^   pandasc                    a  ] tR t^t$ Rt]P                  ]! 4       ,          tRt. t	R]
R&   ]! 4       t]! 4       tR.tR]
R&   RR R lltR R ltRR R llt]R]P(                  3R R ll4       t]]RR R ll4       4       t]R]P(                  3R R ll4       t]RR R ll4       t]R R l4       t]R R l4       t]R 4       t]R R l4       tR  R! lt ]R" R# l4       t!]R$ R% l4       t"R&RR'R	R(R
R)R	/R* R+ llt#R&RR)R
/R, R- llt$]R. R/ l4       t%]R0 R1 l4       t&]R2 R3 l4       t'R&RR'R	R(R
R)R	/R4 R5 llt(R&RR)R
/R6 R7 llt)]R8 4       t*]R9 R: l4       t+]P(                  3R; R< llt,R= R> lt-RR? R@ llt.RRA RB llt/RRC RD llt0RE RF lt1]RG RH l4       t2]RI RJ l4       t3RRK RL llt4]RM RN l4       t5RRO RP llt6RQ t7RRRS/RT RU llt8RVR/RW RX llt9RY RZ lt:R&R/R[ R\ llt;]! ];]:R]R^7      t<]R_ R` l4       t=Ra Rb lt>]Rc Rd l4       t?]Re Rf l4       t@RRg Rh lltA]AtBRi tCRRj Rk lltDRRl Rm lltERn Ro ltFRRp ltGR
]P(                  R	3Rq Rr lltHRs Rt ltIRu Rv ltJ]Rw Rx l4       tKRRy Rz lltLR{ R| ltMR} tNR~ tOR R ltPRR R lltQR tRRR/R R lltSRR R lltTRR R lltURR R lltVRR R lltWR R ltXR R ltYR R ltZR R lt[RR R llt\R R lt]R R lt^R R lt_]R R l4       t`R V 3R lltaR V 3R lltbR R ltcR R ltdRR V 3R lllteRR R lltfR R ltgR thRR R lltiRR R lltjRR R lltkR R ltlR R ltmRR R lltnR R ltoR R ltpR V 3R lltqR R ltrR R ltsR ttR R ltuR R ltvR twER R R lltxR tyR R ltzR R lt{R R lt|RR R llt}]P                  t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      t]! R4      tRtV ;t# (  
MultiIndexa(  
A multi-level, or hierarchical, index object for pandas objects.

Parameters
----------
levels : sequence of arrays
    The unique labels for each level.
codes : sequence of arrays
    Integers for each level designating which label at each location.
sortorder : optional int
    Level of sortedness (must be lexicographically sorted by that
    level).
names : optional sequence of objects
    Names for each of the index levels. (name is accepted for compat).
copy : bool, default False
    Copy the meta-data.
name : Label
    Kept for compatibility with 1-dimensional Index. Should not be used.
verify_integrity : bool, default True
    Check that the levels/codes are consistent and valid.

Attributes
----------
names
levels
codes
nlevels
levshape
dtypes

Methods
-------
from_arrays
from_tuples
from_product
from_frame
set_levels
set_codes
to_frame
to_flat_index
sortlevel
droplevel
swaplevel
reorder_levels
remove_unused_levels
get_level_values
get_indexer
get_loc
get_locs
get_loc_level
drop

See Also
--------
MultiIndex.from_arrays  : Convert list of arrays to MultiIndex.
MultiIndex.from_product : Create a MultiIndex from the cartesian product
                          of iterables.
MultiIndex.from_tuples  : Convert list of tuples to a MultiIndex.
MultiIndex.from_frame   : Make a MultiIndex from a DataFrame.
Index : The base pandas Index type.

Notes
-----
See the `user guide
<https://pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html>`__
for more.

Examples
--------
A new ``MultiIndex`` is typically constructed using one of the helper
methods :meth:`MultiIndex.from_arrays`, :meth:`MultiIndex.from_product`
and :meth:`MultiIndex.from_tuples`. For example (using ``.from_arrays``):

>>> arrays = [[1, 1, 2, 2], ["red", "blue", "red", "blue"]]
>>> pd.MultiIndex.from_arrays(arrays, names=("number", "color"))
MultiIndex([(1,  'red'),
            (1, 'blue'),
            (2,  'red'),
            (2, 'blue')],
           names=['number', 'color'])

See further examples for how to construct a MultiIndex in the doc strings
of the mentioned helper methods.

multiindexzlist[Hashable | None]_namesrz   
int | None	sortorderNFTc               $    V ^8  d   QhRRRRRR/# )rr   copyboolverify_integrityrt   r   rS   )ru   s   "r_   rv   MultiIndex.__annotate__)  s*     , , , , 
,r^   c                	4   Ve   TpVe   Vf   \        R4      h\        V4      \        V4      8w  d   \        R4      h\        V4      ^ 8X  d   \        R4      h\        P	                  V 4      p/ Vn        VP                  WRR7       VP                  W%RR7       R .\        V4      ,          Vn        Ve   VP                  V4       Ve   \        V4      Vn        MW8n        V'       d   VP                  4       p	Wn        VP                  4        R Vn        V# )NzMust pass both levels and codesz,Length of levels and codes must be the same.z)Must pass non-zero number of levels/codesF)r   validate)r{   len
ValueErrorro   __new___cache_set_levels
_set_codesr   
_set_namesintr   _verify_integrity_codes_reset_identity_references)
clslevelscodesr   rz   r   ry   r   result	new_codess
   &&&&&&&&  r_   r   MultiIndex.__new__)  s    E>U]=>>v;#e*$KLLv;!HII$ 	6u=%U;V,e$ "9~F(002I%M !r^   c               $    V ^8  d   QhRRRRRR/# )rr   levelrE   code
np.ndarrayrt   rS   )ru   s   "r_   rv   r   W  s!      U *  r^   c                    \        V4      p\        P                  ! V4      '       d   \        P                  ! W2,          RV4      pV# )a;  
Reassign code values as -1 if their corresponding levels are NaN.

Parameters
----------
code : Index
    Code to reassign.
level : np.ndarray
    Level to check for missing values (NaN, NaT, None).

Returns
-------
new code where code value = -1 if it corresponds
to a level with missing values (NaN, NaT, None).
)r>   npanywhere)selfr   r   	null_masks   &&& r_   _validate_codesMultiIndex._validate_codesW  s5      K	66)88IOR6Dr^   c               (    V ^8  d   QhRRRRRRRR/# )rr   r   zlist | Noner   levels_to_verifyzlist[int] | range | Nonert   rH   rS   )ru   s   "r_   rv   r   l  s8     L LL L 3	L
 
Lr^   c                   T;'       g    V P                   pT;'       g    V P                  pVf   \        \        V4      4      p\        V4      \        V4      8w  d   \	        R4      h\        V^ ,          4      pV EF  pW%,          pW,          p\        V4      V8w  d(   \	        RV Uu. uF  p\        V4      NK  	  up 24      h\        V4      '       dK   VP                  4       \        V4      8  d-   \	        RV RVP                  4        R\        V4       R24      h\        V4      '       d6   VP                  4       R8  d!   \	        RV RVP                  4        R24      hVP                  '       d   EK  \	        R	\        V4       R
V 24      h	  V P                  ei   V P                  \        V P                   V P                  4      8  d:   \	        RV P                   R\        V P                   V P                  4       24      h. p	\        \        V4      4       FO  pWS9   d0   V	P                  V P                  W%,          W,          4      4       K8  V	P                  W,          4       KQ  	  \        V	4      p
V
# u upi )a  
Parameters
----------
codes : optional list
    Codes to check for validity. Defaults to current codes.
levels : optional list
    Levels to check for validity. Defaults to current levels.
levels_to_validate: optional list
    Specifies the levels to verify.

Raises
------
ValueError
    If length of levels and codes don't match, if the codes for any
    level would exceed level bounds, or there are any duplicate levels.

Returns
-------
new codes where code value = -1 if it corresponds to a
NaN level.
zTLength of levels and codes must match. NOTE: this index is in an inconsistent state.zUnequal code lengths: z	On level z, code max (z) >= length of level (z/). NOTE: this index is in an inconsistent statez, code value (z) < -1zLevel values must be unique: z
 on level zQValue for sortorder must be inferior or equal to actual lexsort_depth: sortorder z with lexsort_depth r   )r   r   ranger   r   maxmin	is_uniquelistr   _lexsort_depthnlevelsappendr   rH   )r   r   r   r   codes_lengthir   level_codescode_result_codesr   s   &&&&       r_   r   MultiIndex._verify_integrityl  sI   : ##&&4;;#$S[1v;#e*$:  58}!AIE(K;</ ,e-LeUc%je-L,MN  ;KOO$5U$C s,{/@.A B!%j\ *)) 
 ;KOO$5$: 9QC~koo>O=PPV!WXX??? 3DK=
1#N # "( >>%~~tzz4<< HH 004/? @**8T\\*R)SU  s6{#A$##D$8$8EH$MN##EH-	 $ |,	= .Ms   +Jc               $    V ^8  d   QhRRRRRR/# )rr   r   r   rz   -Sequence[Hashable] | Hashable | lib.NoDefaultrt   r   rS   )ru   s   "r_   rv   r     s/     D
 D
 D
 =	D

 
D
r^   c                   Rp\        V4      '       g   \        V4      h\        V4      '       d   \        V4      pV F  p\        V4      '       d   K  \        V4      h	  \	        ^\        V4      4       F:  p\        W,          4      \        W^,
          ,          4      8w  g   K1  \        R4      h	  \        V4      w  rxV\        P                  J d   V U	u. uF  p	\        V	RR4      NK  	  pp	V ! VVVVRR7      # u up	i )a  
Convert arrays to MultiIndex.

Parameters
----------
arrays : list / sequence of array-likes
    Each array-like gives one level's value for each data point.
    len(arrays) is the number of levels.
sortorder : int or None
    Level of sortedness (must be lexicographically sorted by that
    level).
names : list / sequence of str, optional
    Names for the levels in the index.

Returns
-------
MultiIndex

See Also
--------
MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
MultiIndex.from_product : Make a MultiIndex from cartesian product
                          of iterables.
MultiIndex.from_frame : Make a MultiIndex from a DataFrame.

Examples
--------
>>> arrays = [[1, 1, 2, 2], ["red", "blue", "red", "blue"]]
>>> pd.MultiIndex.from_arrays(arrays, names=("number", "color"))
MultiIndex([(1,  'red'),
            (1, 'blue'),
            (2,  'red'),
            (2, 'blue')],
           names=['number', 'color'])
z/Input must be a list / sequence of array-likes.zall arrays must be same lengthry   NFr   r   r   rz   r   )r3   r{   r2   r   r   r   r   rB   r   
no_defaultgetattr)
r   arraysr   rz   	error_msgarrayr   r   r   arrs
   &&&&      r_   from_arraysMultiIndex.from_arrays  s    T F	F##I&&v&\F E&&	**  q#f+&A69~VE]!33 !ABB ' 18CNN";AB6CWS&$/6EB"
 	
 Cs   C=c               (    V ^8  d   QhRRRRRRRR/# )	rr   tupleszIterable[tuple[Hashable, ...]]r   r   rz   $Sequence[Hashable] | Hashable | Nonert   r   rS   )ru   s   "r_   rv   r     s>     LI LI.LI LI 4	LI
 
LIr^   c                   \        V4      '       g   \        R4      h\        V4      '       d   \        V4      p\	        \
        \        \        R3,          ,          V4      p\        V4      '       d   \        ;QJ d    R V 4       F  '       d   K   RM	  RM! R V 4       4      '       dd   \        P                  ! \        V4      4      .p\        \        P                  ! V\        P                  ! R4      R7      4      .pV ! VVVVRR7      # \        V4      ^ 8X  d%   Vf   \        R	4      h. .\        V4      ,          pEM\!        V\        P"                  \        34      '       da   \!        V\        4      '       d!   \        P$                  ! VP&                  4      p\        \(        P*                  ! V4      P,                  4      pM\!        V\        4      '       d+   \        \(        P.                  ! V4      P,                  4      pM?\1        VR
\        P2                  / p\	        \        \4        \        ,          ,          V4      pV P7                  WbVR7      # )a  
Convert list of tuples to MultiIndex.

Parameters
----------
tuples : list / sequence of tuple-likes
    Each tuple is the index of one row/column.
sortorder : int or None
    Level of sortedness (must be lexicographically sorted by that
    level).
names : list / sequence of str, optional
    Names for the levels in the index.

Returns
-------
MultiIndex

See Also
--------
MultiIndex.from_arrays : Convert list of arrays to MultiIndex.
MultiIndex.from_product : Make a MultiIndex from cartesian product
                          of iterables.
MultiIndex.from_frame : Make a MultiIndex from a DataFrame.

Examples
--------
>>> tuples = [(1, "red"), (1, "blue"), (2, "red"), (2, "blue")]
>>> pd.MultiIndex.from_tuples(tuples, names=("number", "color"))
MultiIndex([(1,  'red'),
            (1, 'blue'),
            (2,  'red'),
            (2, 'blue')],
           names=['number', 'color'])
z/Input must be a list / sequence of tuple-likes..c              3  `   "   T F$  p\        V\        4      ;'       d    V'       * x  K&  	  R # 5iN)
isinstancetuple).0es   & r_   	<genexpr>)MultiIndex.from_tuples.<locals>.<genexpr>2  s$     Nv!z!U3==A=vs   ..FTro   dtyper   z-Cannot infer number of levels from empty list	fillvaluer   rz   )r3   r{   r2   r   r   r   r   r   r   allr   zerosrE   comasarray_tuplesafer   r   ndarrayasarray_valuesr   tuples_to_object_arrayTto_object_array_tuplesr   nanr	   r   )r   r   r   rz   r   r   r   arrss   &&&&    r_   from_tuplesMultiIndex.from_tuples  s   T F##MNNv&\Fjx}!56? v;;33NvN333NvNNNXXc&k*+EC11&@RSTUF#!&  v;!} OPP TCJ&FU 344&%((FNN3#44V<>>?F%%#44V<>>?F9"&&9D$x12D9Fv%HHr^   c               (    V ^8  d   QhRRRRRRRR/# )	rr   	iterableszSequence[Iterable[Hashable]]r   r   rz   r   rt   r   rS   )ru   s   "r_   rv   r   R  s8     8D 8D/8D 8D =	8D
 
8Dr^   c                    \        V4      '       g   \        R4      h\        V4      '       d   \        V4      p\	        V4      w  rEV\
        P                  J d   V Uu. uF  p\        VRR4      NK  	  pp\        V4      pV ! WTW#R7      # u upi )aE  
Make a MultiIndex from the cartesian product of multiple iterables.

Parameters
----------
iterables : list / sequence of iterables
    Each iterable has unique labels for each level of the index.
sortorder : int or None
    Level of sortedness (must be lexicographically sorted by that
    level).
names : list / sequence of str, optional
    Names for the levels in the index.
    If not explicitly provided, names will be inferred from the
    elements of iterables if an element has a name attribute.

Returns
-------
MultiIndex

See Also
--------
MultiIndex.from_arrays : Convert list of arrays to MultiIndex.
MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
MultiIndex.from_frame : Make a MultiIndex from a DataFrame.

Examples
--------
>>> numbers = [0, 1, 2]
>>> colors = ["green", "purple"]
>>> pd.MultiIndex.from_product([numbers, colors], names=["number", "color"])
MultiIndex([(0,  'green'),
            (0, 'purple'),
            (1,  'green'),
            (1, 'purple'),
            (2,  'green'),
            (2, 'purple')],
           names=['number', 'color'])
z-Input must be a list / sequence of iterables.ry   Nr   )	r3   r{   r2   r   rB   r   r   r   cartesian_product)r   r   r   rz   r   r   its   &&&&   r_   from_productMultiIndex.from_productQ  s    \ I&&KLLy!!YI0;CNN"9BC2WR.EC "%(6ICC	 Ds   Bc               (    V ^8  d   QhRRRRRRRR/# )	rr   dfrN   r   r   rz   r   rt   r   rS   )ru   s   "r_   rv   r     s>     CJ CJCJ CJ 4	CJ
 
CJr^   c                    \        V\        4      '       g   \        R4      h\        VP	                  4       RR/ w  rEVf   TMTpV P                  WRVR7      # )a  
Make a MultiIndex from a DataFrame.

Parameters
----------
df : DataFrame
    DataFrame to be converted to MultiIndex.
sortorder : int, optional
    Level of sortedness (must be lexicographically sorted by that
    level).
names : list-like, optional
    If no names are provided, use the column names, or tuple of column
    names if the columns is a MultiIndex. If a sequence, overwrite
    names with the given sequence.

Returns
-------
MultiIndex
    The MultiIndex representation of the given DataFrame.

See Also
--------
MultiIndex.from_arrays : Convert list of arrays to MultiIndex.
MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
MultiIndex.from_product : Make a MultiIndex from cartesian product
                          of iterables.

Examples
--------
>>> df = pd.DataFrame(
...     [["HI", "Temp"], ["HI", "Precip"], ["NJ", "Temp"], ["NJ", "Precip"]],
...     columns=["a", "b"],
... )
>>> df
      a       b
0    HI    Temp
1    HI  Precip
2    NJ    Temp
3    NJ  Precip

>>> pd.MultiIndex.from_frame(df)
MultiIndex([('HI',   'Temp'),
            ('HI', 'Precip'),
            ('NJ',   'Temp'),
            ('NJ', 'Precip')],
           names=['a', 'b'])

Using explicit names, instead of the column names

>>> pd.MultiIndex.from_frame(df, names=["state", "observation"])
MultiIndex([('HI',   'Temp'),
            ('HI', 'Precip'),
            ('NJ',   'Temp'),
            ('NJ', 'Precip')],
           names=['state', 'observation'])
zInput must be a DataFramestrictTr   )r   r:   r{   zipitemsr   )r   r   r   rz   column_namescolumnss   &&&&  r_   
from_frameMultiIndex.from_frame  sT    ~ "l++788 #RXXZ = = %5w5IIr^   c                   V ^8  d   QhRR/# rr   rt   r   rS   )ru   s   "r_   rv   r     s       r^   c                	   . p\        V P                  4       EF  pV P                  V,          pV P                  V,          pTp\	        VP
                  \        4      '       d'   \        R V4      pVP                  P                  4       p\	        VP
                  \        4      '       g(   \        P                  ! VP
                  R4      '       d   VP                  \        4      p\        P                   ! V4      p\"        P$                  ! WdVP&                  R7      pVP)                  V4       EK  	  \        P*                  ! V4      pV# )rM   mM
fill_value)r   r   r   r   r   r   r8   r   _data_internal_get_valuesr9   r   is_np_dtypeastypero   r   r   r   take_nd	_na_valuer   fast_zip)r   valuesr   r   r   vals
array_valsr   s   &       r_   r   MultiIndex._values  s     t||$AKKNEJJqMED$**&677.5zz668$**n55

D: : {{6*D)JzU__UJMM*%! %$ ll6"
r^   c                   V ^8  d   QhRR/# r   rS   )ru   s   "r_   rv   r     s      
 r^   c                	    V P                   # r   r   r   s   &r_   r	  MultiIndex.values  s    ||r^   c                    \        R4      h)zv
Raises a ValueError for `MultiIndex` because there's no single
array backing a MultiIndex.

Raises
------
ValueError
zcMultiIndex has no single backing array. Use 'MultiIndex.to_numpy()' to get a NumPy array of tuples.)r   r  s   &r_   r   MultiIndex.array  s     F
 	
r^   c                   V ^8  d   QhRR/# )rr   rt   rO   rS   )ru   s   "r_   rv   r     s     R R Rr^   c                    ^ RI Hp \        P                  ! V P                  4      pT! V P
                   Uu. uF  q3P                  NK  	  up\        V4      R7      # u upi )aa  
Return the dtypes as a Series for the underlying MultiIndex.

See Also
--------
Index.dtype : Return the dtype object of the underlying data.
Series.dtypes : Return the data type of the underlying Series.

Examples
--------
>>> idx = pd.MultiIndex.from_product(
...     [(0, 1, 2), ("green", "purple")], names=["number", "color"]
... )
>>> idx
MultiIndex([(0,  'green'),
            (0, 'purple'),
            (1,  'green'),
            (1, 'purple'),
            (2,  'green'),
            (2, 'purple')],
           names=['number', 'color'])
>>> idx.dtypes
number     int64
color     object
dtype: object
)rO   )r   )r   rO   r   fill_missing_namesrz   r   r   rE   )r   rO   rz   r   s   &   r_   dtypesMultiIndex.dtypes  sD    8 	"&&tzz2<u{{<E%LQQ<s   Ac                   V ^8  d   QhRR/# rr   rt   r   rS   )ru   s   "r_   rv   r   "  s     " " "r^   c                	:    \        V P                  ^ ,          4      # r   )r   r   r  s   &r_   __len__MultiIndex.__len__"  s    4::a=!!r^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r   &  s      c r^   c                    \        V 4      # )z7
Return the number of elements in the underlying data.
r   r  s   &r_   sizeMultiIndex.size%  s     4yr^   c                   V ^8  d   QhRR/# rr   rt   rH   rS   )ru   s   "r_   rv   r   1  s     B" B"
 B"r^   c                    \        V P                  V P                  RR7       UUu. uF  w  rVP                  VR7      NK  	  pppV F
  pRVn        K  	  \        V4      # u uppi )aw  
Levels of the MultiIndex.

Levels refer to the different hierarchical levels or layers in a MultiIndex.
In a MultiIndex, each level represents a distinct dimension or category of
the index.

To access the levels, you can use the levels attribute of the MultiIndex,
which returns a tuple of Index objects. Each Index object represents a
level in the MultiIndex and contains the unique values found in that
specific level.

If a MultiIndex is created with levels A, B, C, and the DataFrame using
it filters out all rows of the level C, MultiIndex.levels will still
return A, B, C.

See Also
--------
MultiIndex.codes : The codes of the levels in the MultiIndex.
MultiIndex.get_level_values : Return vector of label values for requested
    level.

Examples
--------
>>> index = pd.MultiIndex.from_product(
...     [["mammal"], ("goat", "human", "cat", "dog")],
...     names=["Category", "Animals"],
... )
>>> leg_num = pd.DataFrame(data=(4, 2, 4, 4), index=index, columns=["Legs"])
>>> leg_num
                  Legs
Category Animals
mammal   goat        4
         human       2
         cat         4
         dog         4

>>> leg_num.index.levels
FrozenList([['mammal'], ['cat', 'dog', 'goat', 'human']])

MultiIndex levels will not change even if the DataFrame using the MultiIndex
does not contain all them anymore.
See how "human" is not in the DataFrame, but it is still in levels:

>>> large_leg_num = leg_num[leg_num.Legs > 2]
>>> large_leg_num
                  Legs
Category Animals
mammal   goat        4
         cat         4
         dog         4

>>> large_leg_num.index.levels
FrozenList([['mammal'], ['cat', 'dog', 'goat', 'human']])
Tr   ry   )r   _levelsr   _rename_no_setting_namerH   )r   xry   r   r   s   &    r_   r   MultiIndex.levels0  si    | t||T[[F
F II4I F 	 
 E%)E"  &!!
s   A!r   r   r   r   c               (    V ^8  d   QhRRRRRRRR/# rr   r   r   r   r   rt   NonerS   )ru   s   "r_   rv   r   u  s4     + +
 + + + 
+r^   c               	  a V'       dm   \        V4      ^ 8X  d   \        R4      hVf&   \        V4      V P                  8w  d   \        R4      hVe%   \        V4      \        V4      8w  d   \        R4      hVf+   \        V3R lV 4       4      p\	        \        V4      4      pMrV Uu. uF  qP                  V4      NK  	  pp\        V P                  4      p	\        WqRR7       F"  w  r\        VSR7      P                  4       W&   K$  	  \        V	4      pV'       d   V P                  WgR	7      pWn        V P                  pW`n        \        V4      '       d   V P                  V4       V P!                  4        R# u upi )
r   z#Must set non-zero number of levels.Nz-Length of levels must match number of levels.z,Length of levels must match length of level.c              3  Z   <"   T F   p\        VSR 7      P                  4       x  K"  	  R# 5ir   N)rF   _view)r   levr   s   & r_   r   )MultiIndex._set_levels.<locals>.<genexpr>  s'      $@FSt,2244s   (+Tr'  r4  )r   r   )r   r   r   rH   r   _get_level_numberr   r)  r   rF   r5  r   r   rz   r   r   _reset_cache)r   r   r   r   r   r   
new_levelslevel_numbersr6  new_levels_listlev_numr   rz   s   &&$d$$       r_   r   MultiIndex._set_levelsu  sE    6{a !FGG}V!< !PQQ S[CJ%> !OPP=# $@F$ J 05S_/EMDIJES33C8EMJ"4<<0O #M$ G+7$+G+M+M+O( !H#O4J..! / I $K

!u::OOE"# Ks   (E<c                    V ^8  d   QhRRRR/# rr   r   r   rt   r   rS   )ru   s   "r_   rv   r     s      u u7;u	ur^   c               *   \        V\        4      '       d   M9\        V4      '       d   \        V4      pM\        V4      '       d   \	        V4      p\        W!R4      w  r!V P                  4       pVP                  4        VP                  WRVR7       V# )a  
Set new levels on MultiIndex. Defaults to returning new index.

The `set_levels` method provides a flexible way to change the levels of a
`MultiIndex`. This is particularly useful when you need to update the
index structure of your DataFrame without altering the data. The method
returns a new `MultiIndex` unless the operation is performed in-place,
ensuring that the original index remains unchanged unless explicitly
modified.

The method checks the integrity of the new levels against the existing
codes by default, but this can be disabled if you are confident that
your levels are consistent with the underlying data. This can be useful
when you want to perform optimizations or make specific adjustments to
the index levels that do not strictly adhere to the original structure.

Parameters
----------
levels : sequence or list of sequence
    New level(s) to apply.
level : int, level name, or sequence of int/level names (default None)
    Level(s) to set (None for all levels).
verify_integrity : bool, default True
    If True, checks that levels and codes are compatible.

Returns
-------
MultiIndex
    A new `MultiIndex` with the updated levels.

See Also
--------
MultiIndex.set_codes : Set new codes on the existing `MultiIndex`.
MultiIndex.remove_unused_levels : Create new MultiIndex from current that
    removes unused levels.
Index.set_names : Set Index or MultiIndex name.

Examples
--------
>>> idx = pd.MultiIndex.from_tuples(
...     [
...         (1, "one"),
...         (1, "two"),
...         (2, "one"),
...         (2, "two"),
...         (3, "one"),
...         (3, "two"),
...     ],
...     names=["foo", "bar"],
... )
>>> idx
MultiIndex([(1, 'one'),
    (1, 'two'),
    (2, 'one'),
    (2, 'two'),
    (3, 'one'),
    (3, 'two')],
   names=['foo', 'bar'])

>>> idx.set_levels([["a", "b", "c"], [1, 2]])
MultiIndex([('a', 1),
            ('a', 2),
            ('b', 1),
            ('b', 2),
            ('c', 1),
            ('c', 2)],
           names=['foo', 'bar'])
>>> idx.set_levels(["a", "b", "c"], level=0)
MultiIndex([('a', 'one'),
            ('a', 'two'),
            ('b', 'one'),
            ('b', 'two'),
            ('c', 'one'),
            ('c', 'two')],
           names=['foo', 'bar'])
>>> idx.set_levels(["a", "b"], level="bar")
MultiIndex([(1, 'a'),
            (1, 'b'),
            (2, 'a'),
            (2, 'b'),
            (3, 'a'),
            (3, 'b')],
           names=['foo', 'bar'])

If any of the levels passed to ``set_levels()`` exceeds the
existing length, all of the values from that argument will
be stored in the MultiIndex levels, though the values will
be truncated in the MultiIndex output.

>>> idx.set_levels([["a", "b", "c"], [1, 2, 3, 4]], level=[0, 1])
MultiIndex([('a', 1),
    ('a', 2),
    ('b', 1),
    ('b', 2),
    ('c', 1),
    ('c', 2)],
   names=['foo', 'bar'])
>>> idx.set_levels([["a", "b", "c"], [1, 2, 3, 4]], level=[0, 1]).levels
FrozenList([['a', 'b', 'c'], [1, 2, 3, 4]])
LevelsT)r   r   r   )	r   rE   r<   r3   r   _require_listliker5  r   r   )r   r   r   r   idxs   &&$$ r_   
set_levelsMultiIndex.set_levels  s    P fe$$6""6]F&!!&\F)%Bjjl$AQ 	 	
 
r^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     ! ! !r^   c                ,    \        V P                  4      # )a  
Integer number of levels in this MultiIndex.

See Also
--------
MultiIndex.levels : Get the levels of the MultiIndex.
MultiIndex.codes : Get the codes of the MultiIndex.
MultiIndex.from_arrays : Convert arrays to MultiIndex.
MultiIndex.from_tuples : Convert list of tuples to MultiIndex.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a"], ["b"], ["c"]])
>>> mi
MultiIndex([('a', 'b', 'c')],
           )
>>> mi.nlevels
3
)r   r)  r  s   &r_   r   MultiIndex.nlevels  s    * 4<<  r^   c                   V ^8  d   QhRR/# )rr   rt   r#   rS   )ru   s   "r_   rv   r   1  s     2 2% 2r^   c                    \         ;QJ d    . R V P                   4       F  NK  	  5# ! R V P                   4       4      # )a  
A tuple representing the length of each level in the MultiIndex.

In a `MultiIndex`, each level can contain multiple unique values. The
`levshape` property provides a quick way to assess the size of each
level by returning a tuple where each entry represents the number of
unique values in that specific level. This is particularly useful in
scenarios where you need to understand the structure and distribution
of your index levels, such as when working with multidimensional data.

See Also
--------
MultiIndex.shape : Return a tuple of the shape of the MultiIndex.
MultiIndex.levels : Returns the levels of the MultiIndex.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a"], ["b"], ["c"]])
>>> mi
MultiIndex([('a', 'b', 'c')],
           )
>>> mi.levshape
(1, 1, 1)
c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   r!  r   r,  s   & r_   r   &MultiIndex.levshape.<locals>.<genexpr>J  s     1[SVV[   )r   r   r  s   &r_   levshapeMultiIndex.levshape0  s.    4 u1T[[1u1u1T[[111r^   c                   V ^8  d   QhRR/# r%  rS   )ru   s   "r_   rv   r   P  s      z r^   c                    V P                   # )a  
Codes of the MultiIndex.

Codes are the position of the index value in the list of level values
for each level.

Returns
-------
tuple of numpy.ndarray
    The codes of the MultiIndex. Each array in the tuple corresponds
    to a level in the MultiIndex.

See Also
--------
MultiIndex.set_codes : Set new codes on MultiIndex.

Examples
--------
>>> arrays = [[1, 1, 2, 2], ["red", "blue", "red", "blue"]]
>>> mi = pd.MultiIndex.from_arrays(arrays, names=("number", "color"))
>>> mi.codes
FrozenList([[0, 0, 1, 1], [1, 0, 1, 0]])
)r   r  s   &r_   r   MultiIndex.codesO  s    2 {{r^   c               (    V ^8  d   QhRRRRRRRR/# r/  rS   )ru   s   "r_   rv   r   j  s4     ' '
 ' ' ' 
'r^   c          	     	  a V'       dR   Vf&   \        V4      V P                  8w  d   \        R4      hVe%   \        V4      \        V4      8w  d   \        R4      hVfA   \        V3R l\	        V P
                  VRR7       4       4      p\        \        V4      4      pMwV Uu. uF  qP                  V4      NK  	  pp\        V P                  4      p	\	        WqRR7       F'  w  rV P                  V
,          p\        WSR7      W&   K)  	  \        V	4      pV'       d   V P                  WgR7      pW`n	        V P                  4        R # u upi )Nz+Length of codes must match number of levelsz,Length of codes must match length of levels.c              3  ^   <"   T F"  w  r\        W!SR 7      P                  4       x  K$  	  R# 5ir3  )_coerce_indexer_frozenview)r   r6  r   r   s   &  r_   r   (MultiIndex._set_codes.<locals>.<genexpr>{  s.      #(M$C '{dCHHJJ(Ms   *-Tr'  r4  )r   r   )r   r   r   rH   r   r)  r   r8  r   r   r   rX  r   r9  )r   r   r   r   r   r   r   r;  r6  new_codes_listr=  r   s   &&$d$$      r_   r   MultiIndex._set_codesj  s$    }Ut||!; !NOO SZ3u:%= !OPP =" #(+DLL%(M# I "#i.1MDIJES33C8EMJ!$++.N(+M(N$kk'**@4+' )O
 #>2I.. / I  ! Ks   #Ec                    V ^8  d   QhRRRR/# r@  rS   )ru   s   "r_   rv   r     s      D D6:D	Dr^   c                   \        W!R4      w  r!V P                  4       pVP                  4        VP                  WVR7       V# )ai  
Set new codes on MultiIndex. Defaults to returning new index.

Parameters
----------
codes : sequence or list of sequence
    New codes to apply.
level : int, level name, or sequence of int/level names (default None)
    Level(s) to set (None for all levels).
verify_integrity : bool, default True
    If True, checks that levels and codes are compatible.

Returns
-------
new index (of same type and class...etc) or None
    The same type as the caller or None if ``inplace=True``.

See Also
--------
MultiIndex.set_levels : Set new levels on MultiIndex.
MultiIndex.codes : Get the codes of the levels in the MultiIndex.
MultiIndex.levels : Get the levels of the MultiIndex.

Examples
--------
>>> idx = pd.MultiIndex.from_tuples(
...     [(1, "one"), (1, "two"), (2, "one"), (2, "two")], names=["foo", "bar"]
... )
>>> idx
MultiIndex([(1, 'one'),
    (1, 'two'),
    (2, 'one'),
    (2, 'two')],
   names=['foo', 'bar'])

>>> idx.set_codes([[1, 0, 1, 0], [0, 0, 1, 1]])
MultiIndex([(2, 'one'),
            (1, 'one'),
            (2, 'two'),
            (1, 'two')],
           names=['foo', 'bar'])
>>> idx.set_codes([1, 0, 1, 0], level=0)
MultiIndex([(2, 'one'),
            (1, 'two'),
            (2, 'one'),
            (1, 'two')],
           names=['foo', 'bar'])
>>> idx.set_codes([0, 0, 1, 1], level="bar")
MultiIndex([(1, 'one'),
            (1, 'one'),
            (2, 'two'),
            (2, 'two')],
           names=['foo', 'bar'])
>>> idx.set_codes([[1, 0, 1, 0], [0, 0, 1, 1]], level=[0, 1])
MultiIndex([(2, 'one'),
            (1, 'one'),
            (2, 'two'),
            (1, 'two')],
           names=['foo', 'bar'])
Codes)r   r   )rC  r5  r   r   )r   r   r   r   rD  s   &&$$ r_   	set_codesMultiIndex.set_codes  s@    @ )w?jjlu<LM
r^   c           
     	   \         P                  ! \         P                  ! V P                   Uu. uF#  p\	        V4      \
        P                  ,           NK%  	  up4      4      p\         P                  ! VR R R1,          4      R R R1,          p\         P                  ! VR,          ^ ..4      pVP                  \         P                  ! \        V^ ,          4      4      4      pV^ ,          ^@8  d"   \        V P                  V P                  V4      # V^ ,          ^ 8  d"   \        V P                  V P                  V4      # V^ ,          ^8  d"   \        V P                  V P                  V4      # V^ ,          ^8  d"   \!        V P                  V P                  V4      # \#        V P                  V P                  V4      # u upi )N   NNr   )r   ceillog2r   r   rY   multiindex_nulls_shiftcumsumconcatenater  min_scalar_typer   rn   r   rQ   rb   rf   rj   )r   r   sizeslev_bitsoffsetss   &    r_   _engineMultiIndex._engine  sM    GGKO;;W;%Uh====;W
 99U4R4[)$B$/ ..(2,!45..!3!3C
O!DE A;(djj'JJA;)$++tzz7KKA;)$++tzz7KKA;?)$++tzz7KK$T[[$**gFF= Xs   )F?c                   V ^8  d   QhRR/# )rr   rt   zCallable[..., MultiIndex]rS   )ru   s   "r_   rv   r     s     & &7 &r^   c                	,    \        V 4      P                  # r   )typer   r  s   &r_   _constructorMultiIndex._constructor  s    Dz%%%r^   c                    V ^8  d   QhRRRR/# )rr   r	  r   rt   r   rS   )ru   s   "r_   rv   r   
  s     K KJ K
 Kr^   c                    V\         P                  Jd   TMV P                  p\        V 4      P	                  VRVR7      # )a2  
Create a new Index with the same class as the caller, don't copy the
data, use the same object attributes with passed in attributes taking
precedence.

*this is an internal non-public method*

Parameters
----------
values : the values to create the new Index, optional
name : Label, defaults to self.name
Nr   )r   r   rz   rr  r   )r   r	  ry   rz   s   &&& r_   _shallow_copyMultiIndex._shallow_copy
  s6     CNN2

Dz%%fE%JJr^   c                   V ^8  d   QhRR/# rr   rt   r   rS   )ru   s   "r_   rv   r     s     
 
z 
r^   c                	    \        V 4      ! V P                  V P                  V P                  V P                  R R7      pV P
                  P                  4       Vn        VP                  R4       V# )Fr   r   )rr  r   r   r   rz   r   r   r9  )r   r   s   & r_   r5  MultiIndex._view  sX    d;;**nn**"
 ((*H%r^   c                    V ^8  d   QhRRRR/# )rr   deepr   rt   r   rS   )ru   s   "r_   rv   r   *  s$     O O O
 
Or^   c                   V P                  W1VR7      pV'       * pRRreV'       d+   ^ RIHp V! V P                  4      pV! V P                  4      pVe   TMV P                  pVe   TMV P                  p\        V 4      ! VVV P                  VRR7      pV P                  P                  4       Vn        VP                  R4       V'       d   V P                  Vn	        V# )a7  
Make a copy of this object. Names, dtype, levels and codes can be passed and         will be set on new copy.

The `copy` method provides a mechanism to create a duplicate of an
existing MultiIndex object. This is particularly useful in scenarios where
modifications are required on an index, but the original MultiIndex should
remain unchanged. By specifying the `deep` parameter, users can control
whether the copy should be a deep or shallow copy, providing flexibility
depending on the size and complexity of the MultiIndex.

Parameters
----------
names : sequence, optional
    Names to set on the new MultiIndex object.
deep : bool, default False
    If False, the new object will be a shallow copy. If True, a deep copy
    will be attempted. Deep copying can be potentially expensive for large
    MultiIndex objects.
name : Label
    Kept for compatibility with 1-dimensional Index. Should not be used.

Returns
-------
MultiIndex
    A new MultiIndex object with the specified modifications.

See Also
--------
MultiIndex.from_arrays : Convert arrays to MultiIndex.
MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
MultiIndex.from_frame : Convert DataFrame to MultiIndex.

Notes
-----
In most cases, there should be no functional difference from using
``deep``, but if ``deep`` is passed it will attempt to deepcopy.
This could be potentially expensive on large MultiIndex objects.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a"], ["b"], ["c"]])
>>> mi
MultiIndex([('a', 'b', 'c')],
           )
>>> mi.copy()
MultiIndex([('a', 'b', 'c')],
           )
)ry   rz   r~  N)deepcopyFr   r   )
_validate_namesr   r  r   r   rr  r   r   r9  _id)	r   rz   r~  ry   keep_idr   r   r  	new_indexs	   &&&&     r_   r   MultiIndex.copy*  s    n $$$$$G(d%dkk*FTZZ(E!-4;;*

Jnn"
	  ;;++-	x( HHIMr^   c                   V ^8  d   QhRR/# r   rS   )ru   s   "r_   rv   r   {  s      * r^   c                    VRJ d   \        R4      hVRJ d#   \        P                  ! V P                  VR7      # V P                  # )z%the array interface, return my valuesFz:Unable to avoid copy while creating an array as requested.Tr   )r   r   r   r	  )r   r   r   s   &&&r_   	__array__MultiIndex.__array__{  sC    5=L  4< 88DKKu55{{r^   c                   V ^8  d   QhRR/# )rr   rt   r   rS   )ru   s   "r_   rv   r     s       r^   c                H    V P                  4       pV P                  Vn        V# )z0this is defined as a copy with the same identity)r   r  )r   r   r   s   && r_   rY  MultiIndex.view  s    XX
r^   c                    V ^8  d   QhRRRR/# )rr   keyr   rt   r   rS   )ru   s   "r_   rv   r     s     ) ) ) )r^   c                z    \        V4        V P                  V4       R#   \        \        \        3 d     R# i ; i)a>  
Return a boolean indicating whether the provided key is in the index.

Parameters
----------
key : label
    The key to check if it is present in the index.

Returns
-------
bool
    Whether the key search is in the index.

Raises
------
TypeError
    If the key is not hashable.

See Also
--------
Index.isin : Returns an ndarray of boolean dtype indicating whether the
    list-like key is in the index.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a"], ["b"], ["c"]])
>>> mi
MultiIndex([('a', 'b', 'c')],
           )

>>> "a" in mi
True
>>> "x" in mi
False
TF)hashget_locLookupErrorr{   r   r   r  s   &&r_   __contains__MultiIndex.__contains__  s9    H 	S		LLY
3 		s     ::c                   V ^8  d   QhRR/# )rr   rt   znp.dtyperS   )ru   s   "r_   rv   r     s      x r^   c                	.    \         P                  ! R 4      # )O)r   r   r  s   &r_   r   MultiIndex.dtype  s    xx}r^   c                   V ^8  d   QhRR/# rr   rt   r   rS   )ru   s   "r_   rv   r     s     < <D <r^   c                   a R R lo\         ;QJ d)    V3R lV P                   4       F  '       g   K   R# 	  R# ! V3R lV P                   4       4      # )z5return a boolean if we need a qualified .info displayc                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   ;MultiIndex._is_memory_usage_qualified.<locals>.__annotate__  s     	 	 	r^   c                l    \        V 4      ;'       g#    \        V 4      ;'       d    V P                  R 8H  # )python)r4   r6   storager   s   &r_   f0MultiIndex._is_memory_usage_qualified.<locals>.f  s2    "5)  &DD5==H+Dr^   c              3  H   <"   T F  pS! VP                   4      x  K  	  R # 5ir   r   )r   r   r  s   & r_   r   8MultiIndex._is_memory_usage_qualified.<locals>.<genexpr>  s     ;{e1U[[>>{s   "TF)r   r   )r   r  s   &@r_   _is_memory_usage_qualified%MultiIndex._is_memory_usage_qualified  s;    	
 s;t{{;ss;s;s;t{{;;;r^   c                    V ^8  d   QhRRRR/# rr   r~  r   rt   r   rS   )ru   s   "r_   rv   r     s     "" "" ""# ""r^   c                $    V P                  V4      # )ab  
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
    Returns memory usage of the values in the Index in bytes.

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
--------
>>> mi = pd.MultiIndex.from_arrays([["a"], ["b"], ["c"]])
>>> mi.memory_usage()
81
_nbytes)r   r~  s   &&r_   memory_usageMultiIndex.memory_usage  s    D ||D!!r^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     # # #r^   c                $    V P                  R4      # )z1return the number of bytes in the underlying dataFr  r  s   &r_   nbytesMultiIndex.nbytes  s     ||E""r^   c                    V ^8  d   QhRRRR/# r  rS   )ru   s   "r_   rv   r     s      D S r^   c                F  aa ^o\        V3R lV P                   4       4      p\        R V P                   4       4      p\        V3R lV P                   4       4      pW#,           V,           pRV P                  9   d#   WPP
                  P                  SR7      ,          pV# )z
return the number of bytes in the underlying data
deeply introspect the level data if deep=True

include the engine hashtable

*this is in internal routine*

c              3  F   <"   T F  qP                  SR 7      x  K  	  R# 5i)r~  N)r  )r   r   r~  s   & r_   r   %MultiIndex._nbytes.<locals>.<genexpr>  s     Jk>>t>44k   !c              3  8   "   T F  qP                   x  K  	  R # 5ir   )r  )r   r   s   & r_   r   r     s     8Z88ZrO  c              3  <   <"   T F  p\        VS4      x  K  	  R # 5ir   r   )r   r   objsizes   & r_   r   r    s     E*Q9Q00*s   rn  r  )sumr   r   rz   r   rn  sizeof)r   r~  level_nbyteslabel_nbytesnames_nbytesr   r  s   &f    @r_   r  MultiIndex._nbytes  s     JdkkJJ8TZZ88E$**EE,|; #ll))t)44Fr^   c           	         R V P                    4       p\        ;QJ d    . R \        W!RR7       4       F  NK  	  5# ! R \        W!RR7       4       4      # )zG
Formats each item in tup according to its level's formatter function.
c              3  8   "   T F  qP                   x  K  	  R # 5ir   )_formatter_funcr   r   s   & r_   r   -MultiIndex._formatter_func.<locals>.<genexpr>  s     JkU00krO  c              3  6   "   T F  w  rV! V4      x  K  	  R # 5ir   rS   )r   funcvals   &  r_   r   r    s     W0V94T#YY0Vs   Tr'  )r   r   r   )r   tupformatter_funcss   && r_   r  MultiIndex._formatter_func  sE     KdkkJuWOQU0VWuWuWOQU0VWWWr^   na_repr   c                    V ^8  d   QhRRRR/# )rr   r  strrt   znpt.NDArray[np.object_]rS   )ru   s   "r_   rv   r     s     $ $$	 $r^   c               	   . p. p\        V P                  V P                  R R7       F  w  rVVP                  ! RRV/VB pVR8H  pVP	                  4       '       di   \        V4      p	VP                  \        4      p\        P                  ! Wq4      pVP                  P                  '       d   Q hVP                  4       pWV&   VP                  V4       VP                  V4       K  	  \        V4      ^8X  d9   \        V^ ,          P                  V^ ,          4      RR7      P                  4       # \        VVV P                   V P"                  RR7      p
V
P$                  # )Tr'  r  Fr4  r   r   rz   r   r   rS   r   )r   r   r   _get_values_for_csvr   r   r  r  r   r   flags	writeabler   rE   taker   rz   r   r   )r   r  r   r:  r   r   r   
level_strsmask	nan_indexmis   &$,        r_   r  MultiIndex._get_values_for_csv  s8    
	 #&dkk4::d"KE22K&KFKJ"$Dxxzz
O	'..s3
YYz:
&,,66666)..0$-D!j)[) #L z?a1""9Q<0u!!#$
 !jj..!&B ::r^   	formatterc               (    V ^8  d   QhRRRRRRRR/# )	rr   include_namesr   sparsifyzbool | None | lib.NoDefaultr  zCallable | Nonert   r   rS   )ru   s   "r_   rv   r   9  s4     = = = .	=
 #= 
=r^   c          	     	p   \        V 4      ^ 8X  d   . # . p\        V P                  V P                  RR7       F  w  rV\	        VP
                  4      p\        V4      ^ 8  dr   VP                  V4      ;rVP                  RVR7      p	VR
8H  p
V
P                  4       '       d1   \        P                  ! V	\        R7      p	WyV
&   V	P                  4       p	MN\        P                  ! VP                  V4       Uu. uF#  p\!        \#        V4      '       d   TMTRR7      NK%  	  p	pVP%                  V	4       K  	  . p\        W@P&                  RR7       Fm  w  r]. pV'       d#   TP%                  Ve   \!        VRR7      MR4       VP)                  \        P                  ! V\        R7      4       VP%                  V4       Ko  	  Vf   \+        R4      pV'       d\   Rp\-        V\.        4      '       g   V\0        P2                  J g   Q hV\0        P2                  J d   Tp\5        V\7        V4      VR	7      pV# u upi )r   Tr'  F)include_namer  r   )escape_chars zdisplay.multi_sparse)startsentinelr   )	
)r   r   r   r   _get_na_repr   r  _format_flatr   r   r   ro   tolistr   r  r   rL   r>   r   rz   extendr   r   r   r   r   sparsify_labelsr   )r   r  r  r  stringified_levelsr6  r   nataken	formattedr  r,  result_levelslev_namer   r  s   &$$$            r_   _format_multiMultiIndex._format_multi9  s    t9>I #DKKD ICSYY'B3x!|$'HH[$99!..EY.W	 #b(88:: "& AI&(dO ) 0 0 2I #]]3;;DD !tAwwADVWD   %%i0) !J,  !3ZZMMCE+ !8JK LL#V45  ' N !"89H;=Hh--S^^1KKK3>>)#+S%7(M Es   5)H3c                   V ^8  d   QhRR/# r%  rS   )ru   s   "r_   rv   r   {  s     ' 'J 'r^   c                	,    \        V P                  4      # r   )rH   r   r  s   &r_   
_get_namesMultiIndex._get_names{  s    $++&&r^   c                   V ^8  d   QhRR/# rr   rt   r0  rS   )ru   s   "r_   rv   r   ~  s     6$ 6$$ 6$r^   c               $  a  Ve   \        V4      '       g   \        R4      h\        V4      pVe%   \        V4      \        V4      8w  d   \        R4      hVf&   \        V4      S P                  8w  d   \        R4      hVf   \        S P                  4      pMV 3R lV 4       p\        W!RR7       FJ  w  r4Ve3   \        V4      '       g"   \        \        S 4      P                   R24      hVS P                  V&   KL  	  S P                  R	4       R# )
a  
Set new names on index. Each name has to be a hashable type.

Parameters
----------
values : str or sequence
    name(s) to set
level : int, level name, or sequence of int/level names (default None)
    If the index is a MultiIndex (hierarchical), level(s) to set (None
    for all levels).  Otherwise level must be None

Raises
------
TypeError if each name is not hashable.

Notes
-----
sets names on levels. WARNING: mutates!

Note that you generally want to set this *after* changing levels, so
that it only acts on copies
Nz*Names should be list-like for a MultiIndexz+Length of names must match length of level.z:Length of names must match number of levels in MultiIndex.c              3  F   <"   T F  pSP                  V4      x  K  	  R # 5ir   )r8  )r   r6  r   s   & r_   r   (MultiIndex._set_names.<locals>.<genexpr>  s     BEST++C00Er  Tr'  z.name must be a hashable typer   )r3   r   r   r   r   r   r   r0   r{   rr  rT   r   r9  )r   rz   r   r6  ry   s   f&$  r_   r   MultiIndex._set_names~  s    2 \%%8%8IJJUUs5z!9JKK=SZ4<<7L  =$,,'EBEBE U$7IC #4((#:..//LM   $DKK 8 	(#r^   a  
        Names of levels in MultiIndex.

        This attribute provides access to the names of the levels in a `MultiIndex`.
        The names are stored as a `FrozenList`, which is an immutable list-like
        container. Each name corresponds to a level in the `MultiIndex`, and can be
        used to identify or manipulate the levels individually.

        See Also
        --------
        MultiIndex.set_names : Set Index or MultiIndex name.
        MultiIndex.rename : Rename specific levels in a MultiIndex.
        Index.names : Get names on index.

        Examples
        --------
        >>> mi = pd.MultiIndex.from_arrays(
        ...     [[1, 2], [3, 4], [5, 6]], names=['x', 'y', 'z']
        ... )
        >>> mi
        MultiIndex([(1, 3, 5),
                    (2, 4, 6)],
                   names=['x', 'y', 'z'])
        >>> mi.names
        FrozenList(['x', 'y', 'z'])
        )fsetfgetdocc                   V ^8  d   QhRR/# )rr   rt   r  rS   )ru   s   "r_   rv   r     s      s r^   c                	    R # )mixedrS   r  s   &r_   inferred_typeMultiIndex.inferred_type  s    r^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s      # r^   c                	F   V P                   P                  V4      pV^8  d!   \        V4      '       g   \        RV R24      h V P                   P	                  V4      pV#   \         d   p\        T4      '       g   \        RT R24      ThT^ 8  dO   YP                  ,          pT^ 8  d0   YP                  ,
          p\        RT P                   RT R24      Th R	p?T# YP                  8  d$   \        RT P                   RT^,            24      Th R	p?T# R	p?ii ; i)
rd  z	The name z* occurs multiple times, use a level numberzLevel z
 not foundz Too many levels: Index has only z	 levels, z is not a valid level numberz levels, not N)rz   countr1   r   r   KeyErrorr   
IndexError)r   r   r	  err
orig_levels   &&   r_   r8  MultiIndex._get_level_number  s<   

  'AIz%00E7"LM 	JJ$$U+E$ #  	e$$wj9:Cqy%19!&!5J$:4<<.	%,&BD    ,,& 6t||n E 19+'  '
 #	s   A! !D ,A0D"3DD c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     K K Kr^   c           
     .   \         ;QJ d&    R V P                   4       F  '       g   K   RM	  RM! R V P                   4       4      '       d   R# \        ;QJ d&    R V P                   4       F  '       d   K   RM	  RM! R V P                   4       4      '       dA   \        P
                  ! V P                   Uu. uF  qP                  RRR7      NK  	  up4      # \        \        \        V P                  4      4      4       Uu. uF  q P                  V4      P                  NK  	  pp \        P                  ! V4      p\        VRR7      P                  # u upi u upi   \          d%    \        T P                  RR7      P                  u # i ; i)z9
Return a boolean if the values are equal or increasing.
c              3  ,   "   T F
  pRV9   x  K  	  R# 5i)rd  Nr   rS   )r   r   s   & r_   r   5MultiIndex.is_monotonic_increasing.<locals>.<genexpr>  s     1jdrTzjs   TFc              3  8   "   T F  qP                   x  K  	  R # 5ir   is_monotonic_increasingr  s   & r_   r   r    s     F+,,+rO  int64r4  )r   r   r   r   libalgosis_lexsortedr  reversedr   r   _get_level_valuesr   r   lexsortrE   r  r{   )r   r,  r   r	  
sort_orders   &    r_   r  "MultiIndex.is_monotonic_increasing  s-   
 31djj13331djj1113F$++F333F$++FFF((8<

C
1'.
C  8@c$++FV@W7X
7X!""1%--7X 	 
	K F+J%0HHH D
  	KE2JJJ	Ks   =E#E .,E% %,FFc                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     2 2 2r^   c                .    V RRR1,          P                   # )z9
Return a boolean if the values are equal or decreasing.
Nr   r  r  s   &r_   is_monotonic_decreasing"MultiIndex.is_monotonic_decreasing  s     DbDz111r^   c                    V ^8  d   QhRRRR/# )rr   keepr   rt   npt.NDArray[np.bool_]rS   )ru   s   "r_   rv   r     s     :% :%x :%6K :%r^   c                    \         ;QJ d    . R V P                   4       F  NK  	  5M! R V P                   4       4      p\        V P                  VRRR7      p\	        W14      # )a  
Indicate duplicate index values.

Duplicated values are indicated as ``True`` values in the resulting
array. Either all duplicates, all except the first, or all except the
last occurrence of duplicates can be indicated.

Parameters
----------
keep : {'first', 'last', False}, default 'first'
    The value or values in a set of duplicates to mark as missing.

    - 'first' : Mark duplicates as ``True`` except for the first
      occurrence.
    - 'last' : Mark duplicates as ``True`` except for the last
      occurrence.
    - ``False`` : Mark all duplicates as ``True``.

Returns
-------
np.ndarray[bool]
    A numpy array of boolean values indicating duplicate index values.

See Also
--------
Series.duplicated : Equivalent method on pandas.Series.
DataFrame.duplicated : Equivalent method on pandas.DataFrame.
Index.drop_duplicates : Remove duplicate values from Index.

Examples
--------
By default, for each set of duplicated values, the first occurrence is
set to False and all others to True:

>>> mi = pd.MultiIndex.from_arrays((list("abca"), list("defd")))
>>> mi.duplicated()
array([False, False, False,  True])

which is equivalent to

>>> mi.duplicated(keep="first")
array([False, False, False,  True])

By using 'last', the last occurrence of each set of duplicated values
is set on False and all others on True:

>>> mi.duplicated(keep="last")
array([ True, False, False, False])

By setting keep on ``False``, all duplicates are True:

>>> mi.duplicated(keep=False)
array([ True, False, False,  True])
c              3  8   "   T F  p\        V4      x  K  	  R # 5ir   r!  )r   r6  s   & r_   r   (MultiIndex.duplicated.<locals>.<genexpr>T  s     6+3c#hh+rO  F)sortxnull)r   r   rJ   r   r   )r   r#  shapeidss   &&  r_   r   MultiIndex.duplicated  sJ    n 6$++66$++66djj%e5I#$$r^   c                    \        R4      h)z*
fillna is not implemented for MultiIndex
z$fillna is not defined for MultiIndex)NotImplementedError)r   values   &&r_   fillnaMultiIndex.fillna]  s     ""HIIr^   c                    V ^8  d   QhRRRR/# )rr   howr   rt   r   rS   )ru   s   "r_   rv   r   c  s     '/ '/& '/Z '/r^   c                T   V P                    Uu. uF  q"R8H  NK	  	  ppVR8X  d   \        P                  ! V^ R7      pM.VR8X  d   \        P                  ! V^ R7      pM\	        RV 24      hV P                    Uu. uF  q"V( ,          NK  	  ppV P                  VR7      # u upi u upi )aQ  
Return MultiIndex without NA/NaN values.

Parameters
----------
how : {'any', 'all'}, default 'any'
    Drop the value when any or all levels are NaN.

Returns
-------
Index
    Returns an MultiIndex object after removing NA/NaN values.

See Also
--------
Index.fillna : Fill NA/NaN values with the specified value.
Index.isna : Detect missing values.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays(([np.nan, np.nan, 2.0], [3.0, np.nan, 4.0]))
>>> mi.dropna()
MultiIndex([(2.0, 4.0)],
           )
>>> mi.dropna(how="all")
MultiIndex([(nan, 3.0),
            (2.0, 4.0)],
           )
r   )axisr   zinvalid how option: )r   r   )r   r   r   r   r   r`  )r   r3  r   nansindexerr   s   &&    r_   dropnaMultiIndex.dropnac  s    < 6:ZZ@Zkr!Z@%<ffT*GE\ffT*G3C59::>BjjIj{'**j	I~~I~.. A Js   B :B%c               $    V ^8  d   QhRRRRRR/# )rr   r   r   uniquer   rt   rE   rS   )ru   s   "r_   rv   r     s!     4 4s 4D 4U 4r^   c                ,   V P                   V,          pV P                  V,          pV P                  V,          pV'       d   \        P                  ! V4      p\        P
                  ! VP                  WCP                  R7      pVP                  WeR7      # )z
Return vector of label values for requested level,
equal to the length of the index

**this is an internal method**

Parameters
----------
level : int
unique : bool, default False
    if True, drop duplicated values

Returns
-------
Index
r   r(  )	r   r   r   r   r;  r  r   r  rw  )r   r   r;  r6  r   ry   filleds   &&&    r_   r  MultiIndex._get_level_values  sk    " kk% jj'{{5!,,{3Ks{{KMMR   33r^   c                   V ^8  d   QhRR/# rr   rt   rE   rS   )ru   s   "r_   rv   r     s     C C Cr^   c                J    V P                  V4      pV P                  V4      pV# )a  
Return vector of label values for requested level.

Length of returned vector is equal to the length of the index.
The `get_level_values` method is a crucial utility for extracting
specific level values from a `MultiIndex`. This function is particularly
useful when working with multi-level data, allowing you to isolate
and manipulate individual levels without having to deal with the
complexity of the entire `MultiIndex` structure. It seamlessly handles
both integer and string-based level access, providing flexibility in
how you can interact with the data. Additionally, this method ensures
that the returned `Index` maintains the integrity of the original data,
even when missing values are present, by appropriately casting the
result to a suitable data type.

Parameters
----------
level : int or str
    ``level`` is either the integer position of the level in the
    MultiIndex, or the name of the level.

Returns
-------
Index
    Values is a level of this MultiIndex converted to
    a single :class:`Index` (or subclass thereof).

See Also
--------
MultiIndex : A multi-level, or hierarchical, index object for pandas objects.
Index : Immutable sequence used for indexing and alignment.
MultiIndex.remove_unused_levels : Create new MultiIndex from current that
    removes unused levels.

Notes
-----
If the level contains missing values, the result may be casted to
``float`` with missing values specified as ``NaN``. This is because
the level is converted to a regular ``Index``.

Examples
--------
Create a MultiIndex:

>>> mi = pd.MultiIndex.from_arrays((list("abc"), list("def")))
>>> mi.names = ["level_1", "level_2"]

Get level values by supplying level as either integer or name:

>>> mi.get_level_values(0)
Index(['a', 'b', 'c'], dtype='str', name='level_1')
>>> mi.get_level_values("level_2")
Index(['d', 'e', 'f'], dtype='str', name='level_2')

If a level contains missing values, the return type of the level
may be cast to ``float``.

>>> pd.MultiIndex.from_arrays([[1, None, 2], [3, 4, 5]]).dtypes
level_0    int64
level_1    int64
dtype: object
>>> pd.MultiIndex.from_arrays([[1, None, 2], [3, 4, 5]]).get_level_values(0)
Index([1.0, nan, 2.0], dtype='float64')
)r8  r  )r   r   r	  s   && r_   get_level_valuesMultiIndex.get_level_values  s*    B &&u-''.r^   c                r    Vf   V P                  4       # V P                  V4      pV P                  VRR7      # )a  
Return unique values in the index.

Unique values are returned in order of appearance, this does NOT sort.

Parameters
----------
level : int or hashable, optional
    Only return values from specified level (for MultiIndex).
    If int, gets the level by integer position, else by level name.

Returns
-------
MultiIndex
    Unique values in the MultiIndex.

See Also
--------
unique : Numpy array of unique values in that column.
Series.unique : Return unique values of Series object.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays((list("abca"), list("defd")))
>>> mi
MultiIndex([('a', 'd'),
            ('b', 'e'),
            ('c', 'f'),
            ('a', 'd')],
           )
>>> mi.unique()
MultiIndex([('a', 'd'),
            ('b', 'e'),
            ('c', 'f')],
           )
T)r   r;  )drop_duplicatesr8  r  )r   r   s   &&r_   r;  MultiIndex.unique  s?    J =''))**51E))d)CCr^   c               $    V ^8  d   QhRRRRRR/# )rr   r   r   allow_duplicatesrt   rN   rS   )ru   s   "r_   rv   r     s-     W WW 	W
 
Wr^   c           	        ^ RI Hp V\        P                  JdN   \	        V4      '       g   \        R4      h\        V4      \        V P                  4      8w  d   \        R4      hTpMV P                  4       pV'       g.   \        \        V4      4      \        V4      8w  d   \        R4      hT! \        \        V P                  4      4       Uu/ uF  qfV P                  V4      bK  	  upRR7      pWWn        V'       d   Wn        V# u upi )a  
Create a DataFrame with the levels of the MultiIndex as columns.

Column ordering is determined by the DataFrame constructor with data as
a dict.

Parameters
----------
index : bool, default True
    Set the index of the returned DataFrame as the original MultiIndex.

name : list / sequence of str, optional
    The passed names should substitute index level names.

allow_duplicates : bool, optional default False
    Allow duplicate column labels to be created.

Returns
-------
DataFrame
    DataFrame representation of the MultiIndex, with levels as columns.

See Also
--------
DataFrame : Two-dimensional, size-mutable, potentially heterogeneous
    tabular data.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a", "b"], ["c", "d"]])
>>> mi
MultiIndex([('a', 'c'),
            ('b', 'd')],
           )

>>> df = mi.to_frame()
>>> df
     0  1
a c  a  c
b d  b  d

>>> df = mi.to_frame(index=False)
>>> df
   0  1
0  a  c
1  b  d

>>> df = mi.to_frame(name=["x", "y"])
>>> df
     x  y
a c  a  c
b d  b  d
)rN   z1'name' must be a list / sequence of column names.z<'name' should have same length as number of levels on index.zBCannot create duplicate column labels if allow_duplicates is FalseFr4  )r   rN   r   r   r3   r{   r   r   r   _get_level_namessetr   r  r   r   )r   r   ry   rH  rN   	idx_namesr   r   s   &&&&    r_   to_frameMultiIndex.to_frame  s    v 	%s~~%%% STT4yC,, R  I--/ICI$73y>$IT 
 ?DSEU?VW?VeD**511?VW
 #L Xs   Dc                   V ^8  d   QhRR/# r@  rS   )ru   s   "r_   rv   r   p  s     D Du Dr^   c                2    \        V P                  RRR7      # )aQ  
Convert a MultiIndex to an Index of Tuples containing the level values.

Returns
-------
pd.Index
    Index with the MultiIndex data represented in Tuples.

See Also
--------
MultiIndex.from_tuples : Convert flat index back to MultiIndex.

Notes
-----
This method will simply return the caller if called by anything other
than a MultiIndex.

Examples
--------
>>> index = pd.MultiIndex.from_product(
...     [["foo", "bar"], ["baz", "qux"]], names=["a", "b"]
... )
>>> index.to_flat_index()
Index([('foo', 'baz'), ('foo', 'qux'),
       ('bar', 'baz'), ('bar', 'qux')],
      dtype='object')
F)tupleize_colsr   )rE   r   r  s   &r_   to_flat_indexMultiIndex.to_flat_indexp  s    8 T\\UCCr^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     &3 &3t &3r^   c                4    V P                   V P                  8H  # )a  
Return True if the codes are lexicographically sorted.

Returns
-------
bool

Examples
--------
In the below examples, the first level of the MultiIndex is sorted because
a<b<c, so there is no need to look at the next level.

>>> pd.MultiIndex.from_arrays(
...     [["a", "b", "c"], ["d", "e", "f"]]
... )._is_lexsorted()
True
>>> pd.MultiIndex.from_arrays(
...     [["a", "b", "c"], ["d", "f", "e"]]
... )._is_lexsorted()
True

In case there is a tie, the lexicographical sorting looks
at the next level of the MultiIndex.

>>> pd.MultiIndex.from_arrays([[0, 1, 1], ["a", "b", "c"]])._is_lexsorted()
True
>>> pd.MultiIndex.from_arrays([[0, 1, 1], ["a", "c", "b"]])._is_lexsorted()
False
>>> pd.MultiIndex.from_arrays(
...     [["a", "a", "b", "b"], ["aa", "bb", "aa", "bb"]]
... )._is_lexsorted()
True
>>> pd.MultiIndex.from_arrays(
...     [["a", "a", "b", "b"], ["bb", "aa", "aa", "bb"]]
... )._is_lexsorted()
False
)r   r   r  s   &r_   _is_lexsortedMultiIndex._is_lexsorted  s    L ""dll22r^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     8 8 8r^   c                v    V P                   e   V P                   # \        V P                  V P                  4      # )z}
Compute and return the lexsort_depth, the number of levels of the
MultiIndex that are sorted lexically

Returns
-------
int
)r   r   r   r   r  s   &r_   r   MultiIndex._lexsort_depth  s-     >>%>>!djj$,,77r^   c                    V ^8  d   QhRRRR/# )rr   raise_if_incomparabler   rt   r   rS   )ru   s   "r_   rv   r     s     B
 B
D B
Z B
r^   c                b   V P                  4       '       d   V P                  '       d   V # . p. p\        V P                  V P                  RR7       F  w  rEVP                  '       gf    VP                  4       pVP                  V4      p\        V4      p\        P                  ! V\        V4      4      p\        P                  ! WuRR7      pVP                  V4       VP                  V4       K  	  \        VVV P                   V P"                  RR7      #   \         d    T'       d   h  L`i ; i)a  
This is an *internal* function.

Create a new MultiIndex from the current to monotonically sorted
items IN the levels. This does not actually make the entire MultiIndex
monotonic, JUST the levels.

The resulting MultiIndex will have the same outward
appearance, meaning the same .values and ordering. It will also
be .equals() to the original.

Returns
-------
MultiIndex

Examples
--------
>>> mi = pd.MultiIndex(
...     levels=[["a", "b"], ["bb", "aa"]], codes=[[0, 0, 1, 1], [0, 1, 0, 1]]
... )
>>> mi
MultiIndex([('a', 'bb'),
            ('a', 'aa'),
            ('b', 'bb'),
            ('b', 'aa')],
           )

>>> mi.sort_values()
MultiIndex([('a', 'aa'),
            ('a', 'bb'),
            ('b', 'aa'),
            ('b', 'bb')],
           )
Tr'  r   F)rz   r   r   r   )rV  r  r   r   r   argsortr  r/   r   get_reverse_indexerr   r   r  r{   r   r   rz   r   )r   r\  r:  r   r6  r   r7  ris   &&      r_   _sort_levels_monotonic!MultiIndex._sort_levels_monotonic  s
   F D$@$@$@K
	 #DKKD IC...P!kkmG
 ((7+C 2':G00#g,GB"'--B"OKc"[)# !J& **nn"
 	
 ! , -s   )DD.*D.-D.c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r   	  s     ` `j `r^   c                l   . p. pRp\        V P                  V P                  RR7       EF  w  rE\        P                  ! \        P
                  ! V^,           4      ^ 8  4      ^ ,          ^,
          p\        \        V4      ;'       d    V^ ,          R8H  4      p\        V4      \        V4      V,           8w  Ed   VP                  4       P                  4       '       d   \        V4      \        V4      8X  d    MRp\        P                  ! V4      pV'       d>   \        P                  ! VR8H  4      ^ ,          pWh^ ,          ^ .,          V^ V^ ,          .&   \        P                  ! \        V4      V,           4      p	\        P                  ! \        V4      4      V,
          W&   W,          pVP                  WgR 4      pVP                  V4       VP                  V4       EK  	  V P!                  4       p
V'       d7   V
P#                  4        V
P%                  VRR7       V
P'                  VRR7       V
# )a!  
Create new MultiIndex from current that removes unused levels.

Unused level(s) means levels that are not expressed in the
labels. The resulting MultiIndex will have the same outward
appearance, meaning the same .values and ordering. It will
also be .equals() to the original.

The `remove_unused_levels` method is useful in cases where you have a
MultiIndex with hierarchical levels, but some of these levels are no
longer needed due to filtering or subsetting operations. By removing
the unused levels, the resulting MultiIndex becomes more compact and
efficient, which can improve performance in subsequent operations.

Returns
-------
MultiIndex
    A new MultiIndex with unused levels removed.

See Also
--------
MultiIndex.droplevel : Remove specified levels from a MultiIndex.
MultiIndex.reorder_levels : Rearrange levels of a MultiIndex.
MultiIndex.set_levels : Set new levels on a MultiIndex.

Examples
--------
>>> mi = pd.MultiIndex.from_product([range(2), list("ab")])
>>> mi
MultiIndex([(0, 'a'),
            (0, 'b'),
            (1, 'a'),
            (1, 'b')],
           )

>>> mi[2:]
MultiIndex([(1, 'a'),
            (1, 'b')],
           )

The 0 from the first level is not represented
and can be removed

>>> mi2 = mi[2:].remove_unused_levels()
>>> mi2.levels
FrozenList([[1], ['a', 'b']])
FTr'  Nr   r   )r   r   r   r   r   bincountr   r   r>   r   r   r;  r   aranger  r   rY  r   r   r   )r   r:  r   changedr6  r   uniqueshas_nana_idxcode_mappingr   s   &          r_   remove_unused_levelsMultiIndex.remove_unused_levels	  s   ` 
	 #DKKD I IC hhr{{;?;a?@CaGGW<<71:+;=F7|s3x&0088:>>##GC(@  ,,{3XXgm4Q7F.5ay!n.EGQq	N+  "xxC6(9:(*		#g,(?&(H%*7 hhww/0c"[)G !JJ ""$zE:i%8r^   c           
         R\        V P                  4      R\        V P                  4      RV P                  R\        V P                  4      /p\
        P                  \        V 4      V3R3# )z*Necessary for making this object picklabler   r   r   rz   N)r   r   r   r   rz   ibase
_new_Indexrr  )r   ds   & r_   
__reduce__MultiIndex.__reduce__m	  s[     d4;;'T$**%T$**%	
 $t*a$66r^   c                	   \         P                  ! V4      p\        V4      '       d   \        P                  ! V4      p. p\        V P                  V P                  R R7       FQ  w  r4WA,          R8X  d"   VP                  \        P                  4       K3  VP                  W4V,          ,          4       KS  	  \        V4      # Rp\        P                  ! V4      '       d*   \        P                  ! V\        R7      pV P                  pMn\!        V\"        4      '       d-   VP$                  e   VP$                  ^ 8  d   V P                  pM,\!        V\&        4      '       d   \        P                  ! V4      pV P                   Uu. uF  qDV,          NK  	  pp\)        V P                  VV P*                  VRR7      # u upi )Tr'  Nr   Fr  r   )r   item_from_zerodimr5   r   cast_scalar_indexerr   r   r   r   r   r   r   is_bool_indexerr   r   r   r   slicesteprE   r   rz   )r   r  retvalr6  r   r   r   s   &&     r_   __getitem__MultiIndex.__getitem__y	  sH   ##C(S>>))#.CF$'TZZ$M #r)MM"&&)MM##&6"78	 %N =  I""3''jjD1 NN	C''88#sxx!| $IC''jjo=AZZHZkS))ZIH{{jj#!&  Is   F<c               $    V ^8  d   QhRRRRRR/# )rr   r   r   slobjry  rt   rS   )ru   s   "r_   rv   r   	  s!     
 
Z 
 
* 
r^   c                    RpVP                   e   VP                   ^ 8  d   V P                  pV P                   Uu. uF  q3V,          NK  	  pp\        V 4      ! V P                  VV P
                  VRR7      # u upi )z8
Fastpath for __getitem__ when we know we have a slice.
NFr  )rz  r   r   rr  r   r   )r   r  r   r   r   s   &&   r_   _getitem_sliceMultiIndex._getitem_slice	  sr     	::aI;?::F:K'':	FDz;;++"
 	
 Gs   A9c               (    V ^8  d   QhRRRRRRRR/# )rr   r   r   r5  r   
allow_fillr   rt   rS   )ru   s   "r_   rv   r   	  s8     V
 V
V
 V
 	V
 
V
r^   c                R   \         P                  ! RV4       \        V4      pV P                  W4V4      pVP                  ^8X  d7   \
        P                  ! V\        V 4      4      '       d   V P                  4       # RpV P                   Uu. uF  qwP                  V4      NK  	  ppV'       dT   VR8H  p	V	P                  4       '       d9   . p
V F.  pTpWlV	&   V
P                  \        P                  ! V4      4       K0  	  T
p\        V P                   WP"                  RR7      # u upi )a  
Return a new MultiIndex of the values selected by the indices.

For internal compatibility with numpy arrays.

Parameters
----------
indices : array-like
    Indices to be taken.
axis : {0 or 'index'}, optional
    The axis over which to select values, always 0 or 'index'.
allow_fill : bool, default True
    How to handle negative values in `indices`.

    * False: negative values in `indices` indicate positional indices
    from the right (the default). This is similar to
    :func:`numpy.take`.

    * True: negative values in `indices` indicate
    missing values. These values are set to `fill_value`. Any other
    other negative values raise a ``ValueError``.

fill_value : scalar, default None
    If allow_fill=True and fill_value is not None, indices specified by
    -1 are regarded as NA. If Index doesn't hold NA, raise ValueError.
**kwargs
    Required for compatibility with numpy.

Returns
-------
Index
    An index formed of elements at the given indices. Will be the same
    type as self, except for RangeIndex.

See Also
--------
numpy.ndarray.take: Return an array formed from the
    elements of a at the given indices.

Examples
--------
>>> idx = pd.MultiIndex.from_arrays([["a", "b", "c"], [1, 2, 3]])
>>> idx
MultiIndex([('a', 1),
            ('b', 2),
            ('c', 3)],
           )
>>> idx.take([2, 2, 1, 0])
MultiIndex([('c', 3),
            ('c', 3),
            ('b', 2),
            ('a', 1)],
           )
Fr   r   rz   r   rS   r   )nvvalidate_taker/   _maybe_disallow_fillndimr   is_range_indexerr   r   r   r  r   r   r   r   r   r   rz   )r   indicesr5  r  r  r   na_valuelabr  r  masked	new_labellabel_valuess   &&&&&,       r_   r  MultiIndex.take	  s    | 	V$%g. ..zwO
<<1!5!5gs4y!I!I99;.2jj9js'"j9b=Dxxzz!&I#,L)1&MM"**\":; "' ;;e::PU
 	
 :s   D$c                  a a
a \        V\        \        34      '       g   V.p\        ;QJ d    V 3R lV 4       F  '       d   K   RM	  RM! V 3R lV 4       4      '       EdR   . p. p. p\	        S P
                  4       EF#  o
S P                  S
,          pV F%  pVP                  VP                  S
,          4      pK'  	  S .VO Uu. uF4  p\        VP                  S
,          VP                  S
,          VRR7      NK6  	  ppS P                  S
,          o\        ;QJ d     V
V3R lV 4       F  '       g   K   RM	  RM! V
V3R lV 4       4      '       d   RoVP                  \        P                  ! V4      4       VP                  V4       VP                  S4       EK&  	  \        W#VRR7      # S P                   .\        ;QJ d    . R V 4       F  NK  	  5M! R V 4       4      O5p\        P                  ! V4      p	 \        P#                  V	4      # u upi   \$        \&        3 d    \)        T	RR7      u # i ; i)	a  
Append a collection of Index options together.

The `append` method is used to combine multiple `Index` objects into a single
`Index`. This is particularly useful when dealing with multi-level indexing
(MultiIndex) where you might need to concatenate different levels of indices.
The method handles the alignment of the levels and codes of the indices being
appended to ensure consistency in the resulting `MultiIndex`.

Parameters
----------
other : Index or list/tuple of indices
    Index or list/tuple of Index objects to be appended.

Returns
-------
Index
    The combined index.

See Also
--------
MultiIndex: A multi-level, or hierarchical, index object for pandas objects.
Index.append : Append a collection of Index options together.
concat : Concatenate pandas objects along a particular axis.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a"], ["b"]])
>>> mi
MultiIndex([('a', 'b')],
           )
>>> mi.append(mi)
MultiIndex([('a', 'b'), ('a', 'b')],
           )
c              3     <"   T F6  p\        V\        4      ;'       d    VP                  SP                  8  x  K8  	  R # 5ir   )r   r   r   )r   or   s   & r_   r   $MultiIndex.append.<locals>.<genexpr>-
  s3      
OT!Z:&DD199+DDus
   A"AFTr4  c              3  N   <"   T F  qP                   S,          S8g  x  K  	  R # 5ir   rz   )r   r  r   
level_names   & r_   r   r  >
  s     A5Rxx{j05s   "%N)r   r   rz   r   c              3  8   "   T F  qP                   x  K  	  R # 5ir   r  r   ks   & r_   r   r  G
  s     )CU))UrO  )r   r   r   r   r   r   r   unionrC   r   rz   r   r   r   ri  r   r   r   r{   r  rE   )r   otherr   r   rz   level_valuesr  r   	to_concat
new_tuplesr   r  s   f&        @@r_   r   MultiIndex.append
  s   H %$//GE3 
OT
333 
OT
 
 
 EFE4<<(#{{1~B#/#5#5biil#CL   !%~u~	  . *RYYq\<e  .	   "ZZ]
3A5A333A5AAA!%JR^^K89l+Z( )  %%  \\DEE)CU)CEE)CU)C$CD	^^I.
	1 ))*55/0 :& 	1%00	1s   :HH   I Ina_positionlastc                    V ^8  d   QhRRRR/# )rr   r  r!   rt   npt.NDArray[np.intp]rS   )ru   s   "r_   rv   r   R
  s      5P 5P",5P	5Pr^   c                   V P                  RR7      pVP                  4        Uu. uF  qUP                  NK  	  pp\        WaRR7      # u upi )a  
Return the integer indices that would sort the index.

Parameters
----------
*args
    Passed to `numpy.ndarray.argsort`.
na_position : {'first' or 'last'}, default 'last'
    Argument 'first' puts NaNs at the beginning, 'last' puts NaNs at
    the end.
**kwargs
    Passed to `numpy.ndarray.argsort`.

Returns
-------
np.ndarray[np.intp]
    Integer indices that would sort the index if used as
    an indexer.

See Also
--------
numpy.argsort : Similar method for NumPy arrays.
Index.argsort : Similar method for Index.

Examples
--------
>>> midx = pd.MultiIndex.from_arrays([[3, 2], ["e", "c"]])
>>> midx
MultiIndex([(3, 'e'),
            (2, 'c')],
           )

>>> order = midx.argsort()
>>> order
array([1, 0])

>>> midx[order]
MultiIndex([(2, 'c'),
            (3, 'e')],
          )

>>> midx = pd.MultiIndex.from_arrays([[2, 2], [np.nan, 0]])
>>> midx.argsort(na_position="first")
array([0, 1])

>>> midx.argsort()
array([1, 0])
T)r\  )r  codes_given)ra  _get_codes_for_sortingr   rK   )r   r  r~   r   targetr6  keyss   &$*,   r_   r^  MultiIndex.argsortR
  sL    f ,,4,H%+%B%B%DE%Dc		%DEt$OO Fs   Ac                    V ^8  d   QhRRRR/# )rr   repeatsr   rt   r   rS   )ru   s   "r_   rv   r   
  s     A
 A
c A
 A
r^   c                z   \         P                  ! RRV/4       \        V4      p\        V P                  V P
                   Uu. uFP  pVP                  \        P                  4      P                  \        P                  RR7      P                  V4      NKR  	  upV P                  V P                  RR7      # u upi )a  
Repeat elements of a MultiIndex.

Returns a new MultiIndex where each element of the current MultiIndex
is repeated consecutively a given number of times.

Parameters
----------
repeats : int or array of ints
    The number of repetitions for each element. This should be a
    non-negative integer. Repeating 0 times will return an empty
    MultiIndex.
axis : None
    Must be ``None``. Has no effect but is accepted for compatibility
    with numpy.

Returns
-------
MultiIndex
    Newly created MultiIndex with repeated elements.

See Also
--------
Series.repeat : Equivalent function for Series.
numpy.repeat : Similar method for :class:`numpy.ndarray`.

Examples
--------
>>> idx = pd.MultiIndex.from_arrays([["a", "b", "c"], [1, 2, 3]])
>>> idx
MultiIndex([('a', 1),
            ('b', 2),
            ('c', 3)],
           )
>>> idx.repeat(2)
MultiIndex([('a', 1),
            ('a', 1),
            ('b', 2),
            ('b', 2),
            ('c', 3),
            ('c', 3)],
           )
>>> idx.repeat([1, 2, 3])
MultiIndex([('a', 1),
            ('b', 2),
            ('b', 2),
            ('c', 3),
            ('c', 3),
            ('c', 3)],
           )
r5  Fr4  r  rS   )r  validate_repeatr/   r   r   r   rY  r   r   r  intprepeatrz   r   )r   r  r5  r   s   &&& r_   r  MultiIndex.repeat
  s    h 	2~. &g.;; $(::#-K   ,33BGG%3HOOPWX#- **nn"	
 		
s   AB8
c               $    V ^8  d   QhRRRRRR/# )rr   r   z.Index | np.ndarray | Iterable[Hashable] | Noneerrorsr   rt   r   rS   )ru   s   "r_   rv   r   
  s/     j! j! >j! 	j!
 
j!r^   c                   Ve   V P                  WV4      # \        V\        P                  \        34      '       g.    \
        P                  ! V\        P                  ! R4      R7      p. pV EFG  p V P                  V4      p\        V\        4      '       d   VP                  V4       K?  \        V\        4      '       dO   VP                  e   VP                  M^pVP                  \        VP                   VP"                  V4      4       K  \
        P$                  ! V4      '       ds   \'        R4      '       d7   V P(                  ^ 8X  d&   \*        P,                  ! R\.        \1        4       R7       VP3                  4       ^ ,          pVP                  V4       EK1  R\5        V4       2p\7        V4      h	  V P;                  V4      #   \         d     ELoi ; i  \8         d    TR8w  d   h  EK  i ; i)aR  
Make a new :class:`pandas.MultiIndex` with the passed list of codes deleted.

This method allows for the removal of specified labels from a MultiIndex.
The labels to be removed can be provided as a list of tuples if no level
is specified, or as a list of labels from a specific level if the level
parameter is provided. This can be useful for refining the structure of a
MultiIndex to fit specific requirements.

Parameters
----------
codes : array-like
    Must be a list of tuples when ``level`` is not specified.
level : int or level name, default None
    Level from which the labels will be dropped.
errors : str, default 'raise'
    If 'ignore', suppress error and existing labels are dropped.

Returns
-------
MultiIndex
    A new MultiIndex with the specified labels removed.

See Also
--------
MultiIndex.remove_unused_levels : Create new MultiIndex from current that
    removes unused levels.
MultiIndex.reorder_levels : Rearrange levels using input order.
MultiIndex.rename : Rename levels in a MultiIndex.

Examples
--------
>>> idx = pd.MultiIndex.from_product(
...     [(0, 1, 2), ("green", "purple")], names=["number", "color"]
... )
>>> idx
MultiIndex([(0,  'green'),
            (0, 'purple'),
            (1,  'green'),
            (1, 'purple'),
            (2,  'green'),
            (2, 'purple')],
           names=['number', 'color'])
>>> idx.drop([(1, "green"), (2, "purple")])
MultiIndex([(0,  'green'),
            (0, 'purple'),
            (1, 'purple'),
            (2,  'green')],
           names=['number', 'color'])

We can also drop from a specific level.

>>> idx.drop("green", level="color")
MultiIndex([(0, 'purple'),
            (1, 'purple'),
            (2, 'purple')],
           names=['number', 'color'])

>>> idx.drop([1, 2], level=0)
MultiIndex([(0,  'green'),
            (0, 'purple')],
           names=['number', 'color'])
ro   r   performance_warningszYdropping on a non-lexsorted multi-index without a level parameter may impact performance.
stacklevelzunsupported indexer of type ignore)_drop_from_levelr   r   r   rE   r   index_labels_to_arrayr   r   r  r   r   ry  rz  r  r   r  stoprx  r   r   warningswarnr'   r+   nonzerorr  AssertionErrorr
  delete)	r   r   r   r  indsr   locrz  msgs	   &&&&     r_   dropMultiIndex.drop
  s   J ((v>>%"**e!45511%rxx?QR  Kll;/ c3''KK$U++'*xx';388DKKcii4 @A((--!"899d>Q>QUV>V P.'7'9	 ++-*CKK$8cDC(--- !6 {{4  ?  6  X% &s=   ,G 38G-A"GG-A/GGGGG54G5c                    V ^8  d   QhRRRR/# )rr   r  r   rt   r   rS   )ru   s   "r_   rv   r   9  s      $/	r^   c                	@   \         P                  ! V4      pV P                  V4      pV P                  V,          pVP	                  V4      p\        V4      pRV\        P                  ! VR4      VR8H  ,          &   VP                  ^ ,          V P                  ^ ,          8X  d   RV\        P                  ! VR4      &   WR8H  ,          p\        V4      ^ 8w  d   VR8w  d   \        RV R24      h\        P                  ! V P                  V,          V4      ( p	W	,          # )rr   FTr  zlabels z not found in levelr   )r   r  r8  r   get_indexerr>   r   equalr*  r   r
  r   isinr   )
r   r   r   r  r   r   r	  	nan_codes	not_foundr  s
   &&&&      r_   r  MultiIndex._drop_from_level9  s     ))%0""5)A""5) K	@BE*v|<=;;q>TZZ]*02F288It,-B,'	y>Q6X#5WYK/BCDD

4::a=&11zr^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r   N  s     J
 J
z J
r^   c                ^   \        V P                  4      p\        V P                  4      p\        V P                  4      pV P	                  V4      pV P	                  V4      pW2,          W1,          uW1&   W2&   WB,          WA,          uWA&   WB&   WR,          WQ,          uWQ&   WR&   \        W4VRR7      # )ah  
Swap level i with level j.

Calling this method does not change the ordering of the values.

Default is to swap the last two levels of the MultiIndex.

Parameters
----------
i : int, str, default -2
    First level of index to be swapped. Can pass level name as string.
    Type of parameters can be mixed. If i is a negative int, the first
    level is indexed relative to the end of the MultiIndex.
j : int, str, default -1
    Second level of index to be swapped. Can pass level name as string.
    Type of parameters can be mixed. If j is a negative int, the second
    level is indexed relative to the end of the MultiIndex.

Returns
-------
MultiIndex
    A new MultiIndex.

See Also
--------
Series.swaplevel : Swap levels i and j in a MultiIndex.
DataFrame.swaplevel : Swap levels i and j in a MultiIndex on a
    particular axis.

Examples
--------
>>> mi = pd.MultiIndex(
...     levels=[["a", "b"], ["bb", "aa"], ["aaa", "bbb"]],
...     codes=[[0, 0, 1, 1], [0, 1, 0, 1], [1, 0, 1, 0]],
... )
>>> mi
MultiIndex([('a', 'bb', 'bbb'),
            ('a', 'aa', 'aaa'),
            ('b', 'bb', 'bbb'),
            ('b', 'aa', 'aaa')],
           )
>>> mi.swaplevel()
MultiIndex([('a', 'bbb', 'bb'),
            ('a', 'aaa', 'aa'),
            ('b', 'bbb', 'bb'),
            ('b', 'aaa', 'aa')],
           )
>>> mi.swaplevel(0)
MultiIndex([('bbb', 'bb', 'a'),
            ('aaa', 'aa', 'a'),
            ('bbb', 'bb', 'b'),
            ('aaa', 'aa', 'b')],
           )
>>> mi.swaplevel(0, 1)
MultiIndex([('bb', 'a', 'bbb'),
            ('aa', 'a', 'aaa'),
            ('bb', 'b', 'bbb'),
            ('aa', 'b', 'aaa')],
        )
Fr  )r   r   r   rz   r8  r   )r   r   jr:  r   	new_namess   &&&   r_   	swaplevelMultiIndex.swaplevelN  s    z $++&
$	$	""1%""1%'1}jm$
z}%.\9<"	il%.\9<"	iliRW
 	
r^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r     s     0 0z 0r^   c                p    V Uu. uF  q P                  V4      NK  	  ppV P                  V4      pV# u upi )a>  
Rearrange levels using input order. May not drop or duplicate levels.

`reorder_levels` is useful when you need to change the order of levels in
a MultiIndex, such as when reordering levels for hierarchical indexing. It
maintains the integrity of the MultiIndex, ensuring that all existing levels
are present and no levels are duplicated. This method is helpful for aligning
the index structure with other data structures or for optimizing the order
for specific data operations.

Parameters
----------
order : list of int or list of str
    List representing new level order. Reference level by number
    (position) or by key (label).

Returns
-------
MultiIndex
    A new MultiIndex with levels rearranged according to the specified order.

See Also
--------
MultiIndex.swaplevel : Swap two levels of the MultiIndex.
MultiIndex.set_names : Set names for the MultiIndex levels.
DataFrame.reorder_levels : Reorder levels in a DataFrame with a MultiIndex.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([[1, 2], [3, 4]], names=["x", "y"])
>>> mi
MultiIndex([(1, 3),
            (2, 4)],
           names=['x', 'y'])

>>> mi.reorder_levels(order=[1, 0])
MultiIndex([(3, 1),
            (4, 2)],
           names=['y', 'x'])

>>> mi.reorder_levels(order=["y", "x"])
MultiIndex([(3, 1),
            (4, 2)],
           names=['y', 'x'])
)r8  _reorder_ilevels)r   orderr   r   s   &&  r_   reorder_levelsMultiIndex.reorder_levels  s<    \ 5::Eq''*E:&&u- ;s   3c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r     s     
 
 
r^   c                	~   \        V4      V P                  8w  d%   \        R V P                   R\        V4       24      hV Uu. uF  q P                  V,          NK  	  ppV Uu. uF  q P                  V,          NK  	  ppV Uu. uF  q P
                  V,          NK  	  pp\        W4VRR7      # u upi u upi u upi )z2Length of order must be same as number of levels (z), got Fr  )r   r   r  r   r   rz   r   )r   r  r   r:  r   r  s   &&    r_   r  MultiIndex._reorder_ilevels  s    u:% DT\\N S5zl$  /44ekk!nne
4,12EqZZ]]E	2,12EqZZ]]E	2iRW
 	
	 522s   B0$B5B:c                    V ^8  d   QhRRRR/# )rr   r   r   rt   zGenerator[np.ndarray]rS   )ru   s   "r_   rv   r     s      #'	r^   c             #  	4  "   \        V4      V P                  8  d&   \        R \        V4       RV P                   R24      h\        \        V4      4       F<  p\	        V P
                  V,          V P                  V,          W,          VR7      x  K>  	  R# 5i)zLength of new_levels (z) must be <= self.nlevels ()r4  N)r   r   r  r   rC   r   r   )r   r:  r   r   s   &&$ r_   _recode_for_new_levels!MultiIndex._recode_for_new_levels  s      z?T\\) (Z(9 :,,0LL><  s:'A'

1t{{1~z}4  (s   BBc                   V ^8  d   QhRR/# )rr   rt   zlist[Categorical]rS   )ru   s   "r_   rv   r     s     
 
(9 
r^   c           
         R R lpV P                    Uu. uF"  p\        P                  ! W!! V4      RRR7      NK$  	  up# u upi )z
we are categorizing our codes by using the
available categories (all, not just observed)
excluding any missing ones (-1); this is in preparation
for sorting, where we need to disambiguate that -1 is not
a valid valid
c                    V ^8  d   QhRRRR/# )rr   r   r   rt   rS   )ru   s   "r_   rv   7MultiIndex._get_codes_for_sorting.<locals>.__annotate__  s     	 	j 	Z 	r^   c                    \         P                  ! \        V 4      '       d   V P                  4       ^,           M^ V P                  R7      # )rd  r   )r   rg  r   r   r   )r   s   &r_   cats/MultiIndex._get_codes_for_sorting.<locals>.cats  s7    99),[)9)9!A%q!'' r^   TFre  )r   r@   
from_codes)r   r  r   s   &  r_   r  !MultiIndex._get_codes_for_sorting  sI    	  $zz
) "";[0A4RWX)
 	
 
s   (A c          
     ,    V ^8  d   QhRRRRRRRRR	R
/# )rr   r   r   	ascendingzbool | list[bool]sort_remainingr   r  r  rt   z'tuple[MultiIndex, npt.NDArray[np.intp]]rS   )ru   s   "r_   rv   r     sC     t" t"t" %t" 	t"
 t" 
1t"r^   c                   \        V4      '       g   V.pV Uu. uF  pV P                  V4      NK  	  ppRpV Uu. uF  qPP                  V,          NK  	  pp\        V\        4      '       d&   \        V4      \        V4      8X  g   \        R4      hMhV'       dX   TP                  \        \        V P                  4      4       Uu. uF  qUV9  g   K  V P                  V,          NK   	  up4       M	V^ ,          p\        WrVRR7      p\        V4      pV P                   U	u. uF  qP                  V4      NK  	  p
p	\        V
V P                  V P                  VRR7      pW3# u upi u upi u upi u up	i )a  
Sort MultiIndex at the requested level.

This method is useful when dealing with MultiIndex objects, allowing for
sorting at a specific level of the index. The function preserves the
relative ordering of data within the same level while sorting
the overall MultiIndex. The method provides flexibility with the `ascending`
parameter to define the sort order and with the `sort_remaining` parameter to
control whether the remaining levels should also be sorted. Sorting a
MultiIndex can be crucial when performing operations that require ordered
indices, such as grouping or merging datasets. The `na_position` argument is
important in handling missing values consistently across different levels.

Parameters
----------
level : list-like, int or str, default 0
    If a string is given, must be a name of the level.
    If list-like must be names or ints of levels.
ascending : bool, default True
    False to sort in descending order.
    Can also be a list to specify a directed ordering.
sort_remaining : bool, default True
    If True, sorts by the remaining levels after sorting by the specified
    `level`.
na_position : {'first' or 'last'}, default 'first'
    Argument 'first' puts NaNs at the beginning, 'last' puts NaNs at
    the end.

    .. versionadded:: 2.1.0

Returns
-------
sorted_index : pd.MultiIndex
    Resulting index.
indexer : np.ndarray[np.intp]
    Indices of output values in original index.

See Also
--------
MultiIndex : A multi-level, or hierarchical, index object for pandas objects.
Index.sort_values : Sort Index values.
DataFrame.sort_index : Sort DataFrame by the index.
Series.sort_index : Sort Series by the index.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([[0, 0], [2, 1]])
>>> mi
MultiIndex([(0, 2),
            (0, 1)],
           )

>>> mi.sortlevel()
(MultiIndex([(0, 1),
            (0, 2)],
           ), array([1, 0]))

>>> mi.sortlevel(sort_remaining=False)
(MultiIndex([(0, 2),
            (0, 1)],
           ), array([0, 1]))

>>> mi.sortlevel(1)
(MultiIndex([(0, 1),
            (0, 2)],
           ), array([1, 0]))

>>> mi.sortlevel(1, ascending=False)
(MultiIndex([(0, 2),
            (0, 1)],
           ), array([0, 1]))
Nz(level must have same length as ascendingT)ordersr  r  F)r   r   rz   r   r   )r3   r8  r   r   r   r   r   r  r   r   rK   r/   r  r   rz   )r   r   r  r  r  r6  r   r   r7  r   r   r  s   &&&&&       r_   	sortlevelMultiIndex.sortlevel  sd   ^ E""GE
 
 ""3' 	 
 	,12ESCE2i&&u:Y/ !KLL 0LL,1#dkk2B,CX,CSRWGWC,CX aI!$
 &g.BF**M*;%%g.*	M;;**"
	 !!C
 3 Y Ns   E$E)E.E."E3c                   V ^8  d   QhRR/# )rr   preserve_namesr   rS   )ru   s   "r_   rv   r   q  s      D r^   c                	
   \        V\        4      '       gI   Vf   T pMAV^ 8  P                  4       '       d   V P                  V4      pM \        P	                  V4      pV P                  W4      pV#   \
         d    Tu # i ; ir   )r   r   r   r  r   r{   _maybe_preserve_names)r   r  r7  r  s   &&&&r_   _wrap_reindex_resultMultiIndex._wrap_reindex_resultq  s|    &*--Q,##%%7+"'33F;F
 ++FC ! "!M"s   
A2 2BBc               $    V ^8  d   QhRRRRRR/# )rr   r  r    r  r   rt   rS   )ru   s   "r_   rv   r     s!      F D V r^   c                	    V'       dZ   VP                   V P                   8X  d?   VP                  V P                  8w  d$   VP                  R R7      pV P                  Vn        V# )Fr  )r   rz   r   )r   r  r  s   &&&r_   r   MultiIndex._maybe_preserve_names  sE    $,,.

*[[e[,F::FLr^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     ) )D )r^   c                	`    \        V4      '       d   \        V4      '       d   \        V4      hR # r   )r0   r2   r&   r  s   &&r_   _check_indexing_error MultiIndex._check_indexing_error  s)    3;s#3#3 $C((	 $4r^   c                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r     s     = = =r^   c                <    V P                   ^ ,          P                  # )z1
Should integer key(s) be treated as positional?
)r   _should_fallback_to_positionalr  s   &r_   r  )MultiIndex._should_fallback_to_positional  s     {{1~<<<r^   c                    V ^8  d   QhRRRR/# )rr   	axis_namer  rt   z"tuple[Index, npt.NDArray[np.intp]]rS   )ru   s   "r_   rv   r     s     ; ;!;	+;r^   c                	4  < Tp\        V\        4      '       g   \        P                  ! V4      p\	        V4      '       dK   \        V^ ,          \
        4      '       g.   V P                  V4      pV P                  WV4       W,          V3# \        SV `%  W4      # r  )
r   rE   r   r   r   r   _get_indexer_level_0_raise_if_missingsuper_get_indexer_strict)r   r  r  keyarrr7  	__class__s   &&&  r_   r  MultiIndex._get_indexer_strict  s}     &%((**62Fv;;z&)U;;//7G""3;='))w*3::r^   c                    V ^8  d   QhRRRR/# )rr   r  r  rt   r0  rS   )ru   s   "r_   rv   r     s     F F F Fr^   c                	  < Tp\        V\        4      '       g   \        P                  ! V4      p\	        V4      '       d   \        V^ ,          \
        4      '       g}   VR8H  pVP                  4       '       d`   V P                  ^ ,          P                  V4      pVR8H  pVP                  4       '       d   \        WG,           R24      h\        V R24      hR# \        SV `-  WV4      # )r   z not in indexNr   )r   rE   r   r   r   r   r   r   r  r
  r  r
  )	r   r  r7  r  r  r  checkcmaskr  s	   &&&&    r_   r
  MultiIndex._raise_if_missing  s    #u%%**3/Fv;;z&)U;; b=DxxzzA226:99;;"fm_M#BCC &788  7,S9EEr^   c                   V ^8  d   QhRR/# rr   rt   r  rS   )ru   s   "r_   rv   r     s     * *.B *r^   c                    V P                   ^ ,          pV P                  ^ ,          p\        P                  ! W2RR7      p\	        VRR7      pVP                  V4      # )zM
Optimized equivalent to `self.get_level_values(0).get_indexer_for(target)`.
F)r   
categoriesr   r4  )r   r   r@   r  rE   get_indexer_for)r   r  r6  r   catcis   &&    r_   r	  MultiIndex._get_indexer_level_0  sM     kk!nA$$55Q3U#!!&))r^   c               $    V ^8  d   QhRRRRRR/# )rr   labelzHashable | Sequence[Hashable]sideLiteral['left', 'right']rt   r   rS   )ru   s   "r_   rv   r     s(     4 4,4 '4 
	4r^   c                r    \        V\        4      '       g   V3pV P                  WR7      p\        V4      pV# )a  
For an ordered MultiIndex, compute slice bound
that corresponds to given label.

Returns leftmost (one-past-the-rightmost if `side=='right') position
of given label.

Parameters
----------
label : object or tuple of objects
side : {'left', 'right'}

Returns
-------
int
    Index of label.

Notes
-----
This method only works if level 0 index of the MultiIndex is lexsorted.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([list("abbc"), list("gefd")])

Get the locations from the leftmost 'b' in the first level
until the end of the multiindex:

>>> mi.get_slice_bound("b", side="left")
1

Like above, but if you get the locations from the rightmost
'b' in the first level and 'f' in the second level:

>>> mi.get_slice_bound(("b", "f"), side="right")
3

See Also
--------
MultiIndex.get_loc : Get location for a label or a tuple of labels.
MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                      sequence of such.
r  )r   r   _partial_tup_indexr-   )r   r  r  r   s   &&& r_   get_slice_boundMultiIndex.get_slice_bound  s;    ` %''HE(((:)&1r^   c                   V ^8  d   QhRR/# )rr   rt   ztuple[int, int]rS   )ru   s   "r_   rv   r      s     64 64_ 64r^   c                $   < \         SV `  WV4      # )a  
For an ordered MultiIndex, compute the slice locations for input
labels.

The input labels can be tuples representing partial levels, e.g. for a
MultiIndex with 3 levels, you can pass a single value (corresponding to
the first level), or a 1-, 2-, or 3-tuple.

Parameters
----------
start : label or tuple, default None
    If None, defaults to the beginning
end : label or tuple
    If None, defaults to the end
step : int or None
    Slice step

Returns
-------
(start, end) : (int, int)

Notes
-----
This method only works if the MultiIndex is properly lexsorted. So,
if only the first 2 levels of a 3-level MultiIndex are lexsorted,
you can only pass two levels to ``.slice_locs``.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays(
...     [list("abbd"), list("deff")], names=["A", "B"]
... )

Get the slice locations from the beginning of 'b' in the first level
until the end of the multiindex:

>>> mi.slice_locs(start="b")
(1, 4)

Like above, but stop at the end of 'b' in the first level and 'f' in
the second level:

>>> mi.slice_locs(start="b", end=("b", "f"))
(1, 3)

See Also
--------
MultiIndex.get_loc : Get location for a label or a tuple of labels.
MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                      sequence of such.
)r  
slice_locs)r   r  endrz  r  s   &&&&r_   r(  MultiIndex.slice_locs   s    l w!%d33r^   c                    V ^8  d   QhRRRR/# )rr   r  r   r  r   rS   )ru   s   "r_   rv   r   8  s     1K 1Ke 1K3K 1Kr^   c                	~   \        V4      V P                  8  d&   \        R \        V4       RV P                   R24      h\        V4      p^ \        V 4      rT\        WP                  V P
                  RR7      p\        V4       EF  w  pw  rp
WV pW9  d   \        V4      '       gq    \        P                  ! WVR7      p\        T4      '       g   \        RT 24      hTR8X  d   T^ 8  d
   T^,          pT\        P                  ! YTR7      ,           u # V P                  W4      p\        V\        4      '       d(   Ws^,
          8  d   VP                  pVP                   pK  Ws^,
          8  dB   V\        P                  ! WRR7      ,           pV\        P                  ! WR	R7      ,           pEK1  \        V\        4      '       d.   VP                  pV\        P                  ! WVR7      ,           u # V\        P                  ! WVR7      ,           u # 	  R#   \         d   p\        RT 24      ThRp?ii ; i)
Key length (z-) was greater than MultiIndex lexsort depth (r  Tr'  r"  zLevel type mismatch: Nrightleft)r   r   r(   r   r   r   	enumerater>   r   searchsortedr{   r1   _get_loc_single_level_indexr   ry  r  r  )r   r  r  nr  r)  zippedr  r  r6  r   sectionr  r  rD  s   &&&            r_   r#  MultiIndex._partial_tup_index8  s   s8d)))$s3xj )''(+ 
 HD	sS++tzz$?*3F*;&A&+!,G ~d3iiL,,SDAC "##&;C5$ABB7?sax1HCu11'TJJJ223<C#u%%!!e) 		hhU e00w 
  2 2v!  C''iiu11'TJJJu11'TJJJO +< ! L#&;C5$ABKLs   *HH<(H77H<c               $    V ^8  d   QhRRRRRR/# )rr   level_indexrE   r  r   rt   r   rS   )ru   s   "r_   rv   r   k  s"     , ,u ,8 ,PS ,r^   c                l    \        V4      '       d   \        V4      '       d   R# VP                  V4      # )a  
If key is NA value, location of index unify as -1.

Parameters
----------
level_index: Index
key : label

Returns
-------
loc : int
    If key is NA value, loc is -1
    Else, location of key in index.

See Also
--------
Index.get_loc : The get_loc method for (single-level) index.
r   )r5   r>   r  )r   r8  r  s   &&&r_   r2  &MultiIndex._get_loc_single_level_indexk  s+    & S>>d3iiI&&s++r^   c                b  a  S P                  V4       V 3R lp\        V\        4      '       g   S P                  V^ R7      pV! V4      # \	        V4      pS P
                  V8  d   \        RV RS P
                   R24      hVS P
                  8X  d/   S P                  '       d    S P                  P                  V4      # S P                  pVRV WR rV'       g   ^ p
\	        S 4      pM S P                  W4      w  rW8X  d   \        V4      hV	'       g   \        W4      # \!        R4      '       d&   \"        P$                  ! R\&        \)        4       R	7       \*        P,                  ! W\*        P.                  R
7      p\1        V	\	        V4      4       F}  w  r|S P2                  V,          V,          S P5                  S P6                  V,          V4      8H  pVP9                  4       '       g	   W=,          p\	        V4      '       d   Kt  \        V4      h	  \	        V4      W,
          8w  d	   V! V4      # \        W4      #   \         d   p\        T4      ThRp?i\         d-    S P                  T\        S P
                  4      4      w  r6Tu # i ; i  \         d   p\        T4      ThRp?ii ; i)aw  
Get location for a label or a tuple of labels. The location is returned         as an integer/slice or boolean mask.

This method returns the integer location, slice object, or boolean mask
corresponding to the specified key, which can be a single label or a tuple
of labels. The key represents a position in the MultiIndex, and the location
indicates where the key is found within the index.

Parameters
----------
key : label or tuple of labels (one for each level)
    A label or tuple of labels that correspond to the levels of the MultiIndex.
    The key must match the structure of the MultiIndex.

Returns
-------
int, slice object or boolean mask
    If the key is past the lexsort depth, the return may be a
    boolean mask array, otherwise it is always a slice or int.

See Also
--------
Index.get_loc : The get_loc method for (single-level) index.
MultiIndex.slice_locs : Get slice location given start label(s) and
                        end label(s).
MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                      sequence of such.

Notes
-----
The key cannot be a slice, list of same-level labels, a boolean mask,
or a sequence of such. If you want to use those, use
:meth:`MultiIndex.get_locs` instead.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([list("abb"), list("def")])

>>> mi.get_loc("b")
slice(1, 3, None)

>>> mi.get_loc(("b", "e"))
1
c                f  < \        V \        P                  4      '       d    V P                  \        P                  8w  d   V # \
        P                  ! V \        S4      4      p \        V \        4      '       d   V # \        P                  ! \        S4      RR7      pVP                  R4       RW&   V# )z<convert integer indexer to boolean mask or slice if possibler   r   FT)r   r   r   r   r  r   maybe_indices_to_slicer   ry  emptyfill)r  r  r   s   & r_   _maybe_to_slice+MultiIndex.get_loc.<locals>._maybe_to_slice  s|    c2::..#))rww2F
,,S#d)<C#u%%
88CIV4DIIeDIKr^   r   r-  z) exceeds index depth (r  Nr  z3indexing past lexsort depth may impact performance.r  r   )r   r   r   _get_level_indexerr   r   r
  r   rn  r  r{   get_loc_levelr   r   r(  ry  r   r  r  r'   r+   r   rg  r  r0  r   r2  r   r   )r   r  r@  r  keylenr  _r   lead_key
follow_keyr  r  r  r  s   f&            r_   r  MultiIndex.get_loc  sI   \ 	""3'	 #u%%))#Q)7C"3''S<<& vh&=dll^1M  T\\!dnnn||++C00 "2AwB*Et9D-"oohA =3-%%,--MME"+- ii2773j#h-8DA::a=%)I)IA* D 88::is88sm# 9 (+3x4<'?s#WU5EWWc  -sm, ++Ct||1DE
$  - sm,-s<   &H> ,J >J	IJ"*JJJ.J))J.c                    V ^8  d   QhRRRR/# )rr   r   r   
drop_levelr   rS   )ru   s   "r_   rv   r     s     ? ?
 ?D ?r^   c                R   \        V\        \        \        34      '       g   V P	                  V4      pMV Uu. uF  q@P	                  V4      NK  	  ppV P                  WR7      w  rVV'       g3   \        P                  ! V4      '       d   WV^,            pWV3# W,          pWV3# u upi )a]  
Get location and sliced index for requested label(s)/level(s).

The `get_loc_level` method is a more advanced form of `get_loc`, allowing
users to specify not just a label or sequence of labels, but also the level(s)
in which to search. This method is useful when you need to isolate particular
sections of a MultiIndex, either for further analysis or for slicing and
dicing the data. The method provides flexibility in terms of maintaining
or dropping levels from the resulting index based on the `drop_level`
parameter.

Parameters
----------
key : label or sequence of labels
    The label(s) for which to get the location.
level : int/level name or list thereof, optional
    The level(s) in the MultiIndex to consider. If not provided, defaults
    to the first level.
drop_level : bool, default True
    If ``False``, the resulting index will not drop any level.

Returns
-------
tuple
    A 2-tuple where the elements :

    Element 0: int, slice object or boolean array.

    Element 1: The resulting sliced multiindex/index. If the key
    contains all levels, this will be ``None``.

See Also
--------
MultiIndex.get_loc  : Get location for a label or a tuple of labels.
MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                      sequence of such.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([list("abb"), list("def")], names=["A", "B"])

>>> mi.get_loc_level("b")
(slice(1, 3, None), Index(['e', 'f'], dtype='str', name='B'))

>>> mi.get_loc_level("e", level="B")
(array([False,  True, False]), Index(['b'], dtype='str', name='A'))

>>> mi.get_loc_level(["b", "e"])
(1, None)
rB  )r   r   r   r   r8  _get_loc_levelr   r1   )r   r  r   rK  r6  r  r  s   &&&&   r_   rD  MultiIndex.get_loc_level  s    f %%u!566**51E<ABES++C0EEB%%c%7~~c""a( w Yw Cs   B$c                   V ^8  d   QhRR/# )rr   r   zint | list[int]rS   )ru   s   "r_   rv   r   E  s     S) S) S)r^   c                
  a  V 3R lp\        V\        \        34      '       d   \        V4      \        V4      8w  d   \	        R4      hRp\        W!RR7       Fh  w  rVS P                  WeR7      w  rx\        V\        4      '       d,   \        P                  ! \        S 4      \        R7      p	RW&   T	pVf   TMWG,          pKj  	   V! WB4      p
WJ3# \        V\        4      '       d   \        V4      p\        V\        4      '       Ed=   V^ 8X  Ed5    VS P                  ^ ,          9   d    S P                  WR7      pV! V^ .4      pW3#  \         ;QJ d    R V 4       F  '       g   K   RM	  R	M! R V 4       4      '       Egi   \        V4      S P"                  8X  d1   S P$                  '       d    S P&                  P)                  V4      R3# S P)                  V4      p\-        \        V4      4       Uu. uF  qV,          \        RR4      8w  g   K  VNK   	  pp\        V4      S P"                  8X  d   \/        V4      '       d   VR3# \-        \        V4      4       Uu. uF_  p\        W,          \0        4      '       d&   S P                  V,          P2                  '       d   KD  W,          \        RR4      8w  g   K]  VNKa  	  pp\        V4      S P"                  8X  d   . pW! W4      3# Rp\5        V4       F  w  r\        V\        4      '       g   S P                  WmR7      p\        V\        4      '       dp   \6        P8                  ! V4      '       g'   \6        P:                  ! V\        S 4      4      '       d   K  \        P                  ! \        S 4      \        R7      pRVV&   M/TpM,\6        P8                  ! V4      '       d   K  \        R
V 24      hVf   TpK  VV,          pK  	  Vf   \        RR4      p\-        \        V4      4       Uu. uF  qV,          \        RR4      8w  g   K  VNK   	  ppW! W4      3# S P                  WR7      p\        V\0        4      '       db   S P                  V,          P2                  '       d?   S P                  V,          P)                  V4      p\/        V4      '       g   VS V,          3#  V! W.4      pVV3#   \         d    S T,          p
 YJ3# i ; i  \        \        3 d     ELi ; i  \*         d   p\+        T4      ThRp?i\         d     ELii ; iu upi u upi u upi   \         d    S T,          p TT3# i ; i)zH
get_loc_level but with `level` known to be positional, not name-based.
c                f   < SV ,          p\        VRR7       F  pVP                  V.4      pK  	  V# )z^
If level does not exist or all levels were dropped, the exception
has to be handled outside.
T)reverse)sorted_drop_level_numbers)r7  r   r  r   r   s   &&  r_   maybe_mi_droplevels6MultiIndex._get_loc_level.<locals>.maybe_mi_droplevelsK  s9    
 WIFD1%991#>	 2 r^   z:Key for location must have same length as number of levelsNTr'  rB  r   c              3  B   "   T F  p\        V\        4      x  K  	  R # 5ir   )r   ry  r  s   & r_   r   ,MultiIndex._get_loc_level.<locals>.<genexpr>~  s     9Sz!U++Ss   Fz'Expected label or tuple of labels, got )r   r   r   r   r  r   rM  ry  r   r   r   r   r   rC  r{   r&   r   r   r   rn  r  r
  r   r1   r  !_supports_partial_string_indexingr0  r   is_null_sliceis_full_slice)r   r  r   rU  r   r6  r  r  r  r  r  r7  r  r   ilevels	loc_levelk_indexr  result_indexs   f&&                r_   rM  MultiIndex._get_loc_levelE  s   
	 eeT]++3x3u:%$P  Fe6!%!4!4Q!4!Bc5))88CIT:D $DIC &FL 7" )7 : c4  *Cc5!!eqj$++a.("55c5GG 3GaS AI"-- ) 39S93339S999s8t||+ $ 4 4S 94@@ ,,s+&+CHoUoQ5tCT9T11oUw<4<</!'**&}, "'s3x!0A *363 7 7#';;q>#S#S	   FeD$&77 !0   7|t||3"$ 3G EEE %cNDA%a//$($;$;A$;$G	%i77"00;;s?P?P )3t9@ @ !) ')hhs4y&EG15GI. '0G**1-- 
 (*QRUQV(WXX")7*; +< ?#D$/G&+CHoUoQ5tCT9T11oU 3G EEE--c-?G3$$KK&HHH E*2237!%(("DM11-27GD L((_  " &\:"$ 01  $ 5&sm4$   V` V   -#G}L((-s   S 6S6 0T 4T:T:AT?%T?>T?U2U	U	 S32S36T
TT7T%%T72T76T7	U#"U#c                    V ^8  d   QhRRRR/# )rr   r   r   r7  znpt.NDArray[np.bool_] | NonerS   )ru   s   "r_   rv   r     s$     oY oYoY,HoYr^   c                	   V P                   V,          pV P                  V,          pW53R  lp\        V\        4      '       Ed   VP                  pVRJ;'       d    V^ 8  p VP
                  e   VP                  VP
                  4      p	MV'       d   \        V4      ^,
          p	M^ p	VP                  e   VP                  VP                  4      p
M@V'       d   ^ p
M5\        V	\        4      '       d   \        V4      p
M\        V4      ^,
          p
 \        V	\        4      '       g   \        V
\        4      '       d$   \        V	RV	4      p	\        V
RV
4      p
V! WV4      # V^ 8  g   V P                  ^ 8X  g   Ve$   V'       d
   V
^,
          MV
^,           p
V! WV4      # \        P                  ! WYRR7      p\        P                  ! WZRR7      p\        WV4      # V P                  WA4      pV^ 8  g   V P                  ^ 8X  d{   \        V\        4      '       d$   W]P
                  8  W]P                  8  ,          pV# \         P"                  ! W]8H  \$        R7      pVP'                  4       '       g   \        V4      hV# \        V\        4      '       dF   \        P                  ! W]P
                  RR7      p	\        P                  ! W]P                  RR7      pM0\        P                  ! W]RR7      p	\        P                  ! W]RR7      pW8X  d   \        V4      h\        \)        V	4      \)        V4      4      #   \         dC    TP                  TP
                  TP                  TP                  4      ;rT	P                  p ELsi ; i)c                    Ve	   WC,          pVe   V^8X  d   W@8  WA8  ,          pM8\         P                  ! WW$P                  R7      p\        P                  ! WF4      pVf   V# VP                  4       pWSV&   V# )Nr   )r   rg  r   r   r  r   )r  r  rz  r7  r   new_indexerrs   &&&&&  r_   convert_indexer6MultiIndex._get_level_indexer.<locals>.convert_indexer  sq     " |tqy$~%,?IIe4{{C#jj2""llnG*GNr^   Nr  r  r/  r"  r.  r   )r   r   r   ry  rz  r  r  r   r  r
  slice_indexerr   r   r   r1  r2  r   r   r   r   r-   )r   r  r   r7  r8  r   rf  rz  is_negative_stepr  r  r   r  rD  locsr)  s   &&&&            r_   rC  MultiIndex._get_level_indexer  s    kk%(jj'7> 	, c5!! 88D#4/<<D1H"99('//		:E%,q0EE88'&..sxx8D%Du--{+D{+a/D %'':dE+B+B
  w6tVT2&uD99d11Q6$:J &6qD1H&uD99 &&{G&&{wGQ4(( 22;DCqyD//14c5))'994xx9OPDKzz+"4DAxxzz"3-'#u%%**;		O((hhVL**;&I((H|sm#1%8:RSV:WXXq  "  +88CHHchhWWzz	"s1   "1L: >L: L: L: !L:  L: :A	NNc                   V ^8  d   QhRR/# r  rS   )ru   s   "r_   rv   r   K  s     E7 E73 E7r^   c           	       a \        \        P                  ! V4      4       UUu. uF  w  r#V'       g   K  VNK  	  pppV'       d4   VR,          V P                  8  d   \	        RV RV P                   24      h\
        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4      h\        V 4      oR V3R llpR	p\        V4       EF  w  r'R	p\        P                  ! V4      '       do   \        V4      S8w  d   \        R
4      h\        V\        \        34      '       d   VP                  p\        P                  ! V4      pVf   VP!                  4       pM\#        V4      '       dB    V P%                  WrVR7      pVf)   \        P0                  ! . \        P2                  R7      u # Mu\        P4                  ! V4      '       dG   Vf@   V\        V4      ^,
          8X  d)   \        P6                  ! S\        P2                  R7      u # EKF  V P%                  WrVR7      pV! V4      pVf   TpEKj  Wh,          p\        P
                  ! V4      '       d   EK  \        P
                  ! V4      '       g   EK  \+        V4      h	  Vf'   \        P0                  ! . \        P2                  R7      # VP9                  4       ^ ,          pV P;                  W4      # u uppi   \&        \(        \*        3 dm   p	T F[  p
\-        T
4      '       g   T	hT P%                  YTR7      pTf   T! T4      pK7  \        T\.        4      '       d   RY&   KS  Y,          pK]  	   R	p	?	ELR	p	?	ii ; i)aO  
Get location for a sequence of labels.

Parameters
----------
seq : label, slice, list, mask or a sequence of such
   You should use one of the above for each level.
   If a level should not be used, set it to ``slice(None)``.

Returns
-------
numpy.ndarray
    NumPy array of integers suitable for passing to iloc.

See Also
--------
MultiIndex.get_loc : Get location for a label or a tuple of labels.
MultiIndex.slice_locs : Get slice location given start label(s) and
                        end label(s).

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([list("abb"), list("def")])

>>> mi.get_locs("b")  # doctest: +SKIP
array([1, 2], dtype=int64)

>>> mi.get_locs([slice(None), ["e", "f"]])  # doctest: +SKIP
array([1, 2], dtype=int64)

>>> mi.get_locs([[True, False, True], slice("e", "f")])  # doctest: +SKIP
array([2], dtype=int64)
zIMultiIndex slicing requires the index to be lexsorted: slicing on levels z, lexsort depth c              3  0   "   T F  q\         J x  K  	  R # 5ir   )EllipsisrM  s   & r_   r   &MultiIndex.get_locs.<locals>.<genexpr>v  s     *cH}cs   TFz2MultiIndex does not support indexing with Ellipsisc                   V ^8  d   QhRR/# rr   rt   r$  rS   )ru   s   "r_   rv   )MultiIndex.get_locs.<locals>.__annotate__}  s     	 	)> 	r^   c                   < \        V \        4      '       d-   \        P                  ! S\        P                  R 7      pRW&   V# V # )r   T)r   ry  r   r   bool_)r7  rd  r3  s   & r_   _to_bool_indexer-MultiIndex.get_locs.<locals>._to_bool_indexer}  s7    '5)) hhq9'+$""Nr^   NzLcannot index with a boolean indexer that is not the same length as the index)r   r7  r   r   )r0  r   is_true_slicesr   r(   r   r.  r   rx  r   r   r;   rE   r   r   r   r   r3   rC  r&   r{   r
  r0   ry  r   r  rZ  rg  r  _reorder_indexer)r   seqr   strue_slicesrv  r7  r  lvl_indexerr  r,  item_indexerpos_indexerr3  s   &&           @r_   get_locsMultiIndex.get_locsK  s   H (11C1CC1H'IO'IVaQqq'IO;r?d.A.AA$(M)9$:M:M9NP 
 3*c*333*c***%D  I	 	 15cNDA@DK""1%%q6Q;$>  a)U!344		A jjm?"-"2"2"4Ka8"&"9"9!g"9"VK0 & 88Bbgg66 '
 ""1%%?qCHqL'899Qbgg66 #55a'5R +;7K%&vvg266++>+>"3-'E #J ?88Bbgg..oo'*$$S66C PZ *9h? 8 *1~~"%I (,'>'> (? ( '.*:<*HK'e<<8<K5'7K 8s#   K.K.K44M6
A!M11M6c               $    V ^8  d   QhRRRRRR/# )rr   rz  z,tuple[Scalar | Iterable | AnyArrayLike, ...]r7  r  rt   rS   )ru   s   "r_   rv   r     s-     V V9V &V 
	Vr^   c                   Rp\        V4       EF7  w  rE\        P                  ! V4      '       g.   \        P                  ! V4      '       g   \	        V4      '       d   M\        V4      '       dv   \        V4      ^8:  d   MV P                  4       '       dL   V P                  V,          P                  V4      pWf^ 8  ,          pVRR VR,          8  P                  4       pMZRpMW\        V\        4      '       d@   V P                  4       '       d'   VP                  RJ;'       d    VP                  ^ 8  pMRpMRpV'       g   EK8   M	  V'       g   V# \        V 4      pRp\        V4       EFi  w  rE\	        V4      '       d   V.p\        P                  ! V4      '       d    \        P                  ! V4      V,          p	EM\        V4      '       Ed#   \        V\        P                   \"        \$        \&        34      '       g   \)        VR4      p\*        P,                  ! V4      p\        P.                  ! \        V P                  V,          4      \        P0                  R7      \        V P                  V,          4      ,          p
V P                  V,          P                  V4      pW^ 8  ,          p\        P                  ! \        V4      4      W&   WP2                  V,          V,          ,          p	M\        V\        4      '       dG   VP                  e9   VP                  ^ 8  d(   \        P                  ! V^,
          RR4      V,          p	M~\        V\        4      '       dL   VP4                  f>   VP6                  f0   \        P.                  ! V3\        P8                  R7      V,          p	M\        P                  ! V4      V,          p	V	.VO5pEKl  	  \        P:                  ! V4      pW,,          # )a  
Reorder an indexer of a MultiIndex (self) so that the labels are in the
same order as given in seq

Parameters
----------
seq : label/slice/list/mask or a sequence of such
indexer: a position indexer of self

Returns
-------
indexer : a sorted position indexer of self ordered as seq
FNrc  Tr   r   rS   )r0  r   rZ  rx  r5   r3   r   rV  r   r  r   r   ry  rz  r   rg  r   rA   rE   r;   rD   r   r;  onesrR   r   r  r  r  r  )r   rz  r7  	need_sortr   r  k_codesr3  r  	new_orderkey_order_maplevel_indexerinds   &&&          r_   ry  MultiIndex._reorder_indexer  s   ( 	cNDA  ##s':':1'='=1aq6Q;'')) #kk!n88;G%l3G!("!; @ @ BI $IAu%%%%'' !d 2 A AqvvzI $I 	y/ #0 NI') cNDA||C""1%%IIaL1	a!!bjj.%%STT&q$/ALLO "DKKN(;299 MPSKKNQ ! !%A : :1 = -q.@ A/1yy]9K/L,)**Q-*@A	Au%%!&&*<!IIa!eR4W=	Au%%!''/affnGGQD8A	 IIaL1	%%D; #@ jj|r^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r   ,  s     0
 0
: 0
r^   c                   V'       d   V'       d   W!8  d   \        R4      hV P                  ^ ,          P                  W4      w  r4V P                  W4      w  rV\        V P                  4      pV^ ,          W4 V^ &   V P                   Uu. uF  qWV NK  	  p	pV	^ ,          V,
          V	^ &   \        VV	V P                  RR7      # u upi )a  
Slice index between two labels / tuples, return new MultiIndex.

Parameters
----------
before : label or tuple, can be partial. Default None
    None defaults to start.
after : label or tuple, can be partial. Default None
    None defaults to end.

Returns
-------
MultiIndex
    The truncated MultiIndex.

See Also
--------
DataFrame.truncate : Truncate a DataFrame before and after some index values.
Series.truncate : Truncate a Series before and after some index values.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays([["a", "b", "c"], ["x", "y", "z"]])
>>> mi
MultiIndex([('a', 'x'), ('b', 'y'), ('c', 'z')],
           )
>>> mi.truncate(before="a", after="b")
MultiIndex([('a', 'x'), ('b', 'y')],
           )
zafter < beforeFr  )r   r   r(  r   r   r   r   )
r   beforeafterr   r  r/  r.  r:  r   r   s
   &&&       r_   truncateMultiIndex.truncate,  s    > V-..{{1~((7oof4$++&
"1a*
1@D

K
,
	K |a'	!++"	
 	
 Ls   
Cc                    V ^8  d   QhRRRR/# )rr   r  ro   rt   r   rS   )ru   s   "r_   rv   r   ^  s     - -F -t -r^   c                B   V P                  V4      '       d   R# \        V\        4      '       g   R# \        V 4      \        V4      8w  d   R# \        V\        4      '       g:   V P                  V4      '       g   R# \        V P                  VP                  4      # V P                  VP                  8w  d   R# \        V P                  4       F  pV P                  V,          pVP                  V,          pVR8H  pVR8H  p\        P                  ! WV4      '       g    R# V P                  V,          pVP                  V,          p\        WHVRR7      p	\        P                  ! W94      '       g    R# VR,          P                  VR,          4      '       d   K   R# 	  R# )z
Determines if two MultiIndex objects have the same labeling information
(the levels themselves do not necessarily have to be the same)

See Also
--------
equal_levels
TFr4  Nr   Nr   )is_r   rE   r   r   _should_comparer=   r   r   r   r   r   array_equalr   rC   equals)
r   r  r   
self_codesother_codes	self_mask
other_mask
self_levelother_levelr   s
   &&        r_   r  MultiIndex.equals^  s3    88E??%''t9E
"%,,''..#DLL%--@@<<5==(t||$AAJ++a.K"b(I$*J>>)88QJ,,q/K-*5I >>*88b>((R99! %" r^   c                    V ^8  d   QhRRRR/# )rr   r  r   rt   r   rS   )ru   s   "r_   rv   r     s      *  r^   c                    V P                   VP                   8w  d   R# \        V P                   4       F?  pV P                  V,          P                  VP                  V,          4      '       d   K>   R# 	  R# )zD
Return True if the levels of both MultiIndex objects are the same

FT)r   r   r   r  )r   r  r   s   && r_   equal_levelsMultiIndex.equal_levels  sS    
 <<5==(t||$A;;q>((a99 % r^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r     s     " "Z "r^   c                	d  < V P                  V4      w  rVP                  '       dl   \        \        V P	                  V4      `  VP	                  V4      V4      p\        V\        4      '       d   V# \        P                  \        VR R/ RVR7      # VP                  V RR7      p\        V4      '       d   V P                  V4      pMV P                  V4      pVRJd    VP                  4       pV# V#   \         d1    TRJ d   h \        P                   ! R\"        \%        4       R7        T# i ; i)r   TNr   Fr(  zTThe values in the array are unorderable. Pass `sort=False` to suppress this warning.r  )_convert_can_do_setophas_duplicatesr  r   rename_unionr   r   r   
differencer   r   _get_reconciled_name_objectsort_valuesr{   r  r  RuntimeWarningr+   )r   r  r(  result_namesr   right_missingr  s   &&&   r_   r  MultiIndex._union  s,   "88? :t{{<'@H\*DF &*--))V)D)T *  
 ",,T,>M=!!]399%@5 
#//1F M6M ! t|MMF&#3#5	 Ms    C4 47D/.D/c                    V ^8  d   QhRRRR/# )rr   r   r   rt   r   rS   )ru   s   "r_   rv   r     s     & &( &t &r^   c                	    \        V4      # r   )r4   )r   r   s   &&r_   _is_comparable_dtypeMultiIndex._is_comparable_dtype  s    u%%r^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r     s     % %J %r^   c                    V P                  V4      pV P                  V8w  d   V P                  V4      # V P                  RR7      # )zO
If the result of a set operation will be self,
return a shallow copy of self.
Fr  )_maybe_match_namesrz   r  r   )r   r  rz   s   && r_   r  &MultiIndex._get_reconciled_name_object  s@    
 ''.::;;u%%yyey$$r^   c                H   \        V P                  4      \        VP                  4      8w  d   R.\        V P                  4      ,          # . p\        V P                  VP                  RR7       F/  w  r4W48X  d   VP                  V4       K  VP                  R4       K1  	  V# )z
Try to find common names to attach to the result of an operation between
a and b. Return a consensus list of names if they match at least partly
or list of None if they have completely different names.
NTr'  )r   rz   r   r   )r   r  rz   a_nameb_names   &&   r_   r  MultiIndex._maybe_match_names  s|     tzz?c%++..6C

O++!$**ekk$GNFV$ T" H r^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r     s     . .* .r^   c                	J    V P                  V4      w  r4VP                  V4      # r   )r  	set_namesr   r  r   rF  r  s   &&&  r_   _wrap_intersection_result$MultiIndex._wrap_intersection_result  s%    44U;--r^   c                    V ^8  d   QhRRRR/# )rr   r   r   rt   rS   )ru   s   "r_   rv   r     s     2 2Z 2J 2r^   c                	    V P                  V4      w  r4\        V4      ^ 8X  d    VP                  4       P                  V4      # VP                  V4      # r  )r  r   rm  r  r  s   &&&  r_   _wrap_difference_result"MultiIndex._wrap_difference_result  sK    44U;v;!..0::<HH##L11r^   c                	B   V P                   p\        V\        4      '       gL   \        V4      ^ 8X  d   V R,          V P                   3# Rp \        P                  WP                   R7      pW3# \        W4      pW3#   \        \        3 d   p\        T4      ThRp?ii ; i)r   r  z.other must be a MultiIndex or a list of tuplesr  N)	rz   r   rE   r   r   r   r   r{   rG   )r   r  r  r  r  s   &&   r_   r   MultiIndex._convert_can_do_setop  s    zz%''5zQBx++F2&225

2KE "" /t;L"" #I. 2 $C.c12s    A< <BBBc                   V ^8  d   QhRR/# )rr   r   r   rS   )ru   s   "r_   rv   r      s     7 7$ 7r^   c                    \        V4      p\        V\        4      '       d   Rp\        V4      h\	        V4      '       g   \        R4      hVRJ d   V P                  4       # V # )a  
Create an MultiIndex with values cast to dtypes.

The class of a new Index is determined by dtype. When conversion is
impossible, a TypeError exception is raised.

Parameters
----------
dtype : numpy dtype or pandas type
    Note that any signed integer `dtype` is treated as ``'int64'``,
    and any unsigned integer `dtype` is treated as ``'uint64'``,
    regardless of the size.
copy : bool, default True
    By default, astype always returns a newly allocated object.
    If copy is set to False and internal requirements on dtype are
    satisfied, the original data is used to create a new Index
    or the original Index is returned.

Returns
-------
MultiIndex
    MultiIndex with values cast to specified dtype.

See Also
--------
Index.dtype: Return the dtype object of the underlying data.
Index.dtypes: Return the dtype object of the underlying data.
Index.convert_dtypes: Convert columns to the best possible dtypes.

Examples
--------
>>> mi = pd.MultiIndex.from_arrays(([1, 2, 3], [4, 5, 6]))
>>> mi
MultiIndex([(1, 4),
            (2, 5),
            (3, 6)],
           )
>>> mi.astype("object")
MultiIndex([(1, 4),
            (2, 5),
            (3, 6)],
           )
z3> 1 ndim Categorical are not supported at this timezISetting a MultiIndex dtype to anything other than object is not supportedT)r7   r   r8   r.  r4   r{   r5  )r   r   r   r  s   &&& r_   r  MultiIndex.astype   sd    X U#e-..GC%c**u%%#  4<::<r^   c                	T   \        V\        4      '       d3   VP                  V P                  8w  d   \        R 4      hVP                  # \        V\
        4      '       g%   V3RV P                  ^,
          ,          ,           pV# \        V4      V P                  8w  d   \        R 4      hV# )z0Item must have length equal to number of levels.)r  )r   r   r   r   r   r   r   )r   items   &&r_   _validate_fill_valueMultiIndex._validate_fill_value9  s    dJ''||t||+ !STT<<D%(( 7UdllQ&677D  Y$,,&OPPr^   c                    V ^8  d   QhRRRR/# )rr   r/  r   rt   rS   )ru   s   "r_   rv   r   G  s     &
 &
: &
* &
r^   c           	     R   \        W4      w  rV'       d   V P                  4       # \        V4      \        V4      8X  d   W!,          P                  4       pMVP                  4       p. p. p\	        \        VP                  V P                  V P                  RR7      4       Fm  w  pw  rp
V	P                  VRR7      pVP                  VP                  V4      4      p\        V
4      pWV&   VP                  V4       VP                  V4       Ko  	  \        WVV P                  RR7      # )z
Return a new MultiIndex of the values set with the mask.

Parameters
----------
mask : array like
value : MultiIndex
    Must either be the same length as self or length one

Returns
-------
MultiIndex
Tr'  Fr  r  )r?   r   r   rm  r0  r   r   r   r  r  rB  r.   r   r   rz   )r   r  r/  noopsubsetr:  r   r   value_levelr   r   	new_levelvalue_codesnew_codes   &&&           r_   putmaskMultiIndex.putmaskG  s    &d1
99;t9E
"[557F//1F
	4=t{{DJJtD5
0A0K Ke<I#33F4K4KA4NOK#K0H(TNi(X&5
 djjSX
 	
r^   c                    V ^8  d   QhRRRR/# )rr   r  r   rt   r   rS   )ru   s   "r_   rv   r   o  s     #
 #
# #

 #
r^   c                   V P                  V4      p. p. p\        W P                  V P                  RR7       F  w  rVpWV9  d7   \	        V4      pVP                  W4      p\        Wh,          4      '       d   RpMVP                  V4      pVP                  V4       VP                  \        P
                  ! \        V4      W4      4       K  	  \        W4V P                  RR7      # )z
Make new MultiIndex inserting new item at location

Parameters
----------
loc : int
item : tuple
    Must be same length as number of levels in the MultiIndex

Returns
-------
new_index : Index
Tr'  Fr  r   )r  r   r   r   r   insertr>   r  r   r   r.   r   rz   )	r   r  r  r:  r   r  r   r   lev_locs	   &&&      r_   r  MultiIndex.inserto  s     ((.
	%({{DJJt%T!Ak~ e*W0'' G--*e$RYY|K'@#OP &U djjSX
 	
r^   c                   V ^8  d   QhRR/# rz  rS   )ru   s   "r_   rv   r     s     
 
Z 
r^   c                    V P                    Uu. uF  p\        P                  ! W!4      NK  	  pp\        V P                  VV P
                  RR7      # u upi )zU
Make new index with passed location deleted

Returns
-------
new_index : MultiIndex
Fr  )r   r   r  r   r   rz   )r   r  r   r   s   &&  r_   r  MultiIndex.delete  sN     EIJJOJ[RYY{0J	O;;**"	
 	
 Ps   Ac                   V ^8  d   QhRR/# rr  rS   )ru   s   "r_   rv   r     s     T% T%*? T%r^   c                L   \        V\        4      '       d   \        V4      pVf   \        V4      ^ 8X  d1   \        P
                  ! \        V 4      3\        P                  R7      # \        V\        4      '       g   \        P                  V4      pVP                  4       P                  V 4      R8g  # V P                  V4      pV P                  V4      pVP                  ^ 8X  d0   \        P
                  ! \        V4      \        P                  R7      # VP                  V4      # )a  
Return a boolean array where the index values are in `values`.

Compute boolean array of whether each index value is found in the
passed set of values. The length of the returned boolean array matches
the length of the index.

Parameters
----------
values : set or list-like
    Sought values.
level : str or int, optional
    Name or position of the index level to use (if the index is a
    `MultiIndex`).

Returns
-------
np.ndarray[bool]
    NumPy array of boolean values.

See Also
--------
Series.isin : Same for Series.
DataFrame.isin : Same method for DataFrames.

Notes
-----
In the case of `MultiIndex` you must either specify `values` as a
list-like object containing tuples that are the same length as the
number of levels, or specify `level`. Otherwise it will raise a
``ValueError``.

If `level` is specified:

- if it is the name of one *and only one* index level, use that level;
- otherwise it should be a number indicating level position.

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

Check whether each index value in a list of values.

>>> idx.isin([1, 4])
array([ True, False, False])

>>> mi = pd.MultiIndex.from_arrays(
...     [[1, 2, 3], ["red", "blue", "green"]], names=["number", "color"]
... )
>>> mi
MultiIndex([(1,   'red'),
            (2,  'blue'),
            (3, 'green')],
           names=['number', 'color'])

Check whether the strings in the 'color' level of the MultiIndex
are in a list of colors.

>>> mi.isin(["red", "orange", "yellow"], level="color")
array([ True, False, False])

To check across the levels of a MultiIndex, pass a list of tuples:

>>> mi.isin([(1, "red"), (3, "red")])
array([ True, False, False])
r   r   )r   r   r   r   r   r   ru  r   r   r;  r  r8  rB  r"  r  )r   r	  r   numlevss   &&&  r_   r  MultiIndex.isin  s    J fi((&\F=6{axxTBHH==fj11#//7==?2248B>>((/C((-DyyA~xxD	::99V$$r^   __add____radd____iadd____sub____rsub____isub____pow____rpow____mul____rmul____floordiv____rfloordiv____truediv____rtruediv____mod____rmod__
__divmod____rdivmod____neg____pos____abs__
__invert__)r   r)  )NNNNFNT)NNN)NN)NFNr   F)first)r   )r   TN)Nraise)r   )r  r   )r   TTr  )r/  )r   Tr  )r   N)T)rT   rU   rV   rW   rX   rE   _hidden_attrs	frozenset_typr   __annotations__rH   r)  r   _comparablesr   r   r   classmethodr   r   r   r   r   r   r   r)   r   propertyr	  r   r  r  r"  r   r   rE  r   rP  r   r   r`  rn  rs  rw  r5  r   r  rY  r  r   r  r  r  r  r  r  r  r  r   rz   r  r8  r  r   r   _duplicatedr0  r8  r  rB  r;  rM  rR  rV  r   ra  rm  rs  r|  r  r  r   r^  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r
  r	  r$  r(  r#  r2  r  rD  rM  rC  r  ry  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rI   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r]   __classcell__)r  s   @r_   r   r      s   Sj '')+5M D$&F!&lG\F9L
,\*L\  !%?B~~	D
 D
L LI  LI\  !%?B~~	8D 8Dt CJ CJN  2   
 
 R R@"   B" B"H+ 	+
 + + "'+Zu#u>Bun ! !, 2 2<  4' 	'
 ' ' "''RD"D=ADR %G %GR & & 69^^ K"
Ob)V   < <""H # #4X$$$L=
 &*=D'6$ 6$p EB  6 K K< 2 2:%| KJ'/R42CJ)DZ ^^!&	WvD<&3P 8 8B
H`J7!F
$V
pJ1X5P/55PnA
Hj!X*J
X0d

(t"l ) = =; ;F F(*4l64 64p1Kf,2~X@?BS)joYbE7RVp0
d-^ " "H&%".2#*7 7r&
P#
J
 T%p __F
 i(Gz*Hz*Hi(Gz*Hz*Hi(Gz*Hi(Gz*H">2L#O4M!-0K">2Li(Gz*H .J!-0Ki(Gi(Gi(G .Jr^   r   c               $    V ^8  d   QhRRRRRR/# )rr   r   list[np.ndarray]r   r   rt   rS   )ru   s   "r_   rv   rv     s"      * S S r^   c                    V  Uu. uF  p\        V4      NK  	  pp\        V^ R4       F&  p\        P                  ! VRV 4      '       g   K$  Vu # 	  ^ # u upi )zJCount depth (up to a maximum of `nlevels`) with which codes are lexsorted.Nr   )r.   r   r  r  )r   r   r   int64_codesr  s   &&   r_   r   r     sU    @EF<,KF7Ar"  Ra11H # 	 Gs   Ac                    V ^8  d   QhRRRR/# )rr   r  r   r  ro   rS   )ru   s   "r_   rv   rv   #  s     + +s +& +r^   c           	        \        \        V R R/ 4      p\        V 4      pVRV^,            pW1,          pW1^,           R  F  p. p\        \        WgRR7      4       Fv  w  p	w  rW^,
          8X  d%   VP	                  V4       VP	                  V4        MAW8X  d   VP	                  V4       KR  VP                  WyR 4       VP	                  V4        M	  TpK  	  \        \        VR R/ 4      # )r   TNr'  )r   r   r   r0  r   r  )
label_listr  r  pivotedr  r   prevcur
sparse_curr   pts   &&&         r_   r  r  #  s    3
0401GJA[uqy!F>Dqy{#
"3t#>?IAvEz!!!$j)v!!(+!!#b'*j) @ ! $$ V)D)**r^   c                    V ^8  d   QhRRRR/# )rr   r   r   rt   r  rS   )ru   s   "r_   rv   rv   ?  s     P Px PC Pr^   c                    \        V \        4      '       d   V P                   # V P                  p\        P
                  R \        P                  R /P                  VR4      # )NaTNaN)r   r9   r  rr  r   
datetime64timedelta64get)r   
dtype_types   & r_   r  r  ?  sI    %((..!"ZZ
MM5"..%8<<ZOOr^   c                    V ^8  d   QhRRRR/# )rr   r   rE   rt   rS   )ru   s   "r_   rv   rv   H  s      E 5 r^   c                    T p\        V\        4      '       d   V F  p V P                  ^ .4      p K  	  V #  V P                  ^ .4      p V #   \         d    Tu u # i ; i  \         d     T # i ; i)z
Attempt to drop level or levels from the given index.

Parameters
----------
index: Index
key : scalar or tuple

Returns
-------
Index
)r   r   rT  r   )r   r  original_indexrF  s   &&  r_   maybe_droplevelsr"  H  s     N#u A&111#6  L	--qc2E L  &%%&  	L	s"   AA! AA!A0/A0c                    V ^8  d   QhRRRR/# )rr   r   r   rt   r   rS   )ru   s   "r_   rv   rv   i  s       * r^   c                n    \        W4      p V'       d   V P                  4       p RV P                  n        V # )z
Coerce the array-like indexer to the smallest integer dtype that can encode all
of the given categories.

Parameters
----------
array_like : array-like
categories : array-like
copy : bool

Returns
-------
np.ndarray
    Non-writeable.
F)r,   r   r  r  )
array_liker  r   s   &&&r_   rX  rX  i  s1      &j=J__&
!&Jr^   c                   V ^8  d   QhRR/# )rr   arrnamer  rS   )ru   s   "r_   rv   rv     s      3 r^   c                   V ep   \        V 4      '       g_   \        V4      '       g   \        V R24      h\        V4      ^ 8  d'   \        V^ ,          4      '       d   \        V R24      hV .p V.pW3# V e   \        V 4      '       d8   \        V4      '       d   \        V^ ,          4      '       g   \        V R24      hW3# )zL
Ensure that level is either None or listlike, and arr is list-of-listlike.
z must be list-likez must be list of lists-like)r3   r{   r   )r   r   r'  s   &&&r_   rC  rC    s     e!4!4C  wi'9:;;s8a<LQ00wi'9:;;e : 
,u--C  SV(<(<wi'BCDD:r^   c                    V ^8  d   QhRRRR/# )rr   Xr  rt   rS   )ru   s   "r_   rv   rv     s     6 6) 6.> 6r^   c                   Rp\        V 4      '       g   \        V4      hV  F  p\        V4      '       d   K  \        V4      h	  \        V 4      ^ 8X  d   . # \        P                  ! R V  4       \        P
                  R7      p\        P                  ! V4      p\        P                  ! V^ 8  4      '       d   \        R4      h\        P                  ! V^4      p^V^ &   VR,          ^ 8w  d   VR,          V,          pM\        P                  ! V4      p\        V 4       UUu. uFQ  w  rr\        P                  ! \        P                  ! W&V,          4      \        P                  ! WW,          4      4      NKS  	  upp# u uppi )a  
Numpy version of itertools.product.
Sometimes faster (for large inputs)...

Parameters
----------
X : list-like of list-likes

Returns
-------
product : list of ndarrays

Examples
--------
>>> cartesian_product([list("ABC"), [1, 2]])
[array(['A', 'A', 'B', 'B', 'C', 'C'], dtype='<U1'), array([1, 2, 1, 2, 1, 2])]

See Also
--------
itertools.product : Cartesian product of input iterables.  Equivalent to
    nested for-loops.
z'Input must be a list-like of list-likesc              3  8   "   T F  p\        V4      x  K  	  R # 5ir   r!  rM  s   & r_   r   $cartesian_product.<locals>.<genexpr>  s     *1ArO  r   z+Product space too large to allocate arrays!r   )r3   r{   r   r   fromiterr  cumprodr   r   roll
zeros_liker0  tiler  prod)r*  r  r,  lenXcumprodXabr   s   &       r_   r   r     s,   . 4C??nAC.   1v{	;;**"'':Dzz$H	vvhlFGG
!AAaD|qRL8# MM(# aL
 !DA	 	IIa1GGADM	
 !  s   "AE=)r   r  r  )
__future__r   collections.abcr   r   r   r   r   r	   	functoolsr
   	itertoolsr   sysr   typingr   r   r   r   r   r  numpyr   pandas._configr   pandas._libsr   r  r   rY   r   pandas._libs.hashtabler   pandas._typingr   r   r   r   r   r   r   r   r    r!   r"   r#   r$   pandas.compat.numpyr%   r  pandas.errorsr&   r'   r(   pandas.util._decoratorsr)   r*   pandas.util._exceptionsr+   pandas.core.dtypes.castr,   r-   pandas.core.dtypes.commonr.   r/   r0   r1   r2   r3   r4   r5   r6   r7   pandas.core.dtypes.dtypesr8   r9   pandas.core.dtypes.genericr:   r;   pandas.core.dtypes.inferencer<   pandas.core.dtypes.missingr=   r>   pandas.core.algorithmscore
algorithmspandas.core.array_algos.putmaskr?   pandas.core.arraysr@   rA   pandas.core.arrays.categoricalrB   rC   pandas.core.commoncommonr   pandas.core.constructionrD   pandas.core.indexes.baseindexesbaserp  rE   rF   rG   pandas.core.indexes.frozenrH   pandas.core.ops.invalidrI   pandas.core.sortingrJ   rK   pandas.io.formats.printingrL   r   rM   rN   rO   BaseMultiIndexCodesEnginerZ   rQ   rd   rb   rh   rf   rl   rj   rp   rn   r   r   r   r  r  r"  rX  rC  r   rS   r^   r_   <module>r^     s   "   !     % 
 .    / 
 5   7
 ' & < !   3 ( ( 
 2 3
 4 X??AVAV X??AVAV X??AVAV H>>@T@T 	H>>@U@U 	& HRE/ RE/ RE/jJ+8PB."6r^   