Ë
    *�£jëW  ã                  ód  — d Z ddlmZ ddlZddlmZmZ ddlZddl	m
Z
mZmZ ddlmZ ddlmZmZ ddlmZmZ dd	lmZ dd
lmZ er2ddlmZmZmZ ddlmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z% ddl&m'Z'm(Z( ddl)m*Z* ddl+m,Z, 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d d„Z-	 	 	 	 	 	 	 	 d!d„Z.	 	 	 	 d"d„Z/d#d„Z0	 	 	 	 	 	 d$d„Z1	 	 	 	 	 	 	 	 	 	 	 	 d%d„Z2	 	 	 	 d&	 	 	 	 	 	 	 	 	 d'd„Z3	 	 	 	 	 d(	 	 	 	 	 	 	 	 	 	 	 	 	 d)d„Z4d*d+d„Z5d,d„Z6	 d-	 	 	 	 	 d.d„Z7	 d-	 	 	 	 	 d/d„Z8	 	 	 	 	 	 d0d„Z9	 d-	 	 	 	 	 d1d„Z:	 d2	 	 	 	 	 d3d„Z;	 	 	 	 	 	 d4d„Z<y)5z)miscellaneous sorting / groupby utilitiesé    )ÚannotationsN)ÚTYPE_CHECKINGÚcast)ÚalgosÚ	hashtableÚlib)Úunique_label_indices)Úensure_int64Úensure_platform_int)ÚABCMultiIndexÚABCRangeIndex)Úisna)Úextract_array)ÚCallableÚHashableÚSequence)Ú	ArrayLikeÚAxisIntÚIndexKeyFuncÚLevelÚ
NaPositionÚShapeÚSortKindÚnpt)Ú
MultiIndexÚSeries)ÚExtensionArray©ÚIndexc                óÔ  — t        | ||¬«      } | j                  «       } |�| j                  ||||¬«      \  }}|S t        j                  |«      r| j
                  s!t        j                  |«      s| j                  ryt        | t        «      r8| j                  «       D �	cg c]  }	|	j                  ‘Œ }
}	t        |
||d¬«      }|S t        | |t        t        |«      |¬«      }|S c c}	w )a"  
    Helper method that return the indexer according to input parameters for
    the sort_index method of DataFrame and Series.

    Parameters
    ----------
    target : Index
    level : int or level name or list of ints or list of level names
    ascending : bool or list of bools, default True
    kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}
    na_position : {'first', 'last'}
    sort_remaining : bool
    key : callable, optional

    Returns
    -------
    Optional[ndarray[intp]]
        The indexer for the new index.
    )ÚlevelsN)Ú	ascendingÚsort_remainingÚna_positionT)Úordersr$   Úcodes_given)Úkindr"   r$   )Úensure_key_mappedÚ_sort_levels_monotonicÚ	sortlevelÚnpÚallÚis_monotonic_increasingÚanyÚis_monotonic_decreasingÚ
isinstancer   Ú_get_codes_for_sortingÚcodesÚlexsort_indexerÚnargsortr   Úbool)ÚtargetÚlevelr"   r'   r$   r#   ÚkeyÚ_ÚindexerÚlevr2   s              ú5C:\FundamentalWorkbench\vendor\pandas\core\sorting.pyÚget_indexer_indexerr=   :   sõ   € ô@ ˜v s°5Ô9€FØ×*Ñ*Ó,€FàÐØ×%Ñ%ØØØ)Ø#ð	 &ó 
‰
ˆˆ7ð0 €Nô% �&‰&�Ô
 × >Ò >Ü�F‰F�9Ô &×"@Ò"@ð Ü	�FœMÔ	*Ø&,×&CÑ&CÔ&EÓFÑ&E˜s�—“Ð&EˆÐFÜ!Ø˜)°È$ô
ˆð €Nô ØØÜœ4 Ó+Ø#ô	
ˆð €Nùò Gs   Â C%c                ó„  — dd„}dd„}| D �cg c]  }t        |«      ‘Œ } }t        |«      }|s4t        t        | |d¬«      «      D ]  \  }\  }	}
 ||	|
«      \  | |<   ||<   Œ 	  ||«      }t	        j
                  |d| d¬«      }|| d   j                  dd	d	¬
«      z  }t        d|«      D ]3  }||   dk(  rt	        j                  d«      }n|||   z  }|| |   |z  z  }Œ5 |r| d   dk(  }| d| D ]
  }	||	dk(  z  }Œ d||<   |t        |«      k(  r	 |S t        ||¬«      \  }}|g| |d ¢} t        |«      g||d ¢}ŒÚc c}w )a{  
    For the particular label_list, gets the offsets into the hypothetical list
    representing the totally ordered cartesian product of all possible label
    combinations, *as long as* this space fits within int64 bounds;
    otherwise, though group indices identify unique combinations of
    labels, they cannot be deconstructed.
    - If `sort`, rank of returned ids preserve lexical ranks of labels.
      i.e. returned id's can be used to do lexical sort on labels;
    - If `xnull` nulls (-1 labels) are passed through.

    Parameters
    ----------
    labels : sequence of arrays
        Integers identifying levels at each location
    shape : tuple[int, ...]
        Number of unique levels at each location
    sort : bool
        If the ranks of returned ids should match lexical ranks of labels
    xnull : bool
        If true nulls are excluded. i.e. -1 values in the labels are
        passed through.

    Returns
    -------
    An array of type int64 where two elements are equal if their corresponding
    labels are equal at all location.

    Notes
    -----
    The length of `labels` and `shape` must be identical.
    c                óŒ   — d}t        | «      D ]*  \  }}|t        |«      z  }|t        j                  k  rŒ(|c S  t	        | «      S ©Né   )Ú	enumerateÚintr   Úi8maxÚlen)ÚshapeÚaccÚiÚmuls       r<   Ú_int64_cut_offz'get_group_index.<locals>._int64_cut_offœ   sC   € ØˆÜ Ö&‰FˆAˆsØ”3�s“8‰OˆCØœŸ™“?Ø’ð 'ô �5‹zÐó    c                óD   — | dk(  j                  «       r
| dz   |dz   fS | |fS )NéÿÿÿÿrA   ©r.   )ÚlabÚsizes     r<   Ú
maybe_liftz#get_group_index.<locals>.maybe_lift¤   s-   € ð (+¨b¡y§o¡oÔ&7��a‘˜ ™Ð"ÐH¸cÀ4¸[ÐHrK   T©ÚstrictrA   Úi8©Údtyper   F©ÚsubokÚcopyrM   ©ÚsortN)ÚreturnrC   )rP   rC   r\   ztuple[np.ndarray, int])r
   ÚlistrB   Úzipr+   ÚprodÚastypeÚrangeÚint64rE   Úcompress_group_index)ÚlabelsrF   r[   ÚxnullrJ   rQ   ÚxÚlshaperH   rO   rP   ÚnlevÚstrideÚoutÚmaskÚcomp_idsÚobs_idss                    r<   Úget_group_indexrn   y   s”  € óFóIñ
 (.Ó.¡v !Œl˜1�o v€FÐ.Ü�%‹[€FÙÜ'¬¨F°EÀ$Ô(GÖH‰NˆA‰{��TÙ#-¨c°4Ó#8Ñ ˆF�1‰I�v˜a’yð Ið
 á˜fÓ%ˆô —‘˜  $˜¨tÔ4ˆØ�v˜a‘y×'Ñ'¨°EÀÐ'ÓFÑFˆä�q˜$–ˆAØ�a‰y˜AŠ~ÜŸ™ !›‘à˜6 !™9Ñ$�Ø�6˜!‘9˜vÑ%Ñ%‰Cð  ñ Ø˜!‘9 ‘?ˆDØ˜a “~�Ø˜˜r™	Ñ!‘ð &àˆC�‰Ià”3�v“;ÒØð €Jô 1°¸4Ô@Ñˆ�'àÐ+˜V D E˜]Ð+ˆÜ�g“,Ð/ ¨¨ Ð/ˆð; ùò /s   �D=c                ó:   — t        | |dd¬«      }t        |d¬«      S )a¾  
    Group_index is offsets into cartesian product of all possible labels. This
    space can be huge, so this function compresses it, by computing offsets
    (comp_ids) into the list of unique labels (obs_group_ids).

    Parameters
    ----------
    labels : list of label arrays
    sizes : tuple[int] of size of the levels

    Returns
    -------
    np.ndarray[np.intp]
        comp_ids
    np.ndarray[np.int64]
        obs_group_ids
    TF©r[   re   rZ   )rn   rc   )rd   ÚsizesÚidss      r<   Úget_compressed_idsrs   Ó   s!   € ô( ˜& %¨d¸%Ô
@€CÜ ¨$Ô/Ð/rK   c                óV   — d}| D ]  }|t        |«      z  }Œ |t        j                  k\  S r@   )rC   r   rD   )rF   Úthe_prodrf   s      r<   Úis_int64_overflow_possiblerv   ë   s0   € Ø€HÛˆØ”C˜“FÑ‰ð ð ”s—y‘yÑ Ð rK   c                óJ  — t        |«      rt        d«      ‚g }d}t        j                  d«      }| }t	        t        t        |«      «      «      D ]K  }||z
  |||   z  z  |z  }t        j                  || dk  d«       |j                  |«       ||z  }|||   z  }ŒM |d d d…   S )Nz,cannot deconstruct factorized group indices!rA   r   rM   )	rv   Ú
ValueErrorr+   ÚarrayÚreversedra   rE   ÚputmaskÚappend)Úcomp_labelsrF   Ú
label_listÚfactorÚyrf   rH   rd   s           r<   Ú_decons_group_indexr�   ó   s´   € ô " %Ô(ô ÐGÓHÐHà€JØ€FÜ
�‰�‹€AØ€AÜ”eœC ›JÓ'Ö(ˆØ�a‘%˜F U¨1¡XÑ-Ñ.°&Ñ8ˆÜ
�
‰
�6˜;¨™?¨BÔ/Ø×Ñ˜&Ô!Ø�V‰OˆØ�%˜‘(Ñ‰ð )ð ‘d˜�dÑÐrK   c                óô  — |s_t        j                  d„ |D «       t         j                  ¬«      }t        j                  |t         j                  ¬«      |z   }t	        |«      }t        |«      sDt        ||«      }|sj                  «       s|S t        ||d¬«      D ��	cg c]
  \  }}	||	z
  ‘Œ c}	}S t        | «      }
|D �cg c]'  }||
   j                  t         j                  dd¬«      ‘Œ) c}S c c}	}w c c}w )a6  
    Reconstruct labels from observed group ids.

    Parameters
    ----------
    comp_ids : np.ndarray[np.intp]
    obs_ids: np.ndarray[np.intp]
    shape : tuple[int]
    labels : Sequence[np.ndarray[np.signedinteger]]
    xnull : bool
        If nulls are excluded; i.e. -1 labels are passed through.
    c              3  óB   K  — | ]  }|d k(  j                  «       –— Œ y­w)rM   NrN   )Ú.0Úas     r<   Ú	<genexpr>z'decons_obs_group_ids.<locals>.<genexpr>  s   è ø€ Ð<±V°˜Q "™WŸM™MŸO±Vùs   ‚rU   TrR   FrW   )r+   ÚfromiterÚintpÚasarrayÚtuplerv   r�   r.   r^   r	   r`   )rl   rm   rF   rd   re   ÚliftÚ	arr_shaperj   rf   r€   r:   rO   s               r<   Údecons_obs_group_idsr�   	  sâ   € ñ& Ü�{‰{Ñ<±VÓ<ÄBÇGÁGÔLˆÜ—J‘J˜u¬B¯G©GÔ4°tÑ;ˆ	Ü�iÓ ˆä% eÔ,ä! '¨5Ó1ˆñ ˜DŸH™HœJð ð	
ô %(¨¨T¸$Õ$?Ô@Ñ$?™D˜A˜q�!�a“%Ð$?Ò@ð	
ô # 8Ó,€GÙLRÓSÉFÀSˆC�‰L×Ñ¤§¡¨u¸4ÐÕ@ÈFÑSÐSùó	 Aùò Ts   ÂC/Ã ,C5c                ó  — ddl m} |dvrt        d|› �«      ‚t        |t        «      r t        j                  |t        | «      «      }n-|€ t        j                  dt        | «      «      }nt        |«      }g }t        t        | «      |d¬«      D ]Ú  \  }}t        ||«      }|r;t        t        j                  |«      }	t        |	«      r|	j                  «       dz   nd}
n+ ||d¬«      }|j                  }	t        |j                   «      }
|	d	k(  }|d
k(  r'|j#                  «       rt        j$                  ||
|	«      }	|st        j$                  ||	|
|	z
  dz
  «      }	|j'                  |	«       ŒÜ t        j(                  |«      S )a÷  
    Performs lexical sorting on a set of keys

    Parameters
    ----------
    keys : Sequence[ArrayLike | Index | Series]
        Sequence of arrays to be sorted by the indexer
        Sequence[Series] is only if key is not None.
    orders : bool or list of booleans, optional
        Determines the sorting order for each element in keys. If a list,
        it must be the same length as keys. This determines whether the
        corresponding element in keys should be sorted in ascending
        (True) or descending (False) order. if bool, applied to all
        elements as above. if None, defaults to True.
    na_position : {'first', 'last'}, default 'last'
        Determines placement of NA elements in the sorted list ("last" or "first")
    key : Callable, optional
        Callable key function applied to every element in keys before sorting
    codes_given: bool, False
        Avoid categorical materialization if codes are already provided.

    Returns
    -------
    np.ndarray[np.intp]
    r   )ÚCategorical)ÚlastÚfirstúinvalid na_position: TrR   rA   )ÚorderedrM   r�   )Úpandas.core.arraysr�   rx   r0   r5   Ú	itertoolsÚrepeatrE   rz   r^   r(   r   r+   ÚndarrayÚmaxr2   Ú
categoriesr.   Úwherer|   Úlexsort)Úkeysr%   r$   r8   r&   r�   rd   ÚkÚorderr2   ÚnÚcatrk   s                r<   r3   r3   .  sI  € õ@ /àÐ+Ñ+ÜÐ0°°Ð>Ó?Ð?ä�&œ$ÔÜ×!Ñ! &¬#¨d«)Ó4‰Ø	ˆÜ×!Ñ! $¬¨D«	Ó2‰ä˜&Ó!ˆà€Fäœ ›¨°t×<‰ˆˆ5Ü˜a Ó%ˆÙÜœŸ™ QÓ'ˆEÜ#& u¤:�—	‘	“˜a’°1‰Aá˜a¨Ô.ˆCØ—I‘IˆEÜ�C—N‘NÓ#ˆAà˜‰{ˆà˜&Ò  T§X¡X¤ZÜ—H‘H˜T 1 eÓ,ˆEñ Ü—H‘H˜T 5¨!¨e©)°a©-Ó8ˆEà�‰�eÕð' =ô* �:‰:�fÓÐrK   c                ó  — |�t        | |«      } t        | |||d|¬«      S t        | t        «      r| j	                  |¬«      S t        | t
        «      st        | «      } nt        d«      ‚|€t        j                  t        | «      «      }t        | t        j                  «      s| j	                  |||¬«      S t        j                  t        | «      «      }| |    }||    }t        j                  |«      d   }	|s|ddd…   }|ddd…   }||j	                  |¬«         }
|s|
ddd…   }
|d	k(  r"t        j                  |
|	g«      }
t#        |
«      S |d
k(  r"t        j                  |	|
g«      }
t#        |
«      S t!        d|› �«      ‚)al  
    Intended to be a drop-in replacement for np.argsort which handles NaNs.

    Adds ascending, na_position, and key parameters.

    (GH #6399, #5231, #27237)

    Parameters
    ----------
    items : np.ndarray, ExtensionArray, Index, or Series
    kind : {'quicksort', 'mergesort', 'heapsort', 'stable'}, default 'quicksort'
    ascending : bool, default True
    na_position : {'first', 'last'}, default 'last'
    key : Optional[Callable], default None
    mask : Optional[np.ndarray[bool]], default None
        Passed when called by ExtensionArray.argsort.

    Returns
    -------
    np.ndarray[np.intp]
    N)r'   r"   r$   r8   rk   )r"   zDnargsort does not support MultiIndex. Use index.sort_values instead.)r"   r'   r$   r   rM   ©r'   r�   r‘   r’   )r(   r4   r0   r   Úargsortr   r   Ú	TypeErrorr+   r‰   r   r—   ÚarangerE   ÚnonzeroÚconcatenaterx   r   )Úitemsr'   r"   r$   r8   rk   ÚidxÚnon_nansÚnon_nan_idxÚnan_idxr:   s              r<   r4   r4   t  s§  € ð< €ä! %¨Ó-ˆÜØØØØ#ØØô
ð 	
ô �%œÔ'Ø�}‰} yˆ}Ó1Ð1Ü˜œ}Ô-Ü˜eÓ$‰äØRó
ð 	
ð €|Ü�z‰zœ$˜u›+Ó&ˆä�eœRŸZ™ZÔ(à�}‰}ØØØ#ð ó 
ð 	
ô �)‰)”C˜“JÓ
€CØ�d�U‰|€HØ�t�e‘*€Kä�j‰j˜Ó˜qÑ!€GÙØ™D˜b˜D‘>ˆØ!¡$ B $Ñ'ˆØ˜(×*Ñ*°Ð*Ó5Ñ6€GÙØ™$˜B˜$‘-ˆð �fÒÜ—.‘. '¨7Ð!3Ó4ˆô
 ˜wÓ'Ð'ð	 
˜Ò	Ü—.‘. '¨7Ð!3Ó4ˆô ˜wÓ'Ð'ô Ð0°°Ð>Ó?Ð?rK   c                óþ  — |dv sJ ‚|dk(  rt         j                  nt         j                  }t        j                  t	        | «      «      }| j                  «       }|j                  dkD  rƒ|j                  «       ri|dk(  rt        ||d¬«      }n"t        |j                  |j                  d¬«      }t        j                  |D ��cg c]  \  }}t        |||«      ‘Œ c}}«      S  |||¬«      S t        |||«      S c c}}w )a  
    Implementation of np.argmin/argmax but for ExtensionArray and which
    handles missing values.

    Parameters
    ----------
    values : ExtensionArray
    method : {"argmax", "argmin"}
    axis : int, default 0

    Returns
    -------
    int
    >   ÚargmaxÚargminr®   rA   TrR   )Úaxis)r+   r®   r¯   r‰   r   Ú_values_for_argsortÚndimr.   r^   ÚTry   Ú_nanargminmax)	ÚvaluesÚmethodr°   Úfuncrk   Ú
arr_valuesÚzippedÚvÚms	            r<   Ú
nargminmaxr¼   È  sÖ   € ð Ð)Ñ)Ð)Ð)Ø (Ò*Œ2�9Š9´·	±	€Dä�:‰:”d˜6“lÓ#€DØ×+Ñ+Ó-€Jà‡�˜ÒØ�8‰8Œ:Ø�qŠyÜ˜Z¨°dÔ;‘ä˜ZŸ\™\¨4¯6©6¸$Ô?�Ü—8‘8Á6ÔJÁ6¹4¸1¸aœ]¨1¨a°Õ6À6ÒJÓKÐKÙ�J TÔ*Ð*ä˜ T¨4Ó0Ð0ùó Ks   ÃC9
c                ót   — t        j                  | j                  d   «      }| |    }||    }| ||«         S )z#
    See nanargminmax.__doc__.
    r   )r+   r¥   rF   )rµ   rk   r·   r©   rª   r«   s         r<   r´   r´   é  s?   € ô �)‰)�F—L‘L ‘OÓ
$€CØ�t�e‰}€HØ�t�e‘*€Kà‘t˜H“~Ñ&Ð&rK   c                óŽ  — |�;t        |t        t        f«      r|g}n|}|D �ch c]  }| j                  |«      ’Œ }}nt	        | j
                  «      }t	        | j
                  «      D �cg c]2  }||v rt        | j                  |«      |«      n| j                  |«      ‘Œ4 }}t        | «      j                  |«      S c c}w c c}w )ad  
    Returns a new MultiIndex in which key has been applied
    to all levels specified in level (or all levels if level
    is None). Used for key sorting for MultiIndex.

    Parameters
    ----------
    index : MultiIndex
        Index to which to apply the key function on the
        specified levels.
    key : Callable
        Function that takes an Index and returns an Index of
        the same shape. This key is applied to each level
        separately. The name of the level can be used to
        distinguish different levels for application.
    level : list-like, int or str, default None
        Level or list of levels to apply the key function to.
        If None, key function is applied to all levels. Other
        levels are left unchanged.

    Returns
    -------
    labels : MultiIndex
        Resulting MultiIndex with modified levels.
    )
r0   ÚstrrC   Ú_get_level_numberra   Únlevelsr(   Ú_get_level_valuesÚtypeÚfrom_arrays)Úindexr8   r7   Ú
level_iterr;   Úsort_levelsÚmappeds          r<   Ú_ensure_key_mapped_multiindexrÉ   ô  sÑ   € ð: ÐÜ�eœc¤3˜ZÔ(Ø˜‰JàˆJáLVÓ#WÉJÀS E×$;Ñ$;¸CÕ$@ÈJˆÑ#Wä˜EŸM™MÓ*ˆô ˜5Ÿ=™=Ô)óñ *ˆEð ˜Ñ#ô ˜e×5Ñ5°eÓ<¸cÔBà×(Ñ(¨Ó/ñ0ð *ð ð ô �‹;×"Ñ" 6Ó*Ð*ùò $Xùòs   £B=Á*7Cc           	     óŒ  — ddl m} |s| S t        | t        «      rt	        | ||¬«      S  || j                  «       «      }t        |«      t        | «      k7  rt        d«      ‚	 t        | |«      r ||d¬«      }|S t        | «      } ||«      }	 |S # t        $ r*}t        dt        |«      › dt        | «      › d	�«      |‚d
}~ww xY w)aÁ  
    Applies a callable key function to the values function and checks
    that the resulting value has the same shape. Can be called on Index
    subclasses, Series, DataFrames, or ndarrays.

    Parameters
    ----------
    values : Series, DataFrame, Index subclass, or ndarray
    key : Optional[Callable], key to be called on the values array
    levels : Optional[List], if values is a MultiIndex, list of levels to
    apply the key to.
    r   r   )r7   zDUser-provided `key` function must not change the shape of the array.F)Útupleize_colsz6User-provided `key` function returned an invalid type z-             which could not be converted to Ú.N)
Úpandas.core.indexes.apir   r0   r   rÉ   rY   rE   rx   rÃ   r¤   )rµ   r8   r!   r   ÚresultÚtype_of_valuesÚerrs          r<   r(   r(   '  sà   € õ .áØˆä�&œ-Ô(Ü,¨V°SÀÔGÐGá�—‘“Ó€FÜ
ˆ6ƒ{”c˜&“kÒ!ÜØRó
ð 	
ðÜØ�Eô
ñ ˜6°Ô7ˆFð €Mô " &›\ˆNá# FÓ+‰Fð €Møô ò ÜØDÄTÈ&Ã\ÀNð S-Ü-1°&«\¨N¸!ð=ó
ð ð	ûðús   Á"B Á:B Â	CÂ%B>Â>Cc                ó®  — t        d„ |D «       «      }t        | |dd¬«      }t        j                  |dk(  «      ri S t	        |«      r!|j
                  xr |j                  «       dz   nt        j                  |d¬«      }t        ||«      }| D �cg c]  }|j                  |«      ‘Œ }}|j                  |«      }t        j                  ||||«      S c c}w )zJ
    Returns
    -------
    dict:
        Labels mapped to indexers.
    c              3  ó2   K  — | ]  }t        |«      –— Œ y ­w©N)rE   )r„   rf   s     r<   r†   z#get_indexer_dict.<locals>.<genexpr>`  s   è ø€ Ð'¡$˜Q”#�a—&¡$ùs   ‚Trp   rM   rA   rT   rU   )rŠ   rn   r+   r,   rv   rP   r˜   r_   Úget_group_index_sorterÚtaker   Úindices_fast)r~   rœ   rF   Úgroup_indexÚngroupsÚsorterrO   Úsorted_labelss           r<   Úget_indexer_dictrÛ   W  sÊ   € ô Ñ'¡$Ó'Ó'€Eä! *¨e¸$ÀdÔK€KÜ	‡v�vˆk˜RÑÔ àˆ	ô & eÔ,ð ×
Ñ
Ò
0˜{Ÿ™Ó0°AÒ	5ä�W‰W�U $Ô'ð ô $ K°Ó9€Fá1;Ó<±¨#�S—X‘X˜fÕ%°€MÐ<Ø×"Ñ" 6Ó*€Kä×Ñ˜F K°°}ÓEÐEùò =s   ÂCc                ó2  — |€d| j                  «       z   }t        | «      }d}d}|dkD  xr! |||z  z   |t        j                  |«      z  k  }|r-t	        j
                  t        | «      |«      \  }}t        |«      S | j                  d¬«      }t        |«      S )a	  
    algos.groupsort_indexer implements `counting sort` and it is at least
    O(ngroups), where
        ngroups = prod(shape)
        shape = map(len, keys)
    that is, linear in the number of combinations (cartesian product) of unique
    values of groupby keys. This can be huge when doing multi-key groupby.
    np.argsort(kind='mergesort') is O(count x log(count)) where count is the
    length of the data-frame;
    Both algorithms are `stable` sort and that is necessary for correctness of
    groupby operations. e.g. consider:
        df.groupby(key)[col].transform('first')

    Parameters
    ----------
    group_index : np.ndarray[np.intp]
        signed integer dtype
    ngroups : int or None, default None

    Returns
    -------
    np.ndarray[np.intp]
    rA   g        g      ð?r   Ú	mergesortr¢   )r˜   rE   r+   Úlogr   Úgroupsort_indexerr   r£   )r×   rØ   ÚcountÚalphaÚbetaÚdo_groupsortrÙ   r9   s           r<   rÔ   rÔ   x  s¦   € ð4 €Ø�k—o‘oÓ'Ñ'ˆÜ�Ó€EØ€EØ€DØ˜1‘9ÒU 5¨4°'©>Ñ#9¸eÄbÇfÁfÈUÃmÑ>SÑ"T€LÙÜ×+Ñ+Ü Ó,Øó
‰	ˆ�ô ˜vÓ&Ð&ð ×$Ñ$¨+Ð$Ó6ˆÜ˜vÓ&Ð&rK   c                ó¾  — t        | «      r_t        j                  | dd | dd k\  «      rAt        j                  | dd dkD  | dd | dd k7  g«      }|j	                  «       }|dz  }| |   }n^t        | «      }t        j                  |«      }t        | «      } |j                  | «      \  }}|rt        |«      dkD  rt        ||«      \  }}t        |«      t        |«      fS )zß
    Group_index is offsets into cartesian product of all possible labels. This
    space can be huge, so this function compresses it, by computing offsets
    (comp_ids) into the list of unique labels (obs_group_ids).
    rA   NrM   r   )
rE   r+   r,   r§   Úcumsumr   ÚInt64HashTabler
   Úget_labels_groupbyÚ_reorder_by_uniques)r×   r[   Úunique_maskrl   Úobs_group_idsÚ	size_hintÚtables          r<   rc   rc   £  sï   € ô ˆ;ÔœBŸF™F ;¨q¨r ?°kÀ#À2Ð6FÑ#FÔGä—n‘nØ˜˜!ˆ_˜rÑ! ;¨q¨r ?°kÀ#À2Ð6FÑ#FÐGó
ˆð ×%Ñ%Ó'ˆØ�A‰ˆØ# KÑ0‰ä˜Ó$ˆ	Ü×(Ñ(¨Ó3ˆä" ;Ó/ˆð #(×":Ñ":¸;Ó"GÑˆ�-á”C˜Ó&¨Ò*Ü&9¸-ÈÓ&RÑ#ˆM˜8ä˜Ó!¤<°Ó#>Ð>Ð>rK   c                ó^  — | j                  «       }t        j                  t        |«      t        j                  ¬«      }|j                  |t        j                  t        |«      «      «       |dk  }|j                  |«      }t        j                  ||d«       | j                  |«      } | |fS )z±
    Parameters
    ----------
    uniques : np.ndarray[np.int64]
    labels : np.ndarray[np.intp]

    Returns
    -------
    np.ndarray[np.int64]
    np.ndarray[np.intp]
    rU   r   rM   )	r£   r+   ÚemptyrE   rˆ   Úputr¥   rÕ   r{   )Úuniquesrd   rÙ   Úreverse_indexerrk   s        r<   rè   rè   Â  sŒ   € ð �_‰_Ó€Fô —h‘hœs 6›{´"·'±'Ô:€OØ×Ñ˜¤§	¡	¬#¨f«+Ó 6Ô7à�A‰:€Dð ×!Ñ! &Ó)€FÜ‡J�Jˆv�t˜RÔ ð �l‰l˜6Ó"€Gà�Fˆ?ÐrK   )r6   r   r7   zLevel | list[Level] | Noner"   zlist[bool] | boolr'   r   r$   r   r#   r5   r8   r   r\   znpt.NDArray[np.intp] | None)rF   r   r[   r5   re   r5   r\   únpt.NDArray[np.int64])rq   r   r\   z2tuple[npt.NDArray[np.intp], npt.NDArray[np.int64]])rF   r   r\   r5   )r}   únpt.NDArray[np.intp]rF   r   r\   úlist[npt.NDArray[np.intp]])rl   ró   rm   ró   rF   r   rd   z'Sequence[npt.NDArray[np.signedinteger]]re   r5   r\   rô   )Nr�   NF)
rœ   z$Sequence[ArrayLike | Index | Series]r$   r¿   r8   úCallable | Noner&   r5   r\   ró   )Ú	quicksortTr�   NN)r¨   úArrayLike | Index | Seriesr'   r   r"   r5   r$   r¿   r8   rõ   rk   znpt.NDArray[np.bool_] | Noner\   ró   )r   )rµ   r   r¶   r¿   r°   r   )rµ   z
np.ndarrayrk   znpt.NDArray[np.bool_]r\   rC   rÓ   )rÅ   r   r8   r   r\   r   )rµ   r÷   r8   rõ   r\   r÷   )r~   zlist[np.ndarray]rœ   zlist[Index]r\   z$dict[Hashable, npt.NDArray[np.intp]])r×   ró   rØ   z
int | Noner\   ró   )T)r×   rò   r[   r5   r\   z3tuple[npt.NDArray[np.int64], npt.NDArray[np.int64]])rð   rò   rd   ró   r\   z2tuple[npt.NDArray[np.int64], npt.NDArray[np.intp]])=Ú__doc__Ú
__future__r   r•   Útypingr   r   Únumpyr+   Úpandas._libsr   r   r   Úpandas._libs.hashtabler	   Úpandas.core.dtypes.commonr
   r   Úpandas.core.dtypes.genericr   r   Úpandas.core.dtypes.missingr   Úpandas.core.constructionr   Úcollections.abcr   r   r   Úpandas._typingr   r   r   r   r   r   r   r   Úpandasr   r   r”   r   Úpandas.core.indexes.baser   r=   rn   rs   rv   r�   r�   r3   r4   r¼   r´   rÉ   r(   rÛ   rÔ   rc   rè   © rK   r<   Ú<module>r     sÞ  ðÙ /å "ã ÷ó
 ÷ñ õ
 8÷÷õ ,å 2á÷ñ ÷	÷ 	ó 	÷õ 2Ý.ð<Øð<à%ð<ð !ð<ð ð	<ð
 ð<ð ð<ð 
ð<ð !ó<ð~WØðWØ $ðWØ-1ðWàóWðt0Øð0à7ó0ó0!ðØ%ðØ.3ðàóð,"TØ"ð"Tà!ð"Tð ð"Tð 4ð	"Tð
 ð"Tð  ó"TðN ØØØðCØ
.ðCð ðCð 
ð	Cð
 ðCð óCðP !ØØØØ)-ðQ(Ø%ðQ(à
ðQ(ð ðQ(ð ð	Q(ð
 
ðQ(ð 'ðQ(ð óQ(ôh1óB'ð -1ð0+Øð0+Ø$ð0+àó0+ðh FJð-Ø&ð-Ø-<ð-àó-ð`FØ ðFØ(3ðFà)óFðD >Bð('Ø%ð('Ø0:ð('àó('ðX 6:ð?Ø&ð?Ø.2ð?à8ó?ð>Ø"ðØ,@ðà7ôrK   