+
    Ŝi                      a  0 t $ R t^ RIHt ^ RIHt ^ RIHt ^ RIt^ RI	H
t
 ^ RIHt ^ RIHtHtHtHtHtHt ^ RIt^ RIt^ RIHt ^ R	IHt ^ R
IHtHt ^ RIHt ^ RI H!t! ^ RI"H#t#H$t$H%t%H&t&H't'H(t(H)t) ^ RI*H+t+H,t, ^ RI-H.t. ^ RI/H0t0H1t1 ^ RI2H3t3 ^ RI4H5t5H6t6H7t7H8t8 ^ RI9H:u H;t< ^ RI=H>t> ^ RI?H@t@ ^ RIAHBtBHCtC ^ RIDHEtEHFtFHGtGHHtH ^ RIIHJtJ ^ RIKHLtL ^ RIMHNtN ^ RIOHPtP ]'       d'   ^ RIHQtQHRtR ^ RISHTtTHUtUHVtVHWtWHXtXHYtYHZtZ ^ RI[H\t\ ^ RI]H^t^ ]_]R]3,          ,          t`R ]aR!&   ]! R"4      tb]! R#4      ]P                   ! R$ R%4      4       4       td]! R&4       ! R' R(]B]J,          4      4       te]! R&4       ! R) R*]B]>,          4      4       tfR+ R, ltgR# )-z
Define the SeriesGroupBy and DataFrameGroupBy
classes that hold the groupby interfaces (and some implementations).

These are user facing as the result of the ``df.groupby(...)`` operations,
which here returns a DataFrameGroupBy object.
)annotations)abc)CallableN)partial)dedent)TYPE_CHECKINGAnyLiteral	TypeAliasTypeVarcast)Interval)
duplicated)Pandas4WarningSpecificationError)
set_module)find_stack_level)ensure_int64is_boolis_dict_likeis_integer_dtypeis_list_likeis_numeric_dtype	is_scalar)CategoricalDtypeIntervalDtype)is_hashable)isnanotna)
algorithms)GroupByApplymaybe_mangle_lambdasreconstruct_funcvalidate_func_kwargs)	DataFrame)base)GroupByGroupByPlot)Index
MultiIndexall_indexes_samedefault_index)Series)get_group_index)maybe_use_numba)boxplot_frame_groupby)HashableSequence)	ArrayLikeBlockManagerCorrelationMethod
IndexLabelManagerSingleBlockManagerTakeIndexer)Categorical)NDFrame.r
   	AggScalarScalarResultpandasc                      ] tR t^mt$ RtR]R&   R]R&   RtR]R&   ]P                  ! ]	R7      t
R	]R
&   R R ltR R ltRtR# )NamedAgga  
Helper for column specific aggregation with control over output column names.

Parameters
----------
column : Hashable
    Column label in the DataFrame to apply aggfunc.
aggfunc : function or str
    Function to apply to the provided column. If string, the name of a built-in
    pandas function.
*args, **kwargs : Any
    Optional positional and keyword arguments passed to ``aggfunc``.

See Also
--------
DataFrame.groupby : Group DataFrame using a mapper or by a Series of columns.

Examples
--------
>>> df = pd.DataFrame({"key": [1, 1, 2], "a": [-1, 0, 1], 1: [10, 11, 12]})
>>> agg_a = pd.NamedAgg(column="a", aggfunc="min")
>>> agg_1 = pd.NamedAgg(column=1, aggfunc=lambda x: np.mean(x))
>>> df.groupby("key").agg(result_a=agg_a, result_1=agg_1)
    result_a  result_1
key
1          -1      10.5
2           1      12.0

>>> def n_between(ser, low, high, **kwargs):
...     return ser.between(low, high, **kwargs).sum()

>>> agg_between = pd.NamedAgg("a", n_between, 0, 1)
>>> df.groupby("key").agg(count_between=agg_between)
    count_between
key
1               1
2               1

>>> agg_between_kw = pd.NamedAgg("a", n_between, 0, 1, inclusive="both")
>>> df.groupby("key").agg(count_between_kw=agg_between_kw)
    count_between_kw
key
1                   1
2                   1
r0   columnr;   aggfuncztuple[Any, ...]args)default_factoryzdict[str, Any]kwargsc          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
   r@   r0   rA   zCallable[..., Any] | strrB   r   rD   returnNone )formats   "d/Users/mibo/.openclaw/workspace/.venv-ak/lib/python3.14/site-packages/pandas/core/groupby/generic.py__annotate__NamedAgg.__annotate__   s<     
 

 *
 	

 
 

    c                	6    Wn         W n        W0n        W@n        R # N)r@   rA   rB   rD   )selfr@   rA   rB   rD   s   &&&*,rK   __init__NamedAgg.__init__   s     	rN   c                    V ^8  d   QhRRRR/# )rF   keyintrG   r   rI   )rJ   s   "rK   rL   rM      s     
/ 
/s 
/s 
/rN   c                    V^ 8X  d   V P                   # V^8X  d   V P                  # V^8X  d   V P                  # V^8X  d   V P                  # \	        R4      h)z/Provide backward-compatible tuple-style access.zindex out of range)r@   rA   rB   rD   
IndexError)rQ   rU   s   &&rK   __getitem__NamedAgg.__getitem__   sR    !8;;AX<<AX99AX;;-..rN   )rA   rB   r@   rD   NrI   )__name__
__module____qualname____firstlineno____doc____annotations__rB   dataclassesfielddictrD   rR   rY   __static_attributes__rI   rN   rK   r?   r?   m   sD    ,\ D/(..tDFND

/ 
/rN   r?   zpandas.api.typingc                    a  ] tR t^tR R ltRRRR/R R lltR	 V 3R
 lltR@RRRR/R llt]tR t	R R lt
RAR R llt]! R4      tRRRR/R ltRBR R lltR R ltRCR R lltRCR R lltRDR V 3R llltRER R  lltR! R" ltRFR# R$ lltRFR% R& llt]R' R( l4       tRGR) R* lltRGR+ R, lltRCR- R. lltRCR/ R0 lltRHR1 R2 lltRIR3 R4 llt]R5 R6 l4       t ]R7 R8 l4       t!RJR9 R: llt"]R; R< l4       t#R= R> lt$R?t%V ;t&# )KSeriesGroupByc                    V ^8  d   QhRRRR/# )rF   mgrr6   rG   r,   rI   )rJ   s   "rK   rL   SeriesGroupBy.__annotate__   s      w 6 rN   c                	    V P                   P                  WP                  R 7      pV P                   P                  Vn        V# axes)obj_constructor_from_mgrrm   name_name)rQ   rh   outs   && rK   _wrap_agged_manager!SeriesGroupBy._wrap_agged_manager   s1    hh,,Sxx,@HHMM	
rN   numeric_onlyFrp   Nc               $    V ^8  d   QhRRRRRR/# )rF   ru   boolrp   
str | NonerG   r7   rI   )rJ   s   "rK   rL   ri      s$      #3=	rN   c          	     	    V P                   pVP                  pV'       dF   \        VP                  4      '       g+   R p\	        RV R\        V 4      P                   RV R24      hV# )ru   zCannot use z=True with .z and non-numeric dtypes.)_obj_with_exclusions_mgrr   dtype	TypeErrortyper[   )rQ   ru   rp   sersinglekwd_names   &$$   rK   _get_data_to_aggregate$SeriesGroupBy._get_data_to_aggregate   sk     '' 0 ; ;%HhZ{:&&'q.FH  rN   c                   V ^8  d   QhRR/# rF   rG   r,   rI   )rJ   s   "rK   rL   ri      s     g4 g4f g4rN   c                ,   < \         SV `  ! V.VO5/ VB # )a  
Apply function ``func`` group-wise and combine the results together.

The function passed to ``apply`` must take a series as its first
argument and return a DataFrame, Series or scalar. ``apply`` will
then take care of combining the results back together into a single
dataframe or series. ``apply`` is therefore a highly flexible
grouping method.

While ``apply`` is a very flexible method, its downside is that
using it can be quite a bit slower than using more specific methods
like ``agg`` or ``transform``. Pandas offers a wide range of method that will
be much faster than using ``apply`` for their specific purposes, so try to
use them before reaching for ``apply``.

Parameters
----------
func : callable
    A callable that takes a series as its first argument, and
    returns a dataframe, a series or a scalar. In addition the
    callable may take positional and keyword arguments.

*args : tuple
    Optional positional arguments to pass to ``func``.

**kwargs : dict
    Optional keyword arguments to pass to ``func``.

Returns
-------
Series or DataFrame
    A pandas object with the result of applying ``func`` to each group.

See Also
--------
pipe : Apply function to the full GroupBy object instead of to each
    group.
aggregate : Apply aggregate function to the GroupBy object.
transform : Apply function column-by-column to the GroupBy object.
Series.apply : Apply a function to a Series.
DataFrame.apply : Apply a function to each row or column of a DataFrame.

Notes
-----
The resulting dtype will reflect the return value of the passed ``func``,
see the examples below.

Functions that mutate the passed object can produce unexpected
behavior or errors and are not supported. See :ref:`gotchas.udf-mutation`
for more details.

Examples
--------
>>> s = pd.Series([0, 1, 2], index="a a b".split())
>>> g1 = s.groupby(s.index, group_keys=False)
>>> g2 = s.groupby(s.index, group_keys=True)

From ``s`` above we can see that ``g`` has two groups, ``a`` and ``b``.
Notice that ``g1`` have ``g2`` have two groups, ``a`` and ``b``, and only
differ in their ``group_keys`` argument. Calling `apply` in various ways,
we can get different grouping results:

Example 1: The function passed to `apply` takes a Series as
its argument and returns a Series.  `apply` combines the result for
each group together into a new Series.

The resulting dtype will reflect the return value of the passed ``func``.

>>> g1.apply(lambda x: x * 2 if x.name == "a" else x / 2)
a    0.0
a    2.0
b    1.0
dtype: float64

In the above, the groups are not part of the index. We can have them included
by using ``g2`` where ``group_keys=True``:

>>> g2.apply(lambda x: x * 2 if x.name == "a" else x / 2)
a  a    0.0
   a    2.0
b  b    1.0
dtype: float64

Example 2: The function passed to `apply` takes a Series as
its argument and returns a scalar. `apply` combines the result for
each group together into a Series, including setting the index as
appropriate:

>>> g1.apply(lambda x: x.max() - x.min())
a    1
b    0
dtype: int64

The ``group_keys`` argument has no effect here because the result is not
like-indexed (i.e. :ref:`a transform <groupby.transform>`) when compared
to the input.

>>> g2.apply(lambda x: x.max() - x.min())
a    1
b    0
dtype: int64
)superapply)rQ   funcrB   rD   	__class__s   &&*,rK   r   SeriesGroupBy.apply   s    N w}T3D3F33rN   engineengine_kwargsc          	     F   VRJ pRpV'       d   \        V4      w  rq/ p\        V\        4      '       d3   \        V4      '       d	   Ve   W%R&   Ve   W5R&   \	        W4      ! V/ VB # \        V\
        P                  4      '       db   \        V4      pW%R&   W5R&   V P                  ! V.VO5/ VB pV'       d   Vf   Q hWxn	        V P                  '       g   VP                  4       pV# \        V4      '       d   V P                  ! V.VO5RV/VB # V P                  ^ 8X  dm   V P                  p	V P                  V P                   P#                  . V P                   P$                  V P&                  P(                  V	P*                  R7      4      # V P,                  ! V.VO5/ VB # )aL  
Aggregate using one or more operations.

The ``aggregate`` method enables flexible and efficient aggregation of grouped
data using a variety of functions, including built-in, user-defined, and
optimized JIT-compiled functions.

Parameters
----------
func : function, str, list or None
    Function to use for aggregating the data. If a function, must either
    work when passed a Series or when passed to Series.apply.

    Accepted combinations are:

    - function
    - string function name
    - list of functions and/or function names, e.g. ``[np.sum, 'mean']``
    - None, in which case ``**kwargs`` are used with Named Aggregation. Here
      the output has one column for each element in ``**kwargs``. The name of
      the column is keyword, whereas the value determines the aggregation
      used to compute the values in the column.

      Can also accept a Numba JIT function with
      ``engine='numba'`` specified. Only passing a single function is supported
      with this engine.

      If the ``'numba'`` engine is chosen, the function must be
      a user defined function with ``values`` and ``index`` as the
      first and second arguments respectively in the function signature.
      Each group's index will be passed to the user defined function
      and optionally available for use.

*args
    Positional arguments to pass to func.
engine : str, default None
    * ``'cython'`` : Runs the function through C-extensions from cython.
    * ``'numba'`` : Runs the function through JIT compiled code from numba.
    * ``None`` : Defaults to ``'cython'`` or globally setting
        ``compute.use_numba``

engine_kwargs : dict, default None
    * For ``'cython'`` engine, there are no accepted ``engine_kwargs``
    * For ``'numba'`` engine, the engine can accept ``nopython``, ``nogil``
      and ``parallel`` dictionary keys. The values must either be ``True`` or
      ``False``. The default ``engine_kwargs`` for the ``'numba'`` engine is
      ``{'nopython': True, 'nogil': False, 'parallel': False}`` and will be
      applied to the function

**kwargs
    * If ``func`` is None, ``**kwargs`` are used to define the output names and
      aggregations via Named Aggregation. See ``func`` entry.
    * Otherwise, keyword arguments to be passed into func.

Returns
-------
Series
    Aggregated Series based on the grouping and the applied aggregation
    functions.

See Also
--------
SeriesGroupBy.apply : Apply function func group-wise
    and combine the results together.
SeriesGroupBy.transform : Transforms the Series on each group
    based on the given function.
Series.aggregate : Aggregate using one or more operations.

Notes
-----
When using ``engine='numba'``, there will be no "fall back" behavior internally.
The group data and group index will be passed as numpy arrays to the JITed
user defined function, and no alternative execution attempts will be tried.

Functions that mutate the passed object can produce unexpected
behavior or errors and are not supported. See :ref:`gotchas.udf-mutation`
for more details.

The resulting dtype will reflect the return value of the passed ``func``,
see the examples below.

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

>>> s
0    1
1    2
2    3
3    4
dtype: int64

>>> s.groupby([1, 1, 2, 2]).min()
1    1
2    3
dtype: int64

>>> s.groupby([1, 1, 2, 2]).agg("min")
1    1
2    3
dtype: int64

>>> s.groupby([1, 1, 2, 2]).agg(["min", "max"])
   min  max
1    1    2
2    3    4

The output column names can be controlled by passing
the desired column names and aggregations as keyword arguments.

>>> s.groupby([1, 1, 2, 2]).agg(
...     minimum="min",
...     maximum="max",
... )
   minimum  maximum
1        1        2
2        3        4

The resulting dtype will reflect the return value of the aggregating
function.

>>> s.groupby([1, 1, 2, 2]).agg(lambda x: x.astype(float).min())
1    1.0
2    3.0
dtype: float64
Nr   r   rp   indexr}   )r#   
isinstancestrr.   getattrr   Iterabler!   _aggregate_multiple_funcscolumnsas_indexreset_index_aggregate_with_numbangroupsr{   _wrap_aggregated_outputrn   _constructorrp   _grouperresult_indexr}   _python_agg_general)
rQ   r   r   r   rB   rD   
relabelingr   retrn   s
   &&$$*,    rK   	aggregateSeriesGroupBy.aggregate:  s   ~ T\
08MGFdC  v&&6+=
 $*x (*7'4&777cll++ (-D%8&3?#00GGGC***%===oo'J v&&11/<@F  ||q 
 //33HH))!XX]]"mm88!ii	 *   ++DB4B6BBrN   c                	   aaa VVV3R  lpV P                   pV P                  P                  WT4      pVP                  WeP                  R7      pV P                  V4      # )c                   < S! V .SO5/ SB # rP   rI   xrB   r   rD   s   &rK   <lambda>3SeriesGroupBy._python_agg_general.<locals>.<lambda>      d1.t.v.rN   )rp   )r{   r   
agg_seriesr   rp   r   )rQ   r   rB   rD   frn   resultress   &fjl    rK   r   !SeriesGroupBy._python_agg_general  sO    .''))#1vHH5++C00rN   c                   V ^8  d   QhRR/# rF   rG   r$   rI   )rJ   s   "rK   rL   ri     s       rN   c                	    \        V\        4      '       d   \        R 4      h\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   R V 4       pMR V 4       p\	        WARR7      p/ p\
        P                  ! V RR4      ;_uu_ 4        \        V4       F7  w  pw  rx\        P                  ! WvR7      p	V P                  ! V.VO5/ VB WY&   K9  	  R	R	R	4       \        ;QJ d*    R
 VP                  4        4       F  '       g   K   RM	  RM! R
 VP                  4        4       4      '       d;   ^ RIHp
 T
! VP                  4       ^V U	u. uF  qP                  NK  	  up	R7      pV# VP                  4        U	Uu/ uF  w  rV	P                   VbK  	  pp	pV P"                  P%                  VR	R7      p\'        R V 4       4      Vn        V#   + '       g   i     EL; iu up	i u upp	i )znested renamer is not supportedc              3  N   "   T F  p\        V\        \        34      x  K  	  R # 5irP   r   tuplelist.0r   s   & rK   	<genexpr>:SeriesGroupBy._aggregate_multiple_funcs.<locals>.<genexpr>  s     9Sz!eT]++Ss   #%TFc              3  d   "   T F&  p\        V\        \        34      '       g   W3MTx  K(  	  R # 5irP   r   r   s   & rK   r   r     s'     RcAt}!=!=A61Dcs   .0c              3  b   "   T F%  p\         P                  ! V4      ;'       g    Tx  K'  	  R # 5irP   )comget_callable_name)r   r   s   & rK   r   r     s&     Bcs,,Q/4414cs   !//)strictr   )labelpositionNc              3  B   "   T F  p\        V\        4      x  K  	  R # 5irP   )r   r$   r   s   & rK   r   r     s     B1AAz!Y''1As   concat)axiskeysr   c              3  8   "   T F  qP                   x  K  	  R # 5irP   )r   )r   rU   s   & rK   r   r     s     <GSyyG   )r   rc   r   anyzipr   temp_setattr	enumerater%   	OutputKeyr   valuesr=   r   r   itemsr   rn   _constructor_expanddimr(   r   )rQ   argrB   rD   r   resultsidxrp   r   rU   r   res_dfvalindexed_outputoutputs   &&*,           rK   r   'SeriesGroupBy._aggregate_multiple_funcs  s   c4  $%FGG39S93339S999RcRC CcBGg40C<>dJ55 &/s^!\dnn4>#~~dDTDVD &4 6 3B1AB333B1ABBB% qW/MWc		W/MF M<CMMOLO#,,+OL00t0L<G<<' 655 0N Ms   AG!G5G:!G2	c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
rF   datar,   r   z	list[Any]not_indexed_samerw   is_transformrG   DataFrame | SeriesrI   )rJ   s   "rK   rL   ri     sJ     FC FCFC FC 	FC
 FC 
FCrN   c                   \        V4      ^ 8X  d~   V'       d   VP                  pM+V P                  '       g   RpMV P                  P                  pV P
                  P                  . V P
                  P                  VVP                  R7      # Vf   Q h\        V^ ,          \        4      '       d`   V P                  P                  pV P
                  P                  W&R7      pVP                  4       pV P
                  P                  Vn        V# \        V^ ,          \        \        34      '       d   V P                  VVVR7      p	\        V	\        4      '       d   V P
                  P                  V	n        V P                   '       g3   V'       d+   V P#                  V	4      p	\%        \        V	4      4      V	n        V	P'                  V P
                  RR7      # V P
                  P                  W P                  P                  V P
                  P                  R7      p	V P                   '       g+   V P#                  V	4      p	\%        \        V	4      4      V	n        V	P'                  V P
                  RR7      # )a[  
Wrap the output of SeriesGroupBy.apply into the expected result.

Parameters
----------
data : Series
    Input data for groupby operation.
values : List[Any]
    Applied output for each group.
not_indexed_same : bool, default False
    Whether the applied outputs are not indexed the same as the group axes.

Returns
-------
DataFrame or Series
Nr   r   r   r   groupbymethod)r   r   rp   )lenr   
group_keysr   r   rn   r   rp   r}   r   rc   r   stackr,   r$   _concat_objectsr   _insert_inaxis_grouperr+   __finalize__)
rQ   r   r   r   r   	res_indexr   r   res_serr   s
   &&&&&     rK   _wrap_applied_output"SeriesGroupBy._wrap_applied_output  s   . v;! JJ	___ 	 MM66	88((XX]]jj	 )   !!!fQi&&MM..EXX44V4IF llnG88==GLNq	FI#677))!1) * F
 &&))"hhmm===%544V<,S[9&&txx	&BB XX**==#=#=DHHMM + F ===44V<,S[9&&txx	&BBrN   a  
    >>> ser = pd.Series([390.0, 350.0, 30.0, 20.0],
    ...                 index=["Falcon", "Falcon", "Parrot", "Parrot"],
    ...                 name="Max Speed")
    >>> grouped = ser.groupby([1, 1, 2, 2])
    >>> grouped.transform(lambda x: (x - x.mean()) / x.std())
        Falcon    0.707107
        Falcon   -0.707107
        Parrot    0.707107
        Parrot   -0.707107
        Name: Max Speed, dtype: float64

    Broadcast result of the transformation

    >>> grouped.transform(lambda x: x.max() - x.min())
    Falcon    40.0
    Falcon    40.0
    Parrot    10.0
    Parrot    10.0
    Name: Max Speed, dtype: float64

    >>> grouped.transform("mean")
    Falcon    370.0
    Falcon    370.0
    Parrot     25.0
    Parrot     25.0
    Name: Max Speed, dtype: float64

    The resulting dtype will reflect the return value of the passed ``func``,
    for example:

    >>> grouped.transform(lambda x: x.astype(int).max())
    Falcon    390
    Falcon    390
    Parrot     30
    Parrot     30
    Name: Max Speed, dtype: int64
    c               6    V P                   ! V.VO5RVRV/VB # )aL  
Call function producing a same-indexed Series on each group.

Returns a Series having the same indexes as the original object
filled with the transformed values.

Parameters
----------
func : function, str
    Function to apply to each group.
    See the Notes section below for requirements.

    Accepted inputs are:

    - String
    - Python function
    - Numba JIT function with ``engine='numba'`` specified.

    Only passing a single function is supported with this engine.
    If the ``'numba'`` engine is chosen, the function must be
    a user defined function with ``values`` and ``index`` as the
    first and second arguments respectively in the function signature.
    Each group's index will be passed to the user defined function
    and optionally available for use.

    If a string is chosen, then it needs to be the name
    of the groupby method you want to use.
*args
    Positional arguments to pass to func.
engine : str, default None
    * ``'cython'`` : Runs the function through C-extensions from cython.
    * ``'numba'`` : Runs the function through JIT compiled code from numba.
    * ``None`` : Defaults to ``'cython'``
      or the global setting ``compute.use_numba``

engine_kwargs : dict, default None
    * For ``'cython'`` engine, there are no accepted ``engine_kwargs``
    * For ``'numba'`` engine, the engine can accept ``nopython``, ``nogil``
      and ``parallel`` dictionary keys. The values must either be ``True`` or
      ``False``. The default ``engine_kwargs`` for the ``'numba'`` engine is
      ``{'nopython': True, 'nogil': False, 'parallel': False}`` and will be
      applied to the function

**kwargs
    Keyword arguments to be passed into func.

Returns
-------
Series
    Series with the same indexes as the original object filled
    with transformed values.

See Also
--------
Series.groupby.apply : Apply function ``func`` group-wise and combine
    the results together.
Series.groupby.aggregate : Aggregate using one or more operations.
Series.transform : Call ``func`` on self producing a Series with the
    same axis shape as self.

Notes
-----
Each group is endowed the attribute 'name' in case you need to know
which group you are working on.

The current implementation imposes three requirements on f:

* f must return a value that either has the same shape as the input
  subframe or can be broadcast to the shape of the input subframe.
  For example, if `f` returns a scalar it will be broadcast to have the
  same shape as the input subframe.
* if this is a DataFrame, f must support application column-by-column
  in the subframe. If f also supports application to the entire subframe,
  then a fast path is used starting from the second chunk.
* f must not mutate groups. Mutation is not supported and may
  produce unexpected results. See :ref:`gotchas.udf-mutation` for more details.

When using ``engine='numba'``, there will be no "fall back" behavior internally.
The group data and group index will be passed as numpy arrays to the JITed
user defined function, and no alternative execution attempts will be tried.

The resulting dtype will reflect the return value of the passed ``func``,
see the examples below.

.. versionchanged:: 2.0.0

    When using ``.transform`` on a grouped DataFrame and
    the transformation function returns a DataFrame,
    pandas now aligns the result's index with the input's index.
    You can call ``.to_numpy()`` on the result of
    the transformation function to avoid alignment.

Examples
--------

>>> ser = pd.Series(
...     [390.0, 350.0, 30.0, 20.0],
...     index=["Falcon", "Falcon", "Parrot", "Parrot"],
...     name="Max Speed",
... )
>>> grouped = ser.groupby([1, 1, 2, 2])
>>> grouped.transform(lambda x: (x - x.mean()) / x.std())
    Falcon    0.707107
    Falcon   -0.707107
    Parrot    0.707107
    Parrot   -0.707107
    Name: Max Speed, dtype: float64

Broadcast result of the transformation

>>> grouped.transform(lambda x: x.max() - x.min())
Falcon    40.0
Falcon    40.0
Parrot    10.0
Parrot    10.0
Name: Max Speed, dtype: float64

>>> grouped.transform("mean")
Falcon    370.0
Falcon    370.0
Parrot     25.0
Parrot     25.0
Name: Max Speed, dtype: float64

The resulting dtype will reflect the return value of the passed ``func``,
for example:

>>> grouped.transform(lambda x: x.astype(int).max())
Falcon    390
Falcon    390
Parrot     30
Parrot     30
Name: Max Speed, dtype: int64
r   r   
_transformrQ   r   r   r   rB   rD   s   &&$$*,rK   	transformSeriesGroupBy.transform  s9    N 

 &
6C
GM
 	
rN   c                    V ^8  d   QhRRRR/# )rF   howr   ru   rw   rI   )rJ   s   "rK   rL   ri     s     M MS M MrN   c                	0   V P                   p V P                  P                  ! R VP                  V^ 3/ VB pTP                  YPP                  P                  TP                  R7      #   \         d"   p\        T RTP                   R24      ThRp?ii ; i)r   z is not supported for z dtypeNr   rp   )r{   r   _cython_operation_valuesNotImplementedErrorr~   r}   r   rn   r   rp   )rQ   r   ru   rD   rn   r   errs   &&&,   rK   _cython_transformSeriesGroupBy._cython_transform  s    ''	V]]44S[[#q4:F hhnn388LL	 # 	Vse#9#))FKLRUU	Vs   *A) )B4BBc                    V ^8  d   QhRRRR/# )rF   r   r   rG   r,   rI   )rJ   s   "rK   rL   ri   #  s     ! !!	!rN   c                p   \        V4      '       d   V P                  ! V.VO5RV/VB # \        V4      '       g   Q h\        V P                  4      p. pV P
                  P                  V P                  4       FJ  w  r\        P                  V	RV4       V! V	.VO5/ VB p
VP                  V! WP                  R7      4       KL  	  V'       d#   ^ RIHp V! VRR7      pV P                  V4      pM*V P                  P                  \         P"                  R7      pV P                  P$                  Vn        V# )z#
Transform with a callable `func`.
r   rp   r   r   T)ignore_indexr}   )r.   _transform_with_numbacallabler   rn   r   get_iteratorr{   object__setattr__appendr   pandas.core.reshape.concatr   _set_result_index_orderedr   npfloat64rp   )rQ   r   r   r   rB   rD   klassr   rp   groupr   r   concatenatedr   s   &&&&*,        rK   _transform_general SeriesGroupBy._transform_general#  s    6""--+8<B  ~~~TXX==55%%
KD ufd3u.t.v.CNN5KK89
 9!'=L33LAFXX***<FhhmmrN   c                   V ^8  d   QhRR/# )rF   dropnarw   rI   )rJ   s   "rK   rL   ri   F  s     G G4 GrN   c                  aaaa \        S\        4      '       d
   VVV3R loMVVV3R loR V3R llp V P                  P                  V P                  4       UUu. uF&  w  rgV! V4      '       g   K  V P                  V4      NK(  	  pppT P                  Y4      p
T
# u uppi   \        \        3 d   p	\        R4      T	hRp	?	ii ; i)a  
Filter elements from groups that don't satisfy a criterion.

Elements from groups are filtered if they do not satisfy the
boolean criterion specified by func.

Parameters
----------
func : function
    Criterion to apply to each group. Should return True or False.
dropna : bool, optional
    Drop groups that do not pass the filter. True by default; if False,
    groups that evaluate False are filled with NaNs.
*args : tuple
    Optional positional arguments to pass to `func`.
**kwargs : dict
    Optional keyword arguments to pass to `func`.

Returns
-------
Series
    The filtered subset of the original Series.

See Also
--------
Series.filter: Filter elements of ungrouped Series.
DataFrameGroupBy.filter : Filter elements from groups base on criterion.

Notes
-----
Functions that mutate the passed object can produce unexpected
behavior or errors and are not supported. See :ref:`gotchas.udf-mutation`
for more details.

Examples
--------
>>> df = pd.DataFrame(
...     {
...         "A": ["foo", "bar", "foo", "bar", "foo", "bar"],
...         "B": [1, 2, 3, 4, 5, 6],
...         "C": [2.0, 5.0, 8.0, 1.0, 2.0, 9.0],
...     }
... )
>>> grouped = df.groupby("A")
>>> df.groupby("A").B.filter(lambda x: x.mean() > 3.0)
1    2
3    4
5    6
Name: B, dtype: int64
c                (   < \        V S4      ! S/ SB # rP   r   r   s   &rK   r   &SeriesGroupBy.filter.<locals>.<lambda>z  s    4 0$ A& ArN   c                   < S! V .SO5/ SB # rP   rI   r   s   &rK   r   r  |  s    Q 8 8 8rN   c                   V ^8  d   QhRR/# )rF   rG   rw   rI   )rJ   s   "rK   rL   *SeriesGroupBy.filter.<locals>.__annotate__  s     	" 	" 	"rN   c                >   < S! V 4      p\        V4      ;'       d    T# rP   )r   )r   bwrappers   & rK   true_and_notna,SeriesGroupBy.filter.<locals>.true_and_notna  s    
A8>>!rN   z'the filter must return a boolean resultN)	r   r   r   r  r{   
_get_index
ValueErrorr~   _apply_filter)rQ   r   r  rB   rD   r  rp   r  indicesr   filteredr  s   &f&jl      @rK   filterSeriesGroupBy.filterF  s    f dC  AG8G	" 	"	P $(==#=#=d>W>W#X#XKD!%( &%#X   %%g6
 I& 	PEFCO	Ps/   (B& B 5B 
B&  B& &C7CCc                    V ^8  d   QhRRRR/# )rF   r  rw   rG   Series | DataFramerI   )rJ   s   "rK   rL   ri     s     C Cd C.@ CrN   c                0   V P                   P                  pV P                   P                  pV P                  P                  p\
        P                  ! WARR7      w  rVV P                   P                  '       d   V^ 8  pW',          pWW,          p\        W%.V\        V4      3RVR7      pV'       d-   V^ 8  pV( P                  4       '       d   W',          pW,          p\        VR4      p\        P                  ! W'( ,          VR7      p	\        V	4      p	V P                   P                  p
V P                  P!                  WV P                  P"                  R7      pV P$                  '       g+   V P'                  V4      p\)        \        V4      4      Vn        V# )a  
Return number of unique elements in the group.

Parameters
----------
dropna : bool, default True
    Don't include NaN in the counts.

Returns
-------
Series
    Number of unique values within each group.

See Also
--------
core.resample.Resampler.nunique : Method nunique for Resampler.

Examples
--------
>>> lst = ["a", "a", "b", "b"]
>>> ser = pd.Series([1, 2, 3, 3], index=lst)
>>> ser
a    1
a    2
b    3
b    3
dtype: int64
>>> ser.groupby(level=0).nunique()
a    2
b    1
dtype: int64
F)use_na_sentinelsort)labelsshaper+  xnullfirst)	minlengthr   )r   idsr   rn   r   r   	factorizehas_dropped_nar-   r   r   r   r  bincountr   r   r   rp   r   r   r+   r   )rQ   r  r1  r   r   codesuniquesmaskgroup_indexr   rir   s   &&          rK   nuniqueSeriesGroupBy.nunique  sI   B mm--''hh#--cPUV=='''!8D)CKE%<CL)	
 !#D{{}}i)/+w/kk#e*83]]''%)XX%:%: &; &
 }}}008F(V5FLrN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   ri     s     l
 l
 l
rN   c                &   < \         SV `  WVR7      # )a|  
Generate descriptive statistics.

Descriptive statistics include those that summarize the central
tendency, dispersion and shape of a
dataset's distribution, excluding ``NaN`` values.

Analyzes both numeric and object series, as well
as ``DataFrame`` column sets of mixed data types. The output
will vary depending on what is provided. Refer to the notes
below for more detail.

Parameters
----------
percentiles : list-like of numbers, optional
    The percentiles to include in the output. All should
    fall between 0 and 1. The default, ``None``, will automatically
    return the 25th, 50th, and 75th percentiles.
include : 'all', list-like of dtypes or None (default), optional
    A white list of data types to include in the result. Ignored
    for ``Series``. Here are the options:

    - 'all' : All columns of the input will be included in the output.
    - A list-like of dtypes : Limits the results to the
      provided data types.
      To limit the result to numeric types submit
      ``numpy.number``. To limit it instead to object columns submit
      the ``numpy.object`` data type. Strings
      can also be used in the style of
      ``select_dtypes`` (e.g. ``df.describe(include=['O'])``). To
      select pandas categorical columns, use ``'category'``
    - None (default) : The result will include all numeric columns.
exclude : list-like of dtypes or None (default), optional,
    A black list of data types to omit from the result. Ignored
    for ``Series``. Here are the options:

    - A list-like of dtypes : Excludes the provided data types
      from the result. To exclude numeric types submit
      ``numpy.number``. To exclude object columns submit the data
      type ``numpy.object``. Strings can also be used in the style of
      ``select_dtypes`` (e.g. ``df.describe(exclude=['O'])``). To
      exclude pandas categorical columns, use ``'category'``
    - None (default) : The result will exclude nothing.

Returns
-------
Series or DataFrame
    Summary statistics of the Series or Dataframe provided.

See Also
--------
DataFrame.count: Count number of non-NA/null observations.
DataFrame.max: Maximum of the values in the object.
DataFrame.min: Minimum of the values in the object.
DataFrame.mean: Mean of the values.
DataFrame.std: Standard deviation of the observations.
DataFrame.select_dtypes: Subset of a DataFrame including/excluding
    columns based on their dtype.

Notes
-----
For numeric data, the result's index will include ``count``,
``mean``, ``std``, ``min``, ``max`` as well as lower, ``50`` and
upper percentiles. By default the lower percentile is ``25`` and the
upper percentile is ``75``. The ``50`` percentile is the
same as the median.

For object data (e.g. strings), the result's index
will include ``count``, ``unique``, ``top``, and ``freq``. The ``top``
is the most common value. The ``freq`` is the most common value's
frequency.

If multiple object values have the highest count, then the
``count`` and ``top`` results will be arbitrarily chosen from
among those with the highest count.

For mixed data types provided via a ``DataFrame``, the default is to
return only an analysis of numeric columns. If the DataFrame consists
only of object and categorical data without any numeric columns, the
default is to return an analysis of both the object and categorical
columns. If ``include='all'`` is provided as an option, the result
will include a union of attributes of each type.

The `include` and `exclude` parameters can be used to limit
which columns in a ``DataFrame`` are analyzed for the output.
The parameters are ignored when analyzing a ``Series``.

Examples
--------
Describing a numeric ``Series``.

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

>>> s
0    1
1    2
2    3
3    4
dtype: int64

>>> s.groupby([1, 1, 2, 2]).describe()
   count  mean       std  min   25%  50%   75%  max
1    2.0   1.5  0.707107  1.0  1.25  1.5  1.75  2.0
2    2.0   3.5  0.707107  3.0  3.25  3.5  3.75  4.0
)percentilesincludeexclude)r   describe)rQ   r>  r?  r@  r   s   &&&&rK   rA  SeriesGroupBy.describe  s"    T w#g   
 	
rN   c          
     ,    V ^8  d   QhRRRRRRRRRR/# )rF   	normalizerw   r+  	ascendingr  rG   r(  rI   )rJ   s   "rK   rL   ri   B  sC     x xx x 	x x 
xrN   c                  a*a+ V'       d   RMRpVf   V P                  WW5R7      pWgn        V# ^ RIHp ^ RIHp	 V P                  P                  p
V P                  P                  p. V P                  P                  OV P                  P                  Np\        VP                  \        4      '       g!   VeY   \        P                  ! V4      '       g=   V P!                  \"        P$                  VVVVR7      pWmn        WP&                  n
        V# V
R8g  pW,          W,          rVf    \(        P*                  ! VRR	7      w  ppR
 pMcV	! \#        VRR7      VRR7      p\-        RVP                  4      pVP.                  pVP1                  VP2                  RVP4                  R7      pR p\        VP                  \6        4      '       d?   \-        \8        V4      p\        P:                  ! VP<                  VP>                  V
34      pM\        P:                  ! W34      pV
V,          VV,          r^\        P@                  ! V
R,          V
RR 8g  4      ^ ,          ,           p\        PB                  ^ V3,          p\E        V
4      '       g   TpV! V\G        ^R4      4      V! V\G        RR4      4      8g  p\        PB                  RV3,          p\E        V4      '       g   TpRVV&   \        PH                  ! \        P@                  ! \        PB                  VR3,          4      ^ ,          4      p\K        \        PL                  \        PN                  PQ                  VV4      R7      p\        V P                  PR                  \T        4      '       d+   \W        V P                  PR                  P2                  4      pM]\(        P*                  ! V P                  PR                  V P                  PX                  V P                  PZ                  R7      ^ ,          .pV Uu. uF  pV! V4      NK  	  upV! VV4      .,           p. V P                  P\                  OVNpV'       dG   VR,          R8g  pVP_                  4       '       d   RpM!VV,          V Uu. uF  pVV,          NK  	  pppV'       d   VPa                  R4      p\        PH                  ! \        PB                  V\E        V
4      3,          4      pV'       d=   WR8H  ,          p \        PN                  Pc                  VV R4       V! V4      V,          p!MV! V4      p!VV!,          pV'       df   Vfb   V'       d   V
V,          V,          MV
V,          p"\        P:                  ! V'       d   TMV) V"34      pVV,          VR,          V,          upVR&   VEe   \        Pd                  ! \E        V4      RR7      o*VRR  F0  pS*\        PB                  RVR,          VRR 8g  3,          ,          o*K2  	  S*Pg                  4       \E        VR,          4      up#o+\        PL                  ! \        Ph                  ! V#4      S+4      \        Pj                  ! \        Ph                  ! S+4      V#4      .p$S*Pm                  4       ^,
          VR,          .p%V! V$V%RRR7      w  p&pVe#   \        Pn                  ! VR8g  VV,          ^ 4      pV'       dH   \        P:                  ! V'       d   TMV) V$^ ,          34      pVV,          V$R,          V,          upV$R&   R V*V+3R llp'VRR  U(u. uF  p(V'! V(4      NK  	  pp(VPq                  V$R,          4       \U        VVVRR7      p)\s        VP                  4      '       d   \u        V4      pV P                  Pw                  VV)VR7      pV Px                  '       g   VP{                  4       pV# u upi u upi u up(i )a  
Return a Series or DataFrame containing counts of unique rows.

Parameters
----------
normalize : bool, default False
    Return proportions rather than frequencies.
sort : bool, default True
    Sort by frequencies.
ascending : bool, default False
    Sort in ascending order.
bins : int or list of ints, optional
    Rather than count values, group them into half-open bins,
    a convenience for pd.cut, only works with numeric data.
dropna : bool, default True
    Don't include counts of rows that contain NA values.

Returns
-------
Series or DataFrame
    Series if the groupby ``as_index`` is True, otherwise DataFrame.

See Also
--------
Series.value_counts: Equivalent method on Series.
DataFrame.value_counts: Equivalent method on DataFrame.
DataFrameGroupBy.value_counts: Equivalent method on DataFrameGroupBy.

Notes
-----
- If the groupby ``as_index`` is True then the returned Series will have a
  MultiIndex with one level per input column.
- If the groupby ``as_index`` is False then the returned DataFrame will have an
  additional column with the value_counts. The column is labelled 'count' or
  'proportion', depending on the ``normalize`` parameter.

By default, rows that contain any NA values are omitted from
the result.

By default, the result will be in descending order so that the
first element of each group is the most frequently-occurring row.

Examples
--------
>>> s = pd.Series(
...     [1, 1, 2, 3, 2, 3, 3, 1, 1, 3, 3, 3],
...     index=["A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B"],
... )
>>> s
A    1
A    1
A    2
A    3
A    2
A    3
B    3
B    1
B    1
B    3
B    3
B    3
dtype: int64
>>> g1 = s.groupby(s.index)
>>> g1.value_counts(bins=2)
A  (0.997, 2.0]    4
   (2.0, 3.0]      2
B  (2.0, 3.0]      4
   (0.997, 2.0]    2
Name: count, dtype: int64
>>> g1.value_counts(normalize=True)
A  1    0.333333
   2    0.333333
   3    0.333333
B  3    0.666667
   1    0.333333
Name: proportion, dtype: float64

proportioncountN)rD  r+  rE  r  )get_join_indexers)cut)rD  r+  rE  binsT)r+  c                    W,          # rP   rI   labincs   &&rK   r   ,SeriesGroupBy.value_counts.<locals>.<lambda>  s    CHrN   F)copy)include_lowestr9   )
allow_fill
fill_valuec                H    W,          P                   P                  R,          # )   )_multiindexr5  rM  s   &&rK   r   rP    s    CH$8$8$>$>r$BrN   :rV  NN)repeats)r+  r*  floatrw   r  left)r+  r   c                    V ^8  d   QhRRRR/# )rF   	lev_codesz
np.ndarrayrG   rI   )rJ   s   "rK   rL   0SeriesGroupBy.value_counts.<locals>.__annotate__+  s     8 8z 8j 8rN   c                @   < \         P                  ! V S,          S4      # rP   )r  repeat)r]  diffnbins   &rK   build_codes/SeriesGroupBy.value_counts.<locals>.build_codes+  s    yy4$77rN   )levelsr5  namesverify_integrityr   rW  )>_value_countsrp   pandas.core.reshape.mergerI  pandas.core.reshape.tilerJ  r   r1  rn   r   rf  r   r}   r   r  iterabler   r,   value_countsr   r   r2  r   
categoriestaker5  	_na_valuer   r   lexsortr[  rightnonzeror_r   slicera  r   r`  addreduceatr   r)   r   _sortr  re  allastypeatzerossumarangetilecumsumwherer  r   r   r   r   r   ),rQ   rD  r+  rE  rK  r  rp   r   rI  rJ  r1  r   index_namesr   r7  rN  levllabcat_sercat_objlab_intervalsorter	idchangesr   lchangesrO  rr   repr5  level_codesre  dmacccatncatr[  rq  _rc  r]  mira  rb  s,   &&&&&&                                    @@rK   rl  SeriesGroupBy.value_countsB  sa   j  )|g<''#) ( F KM?0mmhh;++;TXX]];cii!122R[[%6%6
 **####  C H)IIOJ by9ciS <!++Cd;HC,D &514MG='//:G$$C((==  C
 CDcii//#.LZZ!2!2L4F4F LMFZZ
+Fv;FS 

3r7c#2h#67::	eeAyL!3xxC U1d^,S%b/0JJeeD(N#3xxCCggbjjsDy!12156 biic)BC dmm00*==3399:E $$MM..,,$(MM$8$8 	E 6;;Uk[!U;tC~>NN-4==''--9?Dxxzz Ye(Te{T):):eU(T**W%Cc3s8m,-Ar	N		!Q#!fTl!f3JCDL$*#c(4.CCZZ	tS ABF [%)F*;NCr 88CHF3D$SbzdKO{3B7G$GGHH  * S_JD$IIbiiot4bggbiiot6TUD[[]Q&b	2E
 '	FAs hhsby#c(A6ISC4a$IJ #FT"Xf-=T"X8 8 >C3BZHZ	[+ZEHLLb"kE
 CII&&s#C&&s"4&@}}}'')FO < )Uf Is   _&_+_0c                    V ^8  d   QhRRRR/# )rF   r#  r8   rG   r,   rI   )rJ   s   "rK   rL   ri   <  s"     P PP 
	PrN   c                .    V P                   ! RRV/VB pV# )a  
Return the elements in the given *positional* indices in each group.

This means that we are not indexing according to actual values in
the index attribute of the object. We are indexing according to the
actual position of the element in the object.

If a requested index does not exist for some group, this method will raise.
To get similar behavior that ignores indices that don't exist, see
:meth:`.SeriesGroupBy.nth`.

Parameters
----------
indices : array-like
    An array of ints indicating which positions to take in each group.

**kwargs
    For compatibility with :meth:`numpy.take`. Has no effect on the
    output.

Returns
-------
Series
    A Series containing the elements taken from each group.

See Also
--------
Series.take : Take elements from a Series along an axis.
Series.loc : Select a subset of a DataFrame by labels.
Series.iloc : Select a subset of a DataFrame by positions.
numpy.take : Take elements from an array along an axis.
SeriesGroupBy.nth : Similar to take, won't raise if indices don't exist.

Examples
--------
>>> df = pd.DataFrame(
...     [
...         ("falcon", "bird", 389.0),
...         ("parrot", "bird", 24.0),
...         ("lion", "mammal", 80.5),
...         ("monkey", "mammal", np.nan),
...         ("rabbit", "mammal", 15.0),
...     ],
...     columns=["name", "class", "max_speed"],
...     index=[4, 3, 2, 1, 0],
... )
>>> df
     name   class  max_speed
4  falcon    bird      389.0
3  parrot    bird       24.0
2    lion  mammal       80.5
1  monkey  mammal        NaN
0  rabbit  mammal       15.0
>>> gb = df["name"].groupby([1, 1, 2, 2, 2])

Take elements at rows 0 and 1 in each group.

>>> gb.take([0, 1])
1  4    falcon
   3    parrot
2  2      lion
   1    monkey
Name: name, dtype: str

We may take elements using negative integers for positive indices,
starting from the end of the object, just like with Python lists.

>>> gb.take([-1, -2])
1  3    parrot
   4    falcon
2  0    rabbit
   1    monkey
Name: name, dtype: str
r#  rn  _op_via_applyrQ   r#  rD   r   s   &&, rK   rn  SeriesGroupBy.take<  s"    ^ ##FGFvFrN   c               $    V ^8  d   QhRRRRRR/# rF   skipnarw   ru   rG   r,   rI   )rJ   s   "rK   rL   ri     s-     C
 C
C
 C

 
C
rN   c           	     2    V P                   ! RRRRVRV/VB # )a  
Return unbiased skew within groups.

Normalized by N-1.

Parameters
----------
skipna : bool, default True
    Exclude NA/null values when computing the result.

numeric_only : bool, default False
    Include only float, int, boolean columns. Not implemented for Series.

**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
Series
    Unbiased skew within groups.

See Also
--------
Series.skew : Return unbiased skew over requested axis.

Examples
--------
>>> ser = pd.Series(
...     [390.0, 350.0, 357.0, np.nan, 22.0, 20.0, 30.0],
...     index=[
...         "Falcon",
...         "Falcon",
...         "Falcon",
...         "Falcon",
...         "Parrot",
...         "Parrot",
...         "Parrot",
...     ],
...     name="Max Speed",
... )
>>> ser
Falcon    390.0
Falcon    350.0
Falcon    357.0
Falcon      NaN
Parrot     22.0
Parrot     20.0
Parrot     30.0
Name: Max Speed, dtype: float64
>>> ser.groupby(level=0).skew()
Falcon    1.525174
Parrot    1.457863
Name: Max Speed, dtype: float64
>>> ser.groupby(level=0).skew(skipna=False)
Falcon         NaN
Parrot    1.457863
Name: Max Speed, dtype: float64
altNr  ru   skew_cython_agg_generalrQ   r  ru   rD   s   &&&,rK   r  SeriesGroupBy.skew  s8    B '' 

%+
:F
JP
 	
rN   c               $    V ^8  d   QhRRRRRR/# r  rI   )rJ   s   "rK   rL   ri     s-     L
 L
L
 L

 
L
rN   c           	     8    R pV P                   ! RRVRVRV/VB # )a   
Return unbiased kurtosis within groups.

Parameters
----------
skipna : bool, default True
    Exclude NA/null values when computing the result.

numeric_only : bool, default False
    Include only float, int, boolean columns. Not implemented for Series.

**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
Series
    Unbiased kurtosis within groups.

See Also
--------
Series.kurt : Return unbiased kurtosis over requested axis.

Examples
--------
>>> ser = pd.Series(
...     [390.0, 350.0, 357.0, 333.0, np.nan, 22.0, 20.0, 30.0, 40.0, 41.0],
...     index=[
...         "Falcon",
...         "Falcon",
...         "Falcon",
...         "Falcon",
...         "Falcon",
...         "Parrot",
...         "Parrot",
...         "Parrot",
...         "Parrot",
...         "Parrot",
...     ],
...     name="Max Speed",
... )
>>> ser
Falcon    390.0
Falcon    350.0
Falcon    357.0
Falcon    333.0
Falcon      NaN
Parrot     22.0
Parrot     20.0
Parrot     30.0
Parrot     40.0
Parrot     41.0
Name: Max Speed, dtype: float64
>>> ser.groupby(level=0).kurt()
Falcon    1.622109
Parrot   -2.878714
Name: Max Speed, dtype: float64
>>> ser.groupby(level=0).kurt(skipna=False)
Falcon         NaN
Parrot   -2.878714
Name: Max Speed, dtype: float64
c                2    \        R V P                   24      h)z"'kurt' is not supported for dtype=r~   r}   rn   s   &rK   r  SeriesGroupBy.kurt.<locals>.alt       @LMMrN   r  r  ru   kurtr  rQ   r  ru   rD   r  s   &&&, rK   r  SeriesGroupBy.kurt  s>    J	N
 '' 

$*
9E
IO
 	
rN   c                   V ^8  d   QhRR/# rF   rG   r'   rI   )rJ   s   "rK   rL   ri   "  s      k rN   c                    \        V 4      pV# )a  
Make plots of groups from a Series.

Uses the backend specified by the option ``plotting.backend``.
By default, matplotlib is used.

Returns
-------
GroupByPlot
    A plotting object that can be used to create plots for each group.

See Also
--------
Series.plot : Make plots of Series.

Examples
--------
>>> ser = pd.Series([1, 2, 3, 4, 5], index=["a", "a", "b", "b", "c"])
>>> g = ser.groupby(level=0)
>>> g.plot()  # doctest: +SKIP
r'   rQ   r   s   & rK   plotSeriesGroupBy.plot!  s    . T"rN   c               $    V ^8  d   QhRRRRRR/# rF   nrV   keepzLiteral['first', 'last', 'all']rG   r,   rI   )rJ   s   "rK   rL   ri   ;  $     > >> ?>	>rN   c                z    \        \        P                  WR7      pV P                  pV P	                  W4RR7      pV# )aa  
Return the largest `n` elements.

Parameters
----------
n : int, default 5
    Return this many descending sorted values.
keep : {'first', 'last', 'all'}, default 'first'
    When there are duplicate values that cannot all fit in a
    Series of `n` elements:

    - ``first`` : return the first `n` occurrences in order
      of appearance.
    - ``last`` : return the last `n` occurrences in reverse
      order of appearance.
    - ``all`` : keep all occurrences. This can result in a Series of
      size larger than `n`.

Returns
-------
Series
    The `n` largest values in the Series, sorted in decreasing order.

See Also
--------
Series.nsmallest: Get the `n` smallest elements.
Series.sort_values: Sort Series by values.
Series.head: Return the first `n` rows.

Notes
-----
Faster than ``.sort_values(ascending=False).head(n)`` for small `n`
relative to the size of the ``Series`` object.

Examples
--------
>>> s = pd.Series([1, 2, 3, 4, 5, 6])

>>> s
0    1
1    2
2    3
3    4
4    5
5    6
dtype: int64

>>> s.groupby([1, 1, 1, 2, 2, 2]).nlargest(n=2)
1  2    3
   1    2
2  5    6
   4    5
dtype: int64
r  r  Tr   )r   r,   nlargestr{   _python_apply_generalrQ   r  r  r   r   r   s   &&&   rK   r  SeriesGroupBy.nlargest;  s<    r FOOq4(( ++Ad+KrN   c               $    V ^8  d   QhRRRRRR/# r  rI   )rJ   s   "rK   rL   ri   {  r  rN   c                z    \        \        P                  WR7      pV P                  pV P	                  W4RR7      pV# )aR  
Return the smallest `n` elements.

Parameters
----------
n : int, default 5
    Return this many ascending sorted values.
keep : {'first', 'last', 'all'}, default 'first'
    When there are duplicate values that cannot all fit in a
    Series of `n` elements:

    - ``first`` : return the first `n` occurrences in order
      of appearance.
    - ``last`` : return the last `n` occurrences in reverse
      order of appearance.
    - ``all`` : keep all occurrences. This can result in a Series of
      size larger than `n`.

Returns
-------
Series
    The `n` smallest values in the Series, sorted in increasing order.

See Also
--------
Series.nlargest: Get the `n` largest elements.
Series.sort_values: Sort Series by values.
Series.head: Return the first `n` rows.

Notes
-----
Faster than ``.sort_values().head(n)`` for small `n` relative to
the size of the ``Series`` object.

Examples
--------
>>> s = pd.Series([1, 2, 3, 4, 5, 6])

>>> s
0    1
1    2
2    3
3    4
4    5
5    6
dtype: int64

>>> s.groupby([1, 1, 1, 2, 2, 2]).nsmallest(n=2)
1  0    1
   1    2
2  3    4
   4    5
dtype: int64
r  Tr  )r   r,   	nsmallestr{   r  r  s   &&&   rK   r  SeriesGroupBy.nsmallest{  s>    r F$$5(( ++Ad+KrN   c                    V ^8  d   QhRRRR/# rF   r  rw   rG   r,   rI   )rJ   s   "rK   rL   ri          ;< ;<T ;<V ;<rN   c                (    V P                  RVR7      # )aI  
Return the row label of the minimum value.

If multiple values equal the minimum, the first row label with that
value is returned.

Parameters
----------
skipna : bool, default True
    Exclude NA values.

Returns
-------
Series
    Indexes of minima in each group.

Raises
------
ValueError
    When there are no valid values for a group. Then can happen if:

        * There is an unobserved group and ``observed=False``.
        * All values for a group are NA.
        * Some values for a group are NA and ``skipna=False``.

.. versionchanged:: 3.0.0
    Previously if all values for a group are NA or some values for a group are
    NA and ``skipna=False``, this method would return NA. Now it raises instead.

See Also
--------
numpy.argmin : Return indices of the minimum values
    along the given axis.
DataFrame.idxmin : Return index of first occurrence of minimum
    over requested axis.
Series.idxmax : Return index *label* of the first occurrence
    of maximum of values.

Examples
--------
>>> ser = pd.Series(
...     [1, 2, 3, 4],
...     index=pd.DatetimeIndex(
...         ["2023-01-01", "2023-01-15", "2023-02-01", "2023-02-15"]
...     ),
... )
>>> ser
2023-01-01    1
2023-01-15    2
2023-02-01    3
2023-02-15    4
dtype: int64

>>> ser.groupby(["a", "a", "b", "b"]).idxmin()
a   2023-01-01
b   2023-02-01
dtype: datetime64[us]
idxminr  _idxmax_idxminrQ   r  s   &&rK   r  SeriesGroupBy.idxmin      v ""8F";;rN   c                    V ^8  d   QhRRRR/# r  rI   )rJ   s   "rK   rL   ri     r  rN   c                (    V P                  RVR7      # )aI  
Return the row label of the maximum value.

If multiple values equal the maximum, the first row label with that
value is returned.

Parameters
----------
skipna : bool, default True
    Exclude NA values.

Returns
-------
Series
    Indexes of maxima in each group.

Raises
------
ValueError
    When there are no valid values for a group. Then can happen if:

        * There is an unobserved group and ``observed=False``.
        * All values for a group are NA.
        * Some values for a group are NA and ``skipna=False``.

.. versionchanged:: 3.0.0
    Previously if all values for a group are NA or some values for a group are
    NA and ``skipna=False``, this method would return NA. Now it raises instead.

See Also
--------
numpy.argmax : Return indices of the maximum values
    along the given axis.
DataFrame.idxmax : Return index of first occurrence of maximum
    over requested axis.
Series.idxmin : Return index *label* of the first occurrence
    of minimum of values.

Examples
--------
>>> ser = pd.Series(
...     [1, 2, 3, 4],
...     index=pd.DatetimeIndex(
...         ["2023-01-01", "2023-01-15", "2023-02-01", "2023-02-15"]
...     ),
... )
>>> ser
2023-01-01    1
2023-01-15    2
2023-02-01    3
2023-02-15    4
dtype: int64

>>> ser.groupby(["a", "a", "b", "b"]).idxmax()
a   2023-01-15
b   2023-02-15
dtype: datetime64[us]
idxmaxr  r  r  s   &&rK   r  SeriesGroupBy.idxmax  r  rN   c               (    V ^8  d   QhRRRRRRRR/# )rF   otherr,   r   r4   min_periods
int | NonerG   rI   )rJ   s   "rK   rL   ri   5  s2     % %% "%  	%
 
%rN   c                .    V P                  RWVR7      pV# )ai  
Compute correlation between each group and another Series.

Parameters
----------
other : Series
    Series to compute correlation with.
method : {'pearson', 'kendall', 'spearman'}, default 'pearson'
    Method of correlation to use.
min_periods : int, optional
    Minimum number of observations required per pair of columns to
    have a valid result.

Returns
-------
Series
    Correlation value for each group.

See Also
--------
Series.corr : Equivalent method on ``Series``.

Examples
--------
>>> s = pd.Series([1, 2, 3, 4], index=[0, 0, 1, 1])
>>> g = s.groupby([0, 0, 1, 1])
>>> g.corr()  # doctest: +SKIP
corr)r  r   r  r  )rQ   r  r   r  r   s   &&&& rK   r  SeriesGroupBy.corr5  s(    D ##%K $ 
 rN   c               (    V ^8  d   QhRRRRRRRR/# )rF   r  r,   r  r  ddofrG   rI   )rJ   s   "rK   rL   ri   \  s,     " ""*4"CM"	"rN   c                .    V P                  RWVR7      pV# )aO  
Compute covariance between each group and another Series.

Parameters
----------
other : Series
    Series to compute covariance with.
min_periods : int, optional
    Minimum number of observations required per pair of columns to
    have a valid result.
ddof : int, optional
    Delta degrees of freedom for variance calculation.

Returns
-------
Series
    Covariance value for each group.

See Also
--------
Series.cov : Equivalent method on ``Series``.

Examples
--------
>>> s = pd.Series([1, 2, 3, 4], index=[0, 0, 1, 1])
>>> g = s.groupby([0, 0, 1, 1])
>>> g.cov()  # doctest: +SKIP
cov)r  r  r  r  )rQ   r  r  r  r   s   &&&& rK   r  SeriesGroupBy.cov\  s'    > ##d $ 
 rN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   ri          C C CrN   c                &    V P                  R 4      # )a  
Return whether each group's values are monotonically increasing.

Returns
-------
Series

See Also
--------
SeriesGroupBy.is_monotonic_decreasing : Return whether each group's values
    are monotonically decreasing.

Examples
--------
>>> s = pd.Series([2, 1, 3, 4], index=["Falcon", "Falcon", "Parrot", "Parrot"])
>>> s.groupby(level=0).is_monotonic_increasing
Falcon    False
Parrot     True
dtype: bool
c                    V P                   # rP   )is_monotonic_increasingr   s   &rK   r   7SeriesGroupBy.is_monotonic_increasing.<locals>.<lambda>  
    c&A&ArN   r   rQ   s   &rK   r  %SeriesGroupBy.is_monotonic_increasing      , zzABBrN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   ri     r  rN   c                &    V P                  R 4      # )a  
Return whether each group's values are monotonically decreasing.

Returns
-------
Series

See Also
--------
SeriesGroupBy.is_monotonic_increasing : Return whether each group's values
    are monotonically increasing.

Examples
--------
>>> s = pd.Series([2, 1, 3, 4], index=["Falcon", "Falcon", "Parrot", "Parrot"])
>>> s.groupby(level=0).is_monotonic_decreasing
Falcon     True
Parrot    False
dtype: bool
c                    V P                   # rP   )is_monotonic_decreasingr  s   &rK   r   7SeriesGroupBy.is_monotonic_decreasing.<locals>.<lambda>  r  rN   r  r  s   &rK   r  %SeriesGroupBy.is_monotonic_decreasing  r  rN   c               <    V ^8  d   QhRRRRRRRRRRR	R
RRRRRR/	# )rF   gridrw   
xlabelsizer  xrotfloat | None
ylabelsizeyrotfigsizetuple[float, float] | NonerK  int | Sequence[int]backendrx   legendrI   )rJ   s   "rK   rL   ri     sq     L L 	L
 L L L L ,L "L L LrN   c                V    V P                   ! RRVRVRVRVRVRVRVRVR	V	R
V
RV/VB pV# )a  
Draw histogram for each group's values using :meth:`Series.hist` API.

Parameters
----------
by : object, optional
    Grouping key.
ax : matplotlib.axes.Axes, optional
    Axis to draw the histogram on.
grid : bool, default True
    Show axis grid lines.
xlabelsize : int, default None
    X axis label size.
xrot : float, default None
    Rotation for x ticks.
ylabelsize : int, default None
    Y axis label size.
yrot : float, default None
    Rotation for y ticks.
figsize : tuple, optional
    Figure size in inches.
bins : int or sequence, default 10
    Number of histogram bins or bin edges.
backend : str or callable or None, optional
    Plotting backend to use (e.g. 'matplotlib'). If None, use the default
    plotting backend.
legend : bool, default False
    Whether to draw the legend.
**kwargs
    Additional keyword arguments passed to :meth:`Series.hist`.

Returns
-------
matplotlib.axes.Axes or ndarray of Axes
    The returned matplotlib axes or array of axes depending on input.

See Also
--------
Series.hist : Equivalent histogram plotting method on Series.

Examples
--------
>>> df = pd.DataFrame({"val": [1, 2, 2, 3, 3, 3]}, index=[0, 0, 1, 1, 2, 2])
>>> g = df["val"].groupby([0, 0, 1, 1, 2, 2])
>>> g.hist()  # doctest: +SKIP
byaxr  r  r  r  r  r  rK  r  r   histr  )rQ   r  r  r  r  r  r  r  r  rK  r  r   rD   r   s   &&&&&&&&&&&&, rK   r  SeriesGroupBy.hist  s    z ## 

 
 	

 "
 
 "
 
 
 
 
 
 
 rN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   ri     s     1 1v 1rN   c                &    V P                  R 4      # )z
Return the dtype object of the underlying data for each group.

Mirrors :meth:`Series.dtype` applied group-wise.

Returns
-------
Series
    Dtype of each group's values.
c                    V P                   # rP   r  r  s   &rK   r   %SeriesGroupBy.dtype.<locals>.<lambda>
  s    ciirN   r  r  s   &rK   r}   SeriesGroupBy.dtype  s     zz/00rN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   ri     s     - - -rN   c                (    V P                  R4      pV# )a4  
Return unique values for each group.

It returns unique values for each of the grouped values. Returned in
order of appearance. Hash table-based unique, therefore does NOT sort.

Returns
-------
Series
    Unique values for each of the grouped values.

See Also
--------
Series.unique : Return unique values of Series object.

Examples
--------
>>> df = pd.DataFrame(
...     [
...         ("Chihuahua", "dog", 6.1),
...         ("Beagle", "dog", 15.2),
...         ("Chihuahua", "dog", 6.9),
...         ("Persian", "cat", 9.2),
...         ("Chihuahua", "dog", 7),
...         ("Persian", "cat", 8.8),
...     ],
...     columns=["breed", "animal", "height_in"],
... )
>>> df
       breed     animal   height_in
0  Chihuahua        dog         6.1
1     Beagle        dog        15.2
2  Chihuahua        dog         6.9
3    Persian        cat         9.2
4  Chihuahua        dog         7.0
5    Persian        cat         8.8
>>> ser = df.groupby("animal")["breed"].unique()
>>> ser
animal
cat              [Persian]
dog    [Chihuahua, Beagle]
Name: breed, dtype: object
uniquer  r  s   & rK   r  SeriesGroupBy.unique  s    X ##H-rN   rI   rP   FFFT)NNN)FTFNTTF)   r/  )pearsonN)NrV  )NNTNNNNN
   NF)'r[   r\   r]   r^   rs   r   r   r   aggr   r   r   r   #_SeriesGroupBy__examples_series_docr   r   r  r%  r:  rA  rl  rn  r  r  propertyr  r  r  r  r  r  r  r  r  r  r}   r  rd   __classcell__r   s   @rK   rf   rf      sT   
&+@Dg4 g4RsC sCT sCj C1BFCP #%	'RI
D I
 I
VM!FGRCJl
 l
\xtPdC
JL
\  2>@>@;<z;<z%N"H C C. C C.L\ 1 1- -rN   rf   c                    a  ] tR tRtR=RRRR/R llt]tR tR R ltR>R
 R lltR R lt	R?R R llt
R t]! R4      tRRRR/R ltR tR R ltR@R R lltR V 3R lltR=R R lltRR	RR/R R lltR  R! ltR" R# ltR@R$ R% lltRAR& R' lltRAR( R) llt]tRBR* R+ lltR, R- ltRAR. R/ lltRAR0 R1 llt] R2 R3 l4       t!RCR4 R5 llt"RDR6 R7 llt#RER8 R9 llt$RFR: R; llt%R<t&V ;t'# )GDataFrameGroupByi<  Nr   r   c                  \        V3/ VB w  rarx\        V4      p\        V4      '       d	   W%R&   W5R&   \        WWER7      p	V	P	                  4       p
\        V4      '       g:   V
e6   V P                  '       g"   \        V4      '       d   V
P                  4       # V
# V'       d<   \        \        V
4      p
V
P                  RV3,          p
\        \        V
4      p
Wzn        V
f   RV9   d   VR VR \        V4      '       d   V P                  ! V.VO5RV/VB # V P                  P                  ^8  d   V P                   ! V.VO5/ VB # V'       g	   V'       d   V P"                  ! V.VO5/ VB p
MY\        W.R/ R7      p VP	                  4       p
\        \        V
4      p
V P$                  P                  P'                  4       V
n        V P                  '       g+   V P-                  V
4      p
\/        \1        V
4      4      V
n        V
#   \(         d-   pR\+        T4      9  d   h T P#                  T4      p
 Rp?LpRp?ii ; i)a  
Aggregate using one or more operations.

The ``aggregate`` function allows the application of one or more aggregation
operations on groups of data within a DataFrameGroupBy object. It supports
various aggregation methods, including user-defined functions and predefined
functions such as 'sum', 'mean', etc.

Parameters
----------
func : function, str, list, dict or None
    Function to use for aggregating the data. If a function, must either
    work when passed a DataFrame or when passed to DataFrame.apply.

    Accepted combinations are:

    - function
    - string function name
    - list of functions and/or function names, e.g. ``[np.sum, 'mean']``
    - dict of index labels -> functions, function names or list of such.
    - None, in which case ``**kwargs`` are used with Named Aggregation. Here the
      output has one column for each element in ``**kwargs``. The name of the
      column is keyword, whereas the value determines the aggregation used to
      compute the values in the column.

      Can also accept a Numba JIT function with
      ``engine='numba'`` specified. Only passing a single function is supported
      with this engine.

      If the ``'numba'`` engine is chosen, the function must be
      a user defined function with ``values`` and ``index`` as the
      first and second arguments respectively in the function signature.
      Each group's index will be passed to the user defined function
      and optionally available for use.

*args
    Positional arguments to pass to func.
engine : str, default None
    * ``'cython'`` : Runs the function through C-extensions from cython.
    * ``'numba'`` : Runs the function through JIT compiled code from numba.
    * ``None`` : Defaults to ``'cython'`` or globally setting
        ``compute.use_numba``

engine_kwargs : dict, default None
    * For ``'cython'`` engine, there are no accepted ``engine_kwargs``
    * For ``'numba'`` engine, the engine can accept ``nopython``, ``nogil``
      and ``parallel`` dictionary keys. The values must either be ``True`` or
      ``False``. The default ``engine_kwargs`` for the ``'numba'`` engine is
      ``{'nopython': True, 'nogil': False, 'parallel': False}`` and will be
      applied to the function

**kwargs
    * If ``func`` is None, ``**kwargs`` are used to define the output names and
      aggregations via Named Aggregation. See ``func`` entry.
    * Otherwise, keyword arguments to be passed into func.

Returns
-------
DataFrame
    Aggregated DataFrame based on the grouping and the applied aggregation
    functions.

See Also
--------
DataFrame.groupby.apply : Apply function func group-wise
    and combine the results together.
DataFrame.groupby.transform : Transforms the Series on each group
    based on the given function.
DataFrame.aggregate : Aggregate using one or more operations.

Notes
-----
When using ``engine='numba'``, there will be no "fall back" behavior internally.
The group data and group index will be passed as numpy arrays to the JITed
user defined function, and no alternative execution attempts will be tried.

Functions that mutate the passed object can produce unexpected
behavior or errors and are not supported. See :ref:`gotchas.udf-mutation`
for more details.

The resulting dtype will reflect the return value of the passed ``func``,
see the examples below.

Examples
--------
>>> data = {
...     "A": [1, 1, 2, 2],
...     "B": [1, 2, 3, 4],
...     "C": [0.362838, 0.227877, 1.267767, -0.562860],
... }
>>> df = pd.DataFrame(data)
>>> df
   A  B         C
0  1  1  0.362838
1  1  2  0.227877
2  2  3  1.267767
3  2  4 -0.562860

The aggregation is for each column.

>>> df.groupby("A").agg("min")
   B         C
A
1  1  0.227877
2  3 -0.562860

Multiple aggregations

>>> df.groupby("A").agg(["min", "max"])
    B             C
  min max       min       max
A
1   1   2  0.227877  0.362838
2   3   4 -0.562860  1.267767

Select a column for aggregation

>>> df.groupby("A").B.agg(["min", "max"])
   min  max
A
1    1    2
2    3    4

User-defined function for aggregation

>>> df.groupby("A").agg(lambda x: sum(x) + 2)
    B          C
A
1       5       2.590715
2       9       2.704907

Different aggregations per column

>>> df.groupby("A").agg({"B": ["min", "max"], "C": "sum"})
    B             C
  min max       sum
A
1   1   2  0.590715
2   3   4  0.704907

To control the output names with different aggregations per column,
pandas supports "named aggregation"

>>> df.groupby("A").agg(
...     b_min=pd.NamedAgg(column="B", aggfunc="min"),
...     c_sum=pd.NamedAgg(column="C", aggfunc="sum"),
... )
   b_min     c_sum
A
1      1  0.590715
2      3  0.704907

- The keywords are the *output* column names
- The values are tuples whose first element is the column to select
  and the second element is the aggregation to apply to that column.
  Pandas provides the ``pandas.NamedAgg`` namedtuple with the fields
  ``['column', 'aggfunc']`` to make it clearer what the arguments are.
  As usual, the aggregation can be a callable or a string alias.

See :ref:`groupby.aggregate.named` for more.

The resulting dtype will reflect the return value of the aggregating
function.

>>> df.groupby("A")[["B"]].agg(lambda x: x.astype(float).min())
      B
A
1   1.0
2   3.0
r   r   )rB   rD   NNNNzNo objects to concatenaterI   )r"   r!   r.   r    r  r   r   r   r   r   r$   ilocr   r   r   nkeysr   _aggregate_framer{   rQ  r!  r   r   r+   r   r   )rQ   r   r   r   rB   rD   r   r   orderopr   gbar   s   &&$$*,       rK   r   DataFrameGroupBy.aggregate>  s   V ,<D+KF+K(
'#D)6""  &8&3?#$4?D!!f&8===\$%7%7))++ )V,F[[E*F)V,F
 %N> 6!8$?+ v&&11/<@F  }}""Q&//FtFvFF ..tEdEfE #4bDN WWYF  ")V4F%)%>%>%F%F%K%K%MFN}}}008F(V5FL+ " 	92#c(B "2248F	9s    H H>"H99H>c                	  aaa VVV3R  lpV P                   ^ 8X  d   V P                  W@P                  RR7      # V P                  p\	        VP
                  4      '       g   V P                  W@P                  4      # / p\        VP                  4       4       F'  w  pw  rV P                  P                  W4      p
WV&   K)  	  V P                  P                  V4      pVP
                  P                  RR7      Vn        V P                  V4      # )c                   < S! V .SO5/ SB # rP   rI   r   s   &rK   r   6DataFrameGroupBy._python_agg_general.<locals>.<lambda>;	  r   rN   T)is_aggF)deep)r   r  _selected_objr{   r   r   r   r   r   r   rn   r   rQ  r   )rQ   r   rB   rD   r   rn   r   r   rp   r   r   r   s   &fjl        rK   r   $DataFrameGroupBy._python_agg_general:	  s    .<<1 --a1C1CD-QQ''3;;--a1C1CDD') )#))+ 6C$]]--c5F 3K !7 hh##F+kk&&E&2++C00rN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   DataFrameGroupBy.__annotate__Q	  s       rN   c                	h   V P                   P                  ^8w  d   \        R4      hV P                  p/ pV P                   P	                  V4       F  w  rgV! V.VO5/ VB pWV&   K  	  V P                   P
                  p	V P                  P                  WTP                  V	R7      p
V
P                  p
V
# )rV  zNumber of keys must be 1r   r   )
r   r!  AssertionErrorr{   r  r   rn   r   r   T)rQ   r   rB   rD   rn   r   rp   grp_dffresr   rr   s   &&*,       rK   r"  !DataFrameGroupBy._aggregate_frameQ	  s    ==!# !;<<''79 MM66s;LD000D4L < }}11hh##F++|#Tee
rN   Fc               (    V ^8  d   QhRRRRRRRR/# )rF   r   r$   r   r   r   rw   r   rI   )rJ   s   "rK   rL   r/  b	  s8     I II I 	I
 IrN   c                	   \        V4      ^ 8X  d   V'       d   VP                  pM+V P                  '       g   RpMV P                  P                  pV P
                  P                  WQP                  R7      pVP                  VP                  4      pV# \        \        P                  ! V!  R4      pVfD   V P
                  P                  VP                  R7      pVP                  VP                  4      pV# \        V\        4      '       d   V P                  VVVR7      # V P                   '       d   V P                  P                  MRp\        V\"        P$                  \&        34      '       d[   \)        V P*                  4      '       g   \-        V P*                  4      p	MV P*                  p	V P
                  P/                  W(V	R7      # \        V\0        4      '       gi   V P                   '       d   V P
                  P/                  W(R7      # V P
                  P                  W P*                  .R7      pV P3                  V4      pV# V P5                  VVVVV4      # )    Nr1  )r   r   r   r   )r   r   r   r   r   rn   r   r   ry  dtypesnextr   not_noner   r$   r   r   r  ndarrayr(   r   
_selectionr   _constructor_slicedr,   r   _wrap_applied_output_series)
rQ   r   r   r   r   r   r   first_not_none	key_indexrp   s
   &&&&&     rK   r   %DataFrameGroupBy._wrap_applied_outputb	  s    v;! JJ	___ 	 MM66	XX**LL*QF]]4;;/FM cllF3T:! XX**4<<*@F]]4;;/FM	22''!1) (   37---DMM..T	nrzz5&9:: t//T__-
 88//d/SSNF33
 }}}xx33F3LL..v?P.Q44V< 33  rN   c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
rF   r   zlist[Series]r   rw   rB  zIndex | Noner   rG   r   rI   )rJ   s   "rK   rL   r/  	  s<     *? *?*? *?
  *? *? 
*?rN   c                	0   VP                  4       p\        R/ VB pV Uu. uF
  qe   TMTNK  	  pp\        R V 4       4      p	V	'       g   V P                  VRVR7      # \        P
                  ! V U
u. uF  p
\        P                  ! V
4      NK  	  up
4      pTpVP                  P                  4       pVP                  fD   V U
u0 uF  qP                  kK  	  pp
\        V4      ^8X  d   \        \        V4      4      Vn	        VP                  \        8X  d   VP                  4       pV P                   P#                  WVR7      pV P$                  '       g   V P'                  V4      pVP)                  V P                   RR7      # u upi u up
i u up
i )Nc              3  8   "   T F  qP                   x  K  	  R # 5irP   r   r   s   & rK   r   ?DataFrameGroupBy._wrap_applied_output_series.<locals>.<genexpr>	  s     +DVGGVr   Tr   r1  r   r   rI   )_construct_axes_dictr,   r*   r   r  vstackasarrayr   rQ  rp   r   r;  iterr}   r  tolistrn   r   r   r   r   )rQ   r   r   rA  rB  r   rD   backupr   all_indexed_samevstacked_valuesr   r   rf  r   s   &&&&&&          rK   r@  ,DataFrameGroupBy._wrap_applied_output_series	  sd     446!&!<BCFq!F2FC++DV+DD''!%) (   6#B6aBJJqM6#BC &&++-<<%+,VVVVE,5zQ#DK06)+224N&&~G&T}}}008F""488I">>A D $C -s   F	4FFc               $    V ^8  d   QhRRRRRR/# )rF   r   r   ru   rw   rG   r$   rI   )rJ   s   "rK   rL   r/  	  s(       
 
rN   c                	   a aa S P                  VSR 7      pR VVV 3R llpVP                  V4      pS P                  P                  WfP                  R7      pV# ))ru   rp   c                    V ^8  d   QhRRRR/# )rF   bvaluesr2   rG   rI   )rJ   s   "rK   rL   8DataFrameGroupBy._cython_transform.<locals>.__annotate__	  s     	 	i 	I 	rN   c                D   < SP                   P                  ! R V S^3/ SB # )r   )r   r   )rU  r   rD   rQ   s   &rK   arr_func4DataFrameGroupBy._cython_transform.<locals>.arr_func	  s+    ==22Wc106 rN   rl   )r   r   rn   ro   rm   )rQ   r   ru   rD   rh   rX  res_mgrr   s   ff&l    rK   r   "DataFrameGroupBy._cython_transform	  sY     !77%C 8 
	 	
 ))H%//ll/KrN   c                	j   \        V4      '       d   V P                  ! V.VO5R V/VB # ^ RIHp . pV P                  pV P
                  P                  V4      p	V P                  ! V.VO5/ VB w  r \        V	4      w  r\        P                  VRV4        V P                  WV4      w  rTP                  ^ 8  d(   \        T P                  Y4      pTP!                  T4       T	 F^  w  rTP                  ^ 8X  d   K  \        P                  TRT4       X! T4      p\        T P                  Y4      pTP!                  T4       K`  	  TP$                  pT! T^ RRR7      pTP'                  T^R7      pT P)                  T4      #   \         d   pRp\        T4      ThRp?ii ; i  \"         d     Li ; i)	r   r   rp   z3transform must return a scalar value for each groupNFT)r   rg  r  r   )r.   r  r	  r   r{   r   r  _define_pathsr;  r  r  _choose_pathr!  size_wrap_transform_general_framern   r  StopIterationr   reindexr
  )rQ   r   r   r   rB   rD   r   appliedrn   gen	fast_path	slow_pathrp   r  pathr   r   msgconcat_indexr  s   &&&&*,              rK   r  #DataFrameGroupBy._transform_general	  s   6""--+8<B  	6''mm((-#11$HHH	
	$s)KD
 ufd3/ --iEJ	
 zzA~3DHHeIs# KDzzQufd3u+C/%ECNN3  {{!e$
 $++Lq+A--l;;1  /K o3./  		s*   2F$ F F!FF!$F21F2a  
    >>> df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
    ...                           'foo', 'bar'],
    ...                    'B' : ['one', 'one', 'two', 'three',
    ...                           'two', 'two'],
    ...                    'C' : [1, 5, 5, 2, 5, 5],
    ...                    'D' : [2.0, 5., 8., 1., 2., 9.]})
    >>> grouped = df.groupby('A')[['C', 'D']]
    >>> grouped.transform(lambda x: (x - x.mean()) / x.std())
            C         D
    0 -1.154701 -0.577350
    1  0.577350  0.000000
    2  0.577350  1.154701
    3 -1.154701 -1.000000
    4  0.577350 -0.577350
    5  0.577350  1.000000

    Broadcast result of the transformation

    >>> grouped.transform(lambda x: x.max() - x.min())
        C    D
    0  4.0  6.0
    1  3.0  8.0
    2  4.0  6.0
    3  3.0  8.0
    4  4.0  6.0
    5  3.0  8.0

    >>> grouped.transform("mean")
        C    D
    0  3.666667  4.0
    1  4.000000  5.0
    2  3.666667  4.0
    3  4.000000  5.0
    4  3.666667  4.0
    5  4.000000  5.0

    The resulting dtype will reflect the return value of the passed ``func``,
    for example:

    >>> grouped.transform(lambda x: x.astype(int).max())
    C  D
    0  5  8
    1  5  9
    2  5  8
    3  5  9
    4  5  8
    5  5  9
    c               6    V P                   ! V.VO5RVRV/VB # )a  
Call function producing a same-indexed DataFrame on each group.

Returns a DataFrame having the same indexes as the original object
filled with the transformed values.

Parameters
----------
func : function, str
    Function to apply to each group.
    See the Notes section below for requirements.

    Accepted inputs are:

    - String
    - Python function
    - Numba JIT function with ``engine='numba'`` specified.

    Only passing a single function is supported with this engine.
    If the ``'numba'`` engine is chosen, the function must be
    a user defined function with ``values`` and ``index`` as the
    first and second arguments respectively in the function signature.
    Each group's index will be passed to the user defined function
    and optionally available for use.

    If a string is chosen, then it needs to be the name
    of the groupby method you want to use.
*args
    Positional arguments to pass to func.
engine : str, default None
    * ``'cython'`` : Runs the function through C-extensions from cython.
    * ``'numba'`` : Runs the function through JIT compiled code from numba.
    * ``None`` : Defaults to ``'cython'``
      or the global setting ``compute.use_numba``

engine_kwargs : dict, default None
    * For ``'cython'`` engine, there are no accepted ``engine_kwargs``
    * For ``'numba'`` engine, the engine can accept ``nopython``, ``nogil``
      and ``parallel`` dictionary keys. The values must either be ``True`` or
      ``False``. The default ``engine_kwargs`` for the ``'numba'`` engine is
      ``{'nopython': True, 'nogil': False, 'parallel': False}`` and will be
      applied to the function

**kwargs
    Keyword arguments to be passed into func.

Returns
-------
DataFrame
    DataFrame with the same indexes as the original object filled
    with transformed values.

See Also
--------
DataFrame.groupby.apply : Apply function ``func`` group-wise and combine
    the results together.
DataFrame.groupby.aggregate : Aggregate using one or more operations.
DataFrame.transform : Call ``func`` on self producing a DataFrame with the
    same axis shape as self.

Notes
-----
Each group is endowed the attribute 'name' in case you need to know
which group you are working on.

The current implementation imposes three requirements on f:

* f must return a value that either has the same shape as the input
  subframe or can be broadcast to the shape of the input subframe.
  For example, if `f` returns a scalar it will be broadcast to have the
  same shape as the input subframe.
* if this is a DataFrame, f must support application column-by-column
  in the subframe. If f also supports application to the entire subframe,
  then a fast path is used starting from the second chunk.
* f must not mutate groups. Mutation is not supported and may
  produce unexpected results. See :ref:`gotchas.udf-mutation` for more details.

When using ``engine='numba'``, there will be no "fall back" behavior internally.
The group data and group index will be passed as numpy arrays to the JITed
user defined function, and no alternative execution attempts will be tried.

The resulting dtype will reflect the return value of the passed ``func``,
see the examples below.

.. versionchanged:: 2.0.0

    When using ``.transform`` on a grouped DataFrame
    and the transformation function returns a DataFrame,
    pandas now aligns the result's index with the input's index.
    You can call ``.to_numpy()`` on the result of the
    transformation function to avoid alignment.

Examples
--------

>>> df = pd.DataFrame(
...     {
...         "A": ["foo", "bar", "foo", "bar", "foo", "bar"],
...         "B": ["one", "one", "two", "three", "two", "two"],
...         "C": [1, 5, 5, 2, 5, 5],
...         "D": [2.0, 5.0, 8.0, 1.0, 2.0, 9.0],
...     }
... )
>>> grouped = df.groupby("A")[["C", "D"]]
>>> grouped.transform(lambda x: (x - x.mean()) / x.std())
          C         D
0 -1.154701 -0.577350
1  0.577350  0.000000
2  0.577350  1.154701
3 -1.154701 -1.000000
4  0.577350 -0.577350
5  0.577350  1.000000

Broadcast result of the transformation

>>> grouped.transform(lambda x: x.max() - x.min())
     C    D
0  4.0  6.0
1  3.0  8.0
2  4.0  6.0
3  3.0  8.0
4  4.0  6.0
5  3.0  8.0

>>> grouped.transform("mean")
          C    D
0  3.666667  4.0
1  4.000000  5.0
2  3.666667  4.0
3  4.000000  5.0
4  3.666667  4.0
5  4.000000  5.0

The resulting dtype will reflect the return value of the passed ``func``,
for example:

>>> grouped.transform(lambda x: x.astype(int).max())
   C  D
0  5  8
1  5  9
2  5  8
3  5  9
4  5  8
5  5  9
r   r   r   r   s   &&$$*,rK   r   DataFrameGroupBy.transformV
  s9    d 

 &
6C
GM
 	
rN   c                	   aaa \        S\        4      '       d   VVV3R  lpVVV3R lpWE3# VVV3R lpVVV3R lpWE3# )c                (   < \        V S4      ! S/ SB # rP   r  r  rB   r   rD   s   &rK   r   0DataFrameGroupBy._define_paths.<locals>.<lambda>
  s    geT&:D&KF&KrN   c                6   < V P                  VVV3R  l^ R7      # )c                (   < \        V S4      ! S/ SB # rP   r  r   s   &rK   r   BDataFrameGroupBy._define_paths.<locals>.<lambda>.<locals>.<lambda>
  s    '!T*D;F;rN   r]  r  rp  s   &rK   r   rq  
  s    ekk;! '2 'rN   c                   < S! V .SO5/ SB # rP   rI   rp  s   &rK   r   rq  
  s    d5&B4&B6&BrN   c                6   < V P                  VVV3R  l^ R7      # )c                   < S! V .SO5/ SB # rP   rI   r   s   &rK   r   rt  
  s    $q24262rN   r]  r  rp  s   &rK   r   rq  
  s    ekk2 '2 'rN   )r   r   )rQ   r   rB   rD   rf  rg  s   &fjl  rK   r^  DataFrameGroupBy._define_paths
  sA    dC  KII ##	 CII ##rN   c               $    V ^8  d   QhRRRRRR/# )rF   rf  r   rg  r  r$   rI   )rJ   s   "rK   rL   r/  
  s!     " "h "8 "I "rN   c                	   TpV! V4      pV P                   ^8X  d   WE3#  V! V4      p\        T\        4      '       d0   TP
                  P                  TP
                  4      '       g   YE3# MH\        T\        4      '       d0   TP                  P                  TP
                  4      '       g   YE3# MYE3# TP                  T4      '       d   TpYE3#   \         d    h \         d    YE3u # i ; i)rV  )	r   r2  	Exceptionr   r$   r   equalsr,   r   )rQ   rf  rg  r  rh  r   res_fasts   &&&&   rK   r_  DataFrameGroupBy._choose_path
  s    <<1 9	 'H h	**##**5==99y  :&))>>((77y  8 9??3Dy-  	 	 9	s   C C-&C-,C-c                    V ^8  d   QhRRRR/# rF   r  rw   rG   r$   rI   )rJ   s   "rK   rL   r/    s     R3 R34 R3I R3rN   c                :   . pV P                   pV P                  P                  V4      pV F  w  r\        P	                  V	RV4       V! V	.VO5/ VB p
 V
P                  4       p
\        V
4      '       g#   \        V
4      '       dQ   \        V
4      '       d@   \        V
4      '       d-   V
'       d#   VP                  V P                  V4      4       K  K  K  \        R\        V
4      P                   R24      h	  V P!                  WR4      #   \         d     Li ; i)ar  
Filter elements from groups that don't satisfy a criterion.

Elements from groups are filtered if they do not satisfy the
boolean criterion specified by func.

Parameters
----------
func : function
    Criterion to apply to each group. Should return True or False.
dropna : bool
    Drop groups that do not pass the filter. True by default; if False,
    groups that evaluate False are filled with NaNs.
*args : tuple
    Additional positional arguments to pass to `func`.
**kwargs : dict
    Additional keyword arguments to pass to `func`.

Returns
-------
DataFrame
    The filtered subset of the original DataFrame.

See Also
--------
DataFrame.filter: Filter elements of ungrouped DataFrame.
SeriesGroupBy.filter : Filter elements from groups base on criterion.

Notes
-----
Each subframe is endowed the attribute 'name' in case you need to know
which group you are working on.

Functions that mutate the passed object can produce unexpected
behavior or errors and are not supported. See :ref:`gotchas.udf-mutation`
for more details.

Examples
--------
>>> df = pd.DataFrame(
...     {
...         "A": ["foo", "bar", "foo", "bar", "foo", "bar"],
...         "B": [1, 2, 3, 4, 5, 6],
...         "C": [2.0, 5.0, 8.0, 1.0, 2.0, 9.0],
...     }
... )
>>> grouped = df.groupby("A")
>>> grouped.filter(lambda x: x["B"].mean() > 3.0)
     A  B    C
1  bar  2  5.0
3  bar  4  1.0
5  bar  6  9.0
rp   zfilter function returned a z, but expected a scalar bool)r,  r   r  r  r  squeezeAttributeErrorr   r   r   r   r  r   r~   r   r[   r"  )rQ   r   r  rB   rD   r#  rn   re  rp   r  r   s   &&&*,      rK   r%  DataFrameGroupBy.filter  s   l   mm((-KD ufd3u.t.v.Ckkm
 s||	#499::#NN4??4#89 #&:  1$s)2D2D1E F1 1 % . !!'22 " s   DDDc                   V ^8  d   QhRR/# )rF   rG   z DataFrameGroupBy | SeriesGroupByrI   )rJ   s   "rK   rL   r/  q  s     	( 	("B 	(rN   c                	   < \        V\        4      '       d   \        V4      ^8  d   \        R4      h\        SV `  V4      # )rV  zRCannot subset columns with a tuple with more than one element. Use a list instead.)r   r   r   r!  r   rY   )rQ   rU   r   s   &&rK   rY   DataFrameGroupBy.__getitem__q  s@    c5!!c#hl &  w"3''rN   c                   V ^8  d   QhRR/# )rF   ndimrV   rI   )rJ   s   "rK   rL   r/  |  s     .: .:# .:rN   c                B   V^8X  d   Vf   V P                   p\        VV P                  V P                  V P                  V P
                  VV P                  V P                  V P                  V P                  V P                  R7      # V^8X  d   Vf   V P                   V,          p\        VV P                  V P                  V P                  V P
                  VV P                  V P                  V P                  V P                  V P                  R7      # \        R4      h)z
sub-classes to define
return a sliced object

Parameters
----------
key : string / list of selections
ndim : {1, 2}
    requested ndim of result
subset : object, default None
    subset to act on
)	levelgrouper
exclusions	selectionr   r+  r   observedr  zinvalid ndim for _gotitem)rn   r  r   r  r   r  r   r+  r   r  r  rf   r2  )rQ   rU   r  subsets   &&&&rK   _gotitemDataFrameGroupBy._gotitem|  s     19~#		jj??YY??{{  QY~# 		jj??YY??{{  899rN   ru   rp   c               $    V ^8  d   QhRRRRRR/# )rF   ru   rw   rp   rx   rG   r3   rI   )rJ   s   "rK   rL   r/    s$      #3=	rN   c               	f    V P                   pVP                  pV'       d   VP                  4       pV# rP   )r{   r|   get_numeric_data)rQ   ru   rp   rn   rh   s   &$$  rK   r   'DataFrameGroupBy._get_data_to_aggregate  s.     ''hh&&(C
rN   c                    V ^8  d   QhRRRR/# )rF   rh   r3   rG   r$   rI   )rJ   s   "rK   rL   r/    s     B B| B	 BrN   c                	N    V P                   P                  WP                  R 7      # rk   )rn   ro   rm   )rQ   rh   s   &&rK   rs   $DataFrameGroupBy._wrap_agged_manager  s    xx--c-AArN   c                   V ^8  d   QhRR/# r   rI   )rJ   s   "rK   rL   r/    s       rN   c                	  a a ^ RI Hp S P                  oSP                  pVV 3R l\	        SP                  4       4       pV Uu. uF
  qQ! V4      NK  	  ppV'       g$   \        . VS P                  P                  R7      pM
V! Wc^R7      pS P                  '       g+   \        \        V4      4      Vn        S P                  V4      pV# u upi )r9  r   c           	   3     <"   T FH  w  r\        SP                  R V3,          VSP                  SP                  SP                  R7      x  KJ  	  R# 5i)r  )r  r  r  r  N)rf   r   r   r  r  )r   icolnamern   rQ   s   &  rK   r   =DataFrameGroupBy._apply_to_column_groupbys.<locals>.<genexpr>  sO      	
 5
 A!??  5s   AAr   r   )r   r   )r	  r   r{   r   r   r$   r   r   r   r+   r   r   r   )	rQ   r   r   r   sgbssgbr   r   rn   s	   f&      @rK   _apply_to_column_groupbys*DataFrameGroupBy._apply_to_column_groupbys  s    5''++	
 (4	
 )--49-r7$--:T:TUFG:F}}}(V5FL008F .s   C
c                    V ^8  d   QhRRRR/# r  rI   )rJ   s   "rK   rL   r/    s     4O 4Od 4Oi 4OrN   c                .   a V P                  V3R l4      # )a*  
Return DataFrame with counts of unique elements in each position.

Parameters
----------
dropna : bool, default True
    Don't include NaN in the counts.

Returns
-------
nunique: DataFrame
    Counts of unique elements in each position.

See Also
--------
DataFrame.nunique : Count number of distinct elements in specified axis.

Examples
--------
>>> df = pd.DataFrame(
...     {
...         "id": ["spam", "egg", "egg", "spam", "ham", "ham"],
...         "value1": [1, 5, 5, 2, 5, 5],
...         "value2": list("abbaxy"),
...     }
... )
>>> df
     id  value1 value2
0  spam       1      a
1   egg       5      b
2   egg       5      b
3  spam       2      a
4   ham       5      x
5   ham       5      y

>>> df.groupby("id").nunique()
      value1  value2
id
egg        1       1
ham        1       2
spam       2       1

Check for rows with the same id but conflicting values:

>>> df.groupby("id").filter(lambda g: (g.nunique() > 1).any())
     id  value1 value2
0  spam       1      a
3  spam       2      a
4   ham       5      x
5   ham       5      y
c                &   < V P                  S4      # rP   )r:  )r  r  s   &rK   r   *DataFrameGroupBy.nunique.<locals>.<lambda>  s    #++f:MrN   )r  )rQ   r  s   &frK   r:  DataFrameGroupBy.nunique  s    h --.MNNrN   c               $    V ^8  d   QhRRRRRR/# rF   r  rw   ru   rG   r$   rI   )rJ   s   "rK   rL   r/  
  2     FW FWFW FW 
	FWrN   c                (    V P                  RW!R7      # )a  
Return index of first occurrence of maximum in each group.

Parameters
----------
skipna : bool, default True
    Exclude NA values.
numeric_only : bool, default False
    Include only `float`, `int` or `boolean` data.

Returns
-------
DataFrame
    Indexes of maxima in each column according to the group.

Raises
------
ValueError
    When there are no valid values for a group. Then can happen if:

        * There is an unobserved group and ``observed=False``.
        * All values for a group are NA.
        * Some values for a group are NA and ``skipna=False``.

.. versionchanged:: 3.0.0
    Previously if all values for a group are NA or some values for a group are
    NA and ``skipna=False``, this method would return NA. Now it raises instead.

See Also
--------
Series.idxmax : Return index of the maximum element.
DataFrame.idxmax : Indexes of maxima along the specified axis.

Notes
-----
This method is the DataFrame version of ``ndarray.argmax``.

Examples
--------
Consider a dataset containing food consumption in Argentina.

>>> df = pd.DataFrame(
...     {
...         "consumption": [10.51, 103.11, 55.48],
...         "co2_emissions": [37.2, 19.66, 1712],
...         "food_type": ["meat", "plant", "meat"],
...     },
...     index=["Pork", "Wheat Products", "Beef"],
... )

>>> df
                consumption  co2_emissions food_type
Pork                  10.51         37.20       meat
Wheat Products       103.11         19.66      plant
Beef                  55.48       1712.00       meat

By default, it returns the index for the maximum value in each column
according to the group.

>>> df.groupby("food_type").idxmax()
              consumption   co2_emissions
food_type
meat                 Beef            Beef
plant      Wheat Products  Wheat Products
r  ru   r  r  rQ   r  ru   s   &&&rK   r  DataFrameGroupBy.idxmax
      L ""8,"VVrN   c               $    V ^8  d   QhRRRRRR/# r  rI   )rJ   s   "rK   rL   r/  R  r  rN   c                (    V P                  RW!R7      # )a  
Return index of first occurrence of minimum in each group.

Parameters
----------
skipna : bool, default True
    Exclude NA values.
numeric_only : bool, default False
    Include only `float`, `int` or `boolean` data.

Returns
-------
DataFrame
    Indexes of minima in each column according to the group.

Raises
------
ValueError
    When there are no valid values for a group. Then can happen if:

        * There is an unobserved group and ``observed=False``.
        * All values for a group are NA.
        * Some values for a group are NA and ``skipna=False``.

.. versionchanged:: 3.0.0
    Previously if all values for a group are NA or some values for a group are
    NA and ``skipna=False``, this method would return NA. Now it raises instead.

See Also
--------
Series.idxmin : Return index of the minimum element.
DataFrame.idxmin : Indexes of minima along the specified axis.

Notes
-----
This method is the DataFrame version of ``ndarray.argmin``.

Examples
--------
Consider a dataset containing food consumption in Argentina.

>>> df = pd.DataFrame(
...     {
...         "consumption": [10.51, 103.11, 55.48],
...         "co2_emissions": [37.2, 19.66, 1712],
...         "food_type": ["meat", "plant", "meat"],
...     },
...     index=["Pork", "Wheat Products", "Beef"],
... )

>>> df
                consumption  co2_emissions food_type
Pork                  10.51         37.20       meat
Wheat Products       103.11         19.66      plant
Beef                  55.48       1712.00       meat

By default, it returns the index for the minimum value in each column
according to the group.

>>> df.groupby("food_type").idxmin()
              consumption   co2_emissions
food_type
meat                 Pork            Pork
plant      Wheat Products  Wheat Products
r  r  r  r  s   &&&rK   r  DataFrameGroupBy.idxminR  r  rN   c               0    V ^8  d   QhRRRRRRRRRRRR	/# )
rF   r  zSequence[Hashable] | NonerD  rw   r+  rE  r  rG   r   rI   )rJ   s   "rK   rL   r/    sV     uN uN)uN uN 	uN
 uN uN 
uNrN   c                (    V P                  WW4V4      # )af  
Return a Series or DataFrame containing counts of unique rows.

Parameters
----------
subset : list-like, optional
    Columns to use when counting unique combinations.
normalize : bool, default False
    Return proportions rather than frequencies.
sort : bool, default True
    Stable sort by frequencies when True. When False, non-grouping
    columns will appear in the order they occur in within groups.

    .. versionchanged:: 3.0.0

        In prior versions, ``sort=False`` would sort the non-grouping columns
        by label.
ascending : bool, default False
    Sort in ascending order.
dropna : bool, default True
    Don't include counts of rows that contain NA values.

Returns
-------
Series or DataFrame
    Series if the groupby ``as_index`` is True, otherwise DataFrame.

See Also
--------
Series.value_counts: Equivalent method on Series.
DataFrame.value_counts: Equivalent method on DataFrame.
SeriesGroupBy.value_counts: Equivalent method on SeriesGroupBy.

Notes
-----
- If the groupby ``as_index`` is True then the returned Series will have a
  MultiIndex with one level per input column.
- If the groupby ``as_index`` is False then the returned DataFrame will have an
  additional column with the value_counts. The column is labelled 'count' or
  'proportion', depending on the ``normalize`` parameter.

By default, rows that contain any NA values are omitted from
the result.

By default, the result will be in descending order so that the
first element of each group is the most frequently-occurring row.

Examples
--------
>>> df = pd.DataFrame(
...     {
...         "gender": ["male", "male", "female", "male", "female", "male"],
...         "education": ["low", "medium", "high", "low", "high", "low"],
...         "country": ["US", "FR", "US", "FR", "FR", "FR"],
...     }
... )

>>> df
        gender  education   country
0       male    low         US
1       male    medium      FR
2       female  high        US
3       male    low         FR
4       female  high        FR
5       male    low         FR

>>> df.groupby("gender").value_counts()
gender  education  country
female  high       US         1
                   FR         1
male    low        FR         2
                   US         1
        medium     FR         1
Name: count, dtype: int64

>>> df.groupby("gender").value_counts(ascending=True)
gender  education  country
female  high       US         1
                   FR         1
male    low        US         1
        medium     FR         1
        low        FR         2
Name: count, dtype: int64

>>> df.groupby("gender").value_counts(normalize=True)
gender  education  country
female  high       US         0.50
                   FR         0.50
male    low        FR         0.50
                   US         0.25
        medium     FR         0.25
Name: proportion, dtype: float64

>>> df.groupby("gender", as_index=False).value_counts()
   gender education country  count
0  female      high      US      1
1  female      high      FR      1
2    male       low      FR      2
3    male       low      US      1
4    male    medium      FR      1

>>> df.groupby("gender", as_index=False).value_counts(normalize=True)
   gender education country  proportion
0  female      high      US        0.50
1  female      high      FR        0.50
2    male       low      FR        0.50
3    male       low      US        0.25
4    male    medium      FR        0.25
)rh  )rQ   r  rD  r+  rE  r  s   &&&&&&rK   rl  DataFrameGroupBy.value_counts  s    j !!&TfMMrN   c                    V ^8  d   QhRRRR/# )rF   r#  r8   rG   r$   rI   )rJ   s   "rK   rL   r/    s"     ] ]] 
	]rN   c                .    V P                   ! RRV/VB pV# )a	  
Return the elements in the given *positional* indices in each group.

This means that we are not indexing according to actual values in
the index attribute of the object. We are indexing according to the
actual position of the element in the object.

If a requested index does not exist for some group, this method will raise.
To get similar behavior that ignores indices that don't exist, see
:meth:`.DataFrameGroupBy.nth`.

Parameters
----------
indices : array-like
    An array of ints indicating which positions to take.

**kwargs
    For compatibility with :meth:`numpy.take`. Has no effect on the
    output.

Returns
-------
DataFrame
    A DataFrame containing the elements taken from each group.

See Also
--------
DataFrame.take : Take elements from a Series along an axis.
DataFrame.loc : Select a subset of a DataFrame by labels.
DataFrame.iloc : Select a subset of a DataFrame by positions.
numpy.take : Take elements from an array along an axis.

Examples
--------
>>> df = pd.DataFrame(
...     [
...         ("falcon", "bird", 389.0),
...         ("parrot", "bird", 24.0),
...         ("lion", "mammal", 80.5),
...         ("monkey", "mammal", np.nan),
...         ("rabbit", "mammal", 15.0),
...     ],
...     columns=["name", "class", "max_speed"],
...     index=[4, 3, 2, 1, 0],
... )
>>> df
     name   class  max_speed
4  falcon    bird      389.0
3  parrot    bird       24.0
2    lion  mammal       80.5
1  monkey  mammal        NaN
0  rabbit  mammal       15.0
>>> gb = df.groupby([1, 1, 2, 2, 2])

Take elements at rows 0 and 1.

Note how the indices selected in the result do not correspond to
our input indices 0 and 1. That's because we are selecting the 0th
and 1st rows, not rows whose indices equal 0 and 1.

>>> gb.take([0, 1])
       name   class  max_speed
1 4  falcon    bird      389.0
  3  parrot    bird       24.0
2 2    lion  mammal       80.5
  1  monkey  mammal        NaN

The order of the specified indices influences the order in the result.
Here, the order is swapped from the previous example.

>>> gb.take([1, 0])
       name   class  max_speed
1 3  parrot    bird       24.0
  4  falcon    bird      389.0
2 1  monkey  mammal        NaN
  2    lion  mammal       80.5

We may take elements using negative integers for positive indices,
starting from the end of the object, just like with Python lists.

>>> gb.take([-1, -2])
       name   class  max_speed
1 3  parrot    bird       24.0
  4  falcon    bird      389.0
2 0  rabbit  mammal       15.0
  1  monkey  mammal        NaN
r#  r  r  r  s   &&, rK   rn  DataFrameGroupBy.take  s"    x ##FGFvFrN   c               $    V ^8  d   QhRRRRRR/# r  rI   )rJ   s   "rK   rL   r/  r  s-     H
 H
H
 H

 
H
rN   c           	     8    R pV P                   ! RRVRVRV/VB # )a  
Return unbiased skew within groups.

Normalized by N-1.

Parameters
----------
skipna : bool, default True
    Exclude NA/null values when computing the result.

numeric_only : bool, default False
    Include only float, int, boolean columns.

**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
DataFrame
    Unbiased skew within groups.

See Also
--------
DataFrame.skew : Return unbiased skew over requested axis.

Examples
--------
>>> arrays = [
...     ["falcon", "parrot", "cockatoo", "kiwi", "lion", "monkey", "rabbit"],
...     ["bird", "bird", "bird", "bird", "mammal", "mammal", "mammal"],
... ]
>>> index = pd.MultiIndex.from_arrays(arrays, names=("name", "class"))
>>> df = pd.DataFrame(
...     {"max_speed": [389.0, 24.0, 70.0, np.nan, 80.5, 21.5, 15.0]},
...     index=index,
... )
>>> df
                max_speed
name     class
falcon   bird        389.0
parrot   bird         24.0
cockatoo bird         70.0
kiwi     bird          NaN
lion     mammal       80.5
monkey   mammal       21.5
rabbit   mammal       15.0
>>> gb = df.groupby(["class"])
>>> gb.skew()
        max_speed
class
bird     1.628296
mammal   1.669046
>>> gb.skew(skipna=False)
        max_speed
class
bird          NaN
mammal   1.669046
c                2    \        R V P                   24      h)z"'skew' is not supported for dtype=r  r  s   &rK   r  "DataFrameGroupBy.skew.<locals>.alt  r  rN   r  r  ru   r  r  r  s   &&&, rK   r  DataFrameGroupBy.skewr  s>    B	N
 '' 

$*
9E
IO
 	
rN   c               $    V ^8  d   QhRRRRRR/# r  rI   )rJ   s   "rK   rL   r/    s-     g
 g
g
 g

 
g
rN   c           	     2    V P                   ! RRRRVRV/VB # )aL  
Return unbiased kurtosis within groups.

Parameters
----------
skipna : bool, default True
    Exclude NA/null values when computing the result.

numeric_only : bool, default False
    Include only float, int, boolean columns.

**kwargs
    Additional keyword arguments to be passed to the function.

Returns
-------
DataFrame
    Unbiased kurtosis within groups.

See Also
--------
DataFrame.kurt : Return unbiased kurtosis over requested axis.

Examples
--------
>>> arrays = [
...     [
...         "falcon",
...         "parrot",
...         "cockatoo",
...         "kiwi",
...         "eagle",
...         "lion",
...         "monkey",
...         "rabbit",
...         "dog",
...         "wolf",
...     ],
...     [
...         "bird",
...         "bird",
...         "bird",
...         "bird",
...         "bird",
...         "mammal",
...         "mammal",
...         "mammal",
...         "mammal",
...         "mammal",
...     ],
... ]
>>> index = pd.MultiIndex.from_arrays(arrays, names=("name", "class"))
>>> df = pd.DataFrame(
...     {
...         "max_speed": [
...             389.0,
...             24.0,
...             70.0,
...             np.nan,
...             350.0,
...             80.5,
...             21.5,
...             15.0,
...             40.0,
...             50.0,
...         ]
...     },
...     index=index,
... )
>>> df
                 max_speed
name     class
falcon   bird        389.0
parrot   bird         24.0
cockatoo bird         70.0
kiwi     bird          NaN
eagle    bird        350.0
lion     mammal       80.5
monkey   mammal       21.5
rabbit   mammal       15.0
dog      mammal       40.0
wolf     mammal       50.0
>>> gb = df.groupby(["class"])
>>> gb.kurt()
        max_speed
class
bird    -5.493277
mammal   0.204125
>>> gb.kurt(skipna=False)
        max_speed
class
bird          NaN
mammal   0.204125
r  Nr  ru   r  r  r  s   &&&,rK   r  DataFrameGroupBy.kurt  s8    J '' 

%+
:F
JP
 	
rN   c                   V ^8  d   QhRR/# r  rI   )rJ   s   "rK   rL   r/  &  s      k rN   c                    \        V 4      pV# )a  
Make plots of groups from a DataFrame.

Uses the backend specified by the option ``plotting.backend``.
By default, matplotlib is used.

Returns
-------
GroupByPlot
    A plotting object that can be used to create plots for each group.

See Also
--------
DataFrame.plot : Make plots of DataFrame.

Examples
--------
>>> df = pd.DataFrame(
...     {"A": [1, 2, 3, 4], "B": [5, 6, 7, 8]}, index=["a", "a", "b", "b"]
... )
>>> g = df.groupby(level=0)
>>> g.plot()  # doctest: +SKIP
r  r  s   & rK   r  DataFrameGroupBy.plot%  s    2 T"rN   c               (    V ^8  d   QhRRRRRRRR/# )	rF   r   z/str | Callable[[np.ndarray, np.ndarray], float]r  rV   ru   rw   rG   r$   rI   )rJ   s   "rK   rL   r/  A  s8     Q Q?Q Q 	Q
 
QrN   c                .    V P                  RWVR7      pV# )a  
Compute pairwise correlation of columns, excluding NA/null values.

Parameters
----------
method : {'pearson', 'kendall', 'spearman'} or callable
    Method of correlation:

    * pearson : standard correlation coefficient
    * kendall : Kendall Tau correlation coefficient
    * spearman : Spearman rank correlation
    * callable: callable with input two 1d ndarrays
        and returning a float. Note that the returned matrix from corr
        will have 1 along the diagonals and will be symmetric
        regardless of the callable's behavior.
min_periods : int, optional
    Minimum number of observations required per pair of columns
    to have a valid result. Currently only available for Pearson
    and Spearman correlation.
numeric_only : bool, default False
    Include only `float`, `int` or `boolean` data.

    .. versionchanged:: 2.0.0
        The default value of ``numeric_only`` is now ``False``.

Returns
-------
DataFrame
    Correlation matrix.

See Also
--------
DataFrame.corrwith : Compute pairwise correlation with another
    DataFrame or Series.
Series.corr : Compute the correlation between two Series.

Notes
-----
Pearson, Kendall and Spearman correlation are currently computed using
pairwise complete observations.

* `Pearson correlation coefficient <https://en.wikipedia.org/wiki/Pearson_correlation_coefficient>`_
* `Kendall rank correlation coefficient <https://en.wikipedia.org/wiki/Kendall_rank_correlation_coefficient>`_
* `Spearman's rank correlation coefficient <https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient>`_

Examples
--------
>>> df = pd.DataFrame(
...     {
...         "age": [2, 3, 4, 6, 6, 1, 2, 1],
...         "weight": [2.1, 3.2, 4.1, 6.5, 3.3, 2.1, 4.1, 1.9],
...         "pet": ["dog", "cat", "dog", "cat", "dog", "cat", "dog", "cat"],
...     }
... )
>>> df
   age  weight  pet
0    2     2.1  dog
1    3     3.2  cat
2    4     4.1  dog
3    6     6.5  cat
4    6     3.3  dog
5    1     2.1  cat
6    2     4.1  dog
7    1     1.9  cat
>>> df.groupby("pet").corr()
                 age    weight
pet
cat age     1.000000  0.989321
    weight  0.989321  1.000000
dog age     1.000000  0.184177
    weight  0.184177  1.000000
r  )r   r  ru   r  )rQ   r   r  ru   r   s   &&&& rK   r  DataFrameGroupBy.corrA  s(    \ ##6 $ 
 rN   c               (    V ^8  d   QhRRRRRRRR/# )rF   r  r  r  ru   rw   rG   r$   rI   )rJ   s   "rK   rL   r/    s8     g gg g 	g
 
grN   c                .    V P                  RWVR7      pV# )a  
Compute pairwise covariance of columns, excluding NA/null values.

Compute the pairwise covariance among the series of a DataFrame.
The returned data frame is the `covariance matrix
<https://en.wikipedia.org/wiki/Covariance_matrix>`__ of the columns
of the DataFrame.

Both NA and null values are automatically excluded from the
calculation. (See the note below about bias from missing values.)
A threshold can be set for the minimum number of
observations for each value created. Comparisons with observations
below this threshold will be returned as ``NaN``.

This method is generally used for the analysis of time series data to
understand the relationship between different measures
across time.

Parameters
----------
min_periods : int, optional
    Minimum number of observations required per pair of columns
    to have a valid result.

ddof : int, default 1
    Delta degrees of freedom.  The divisor used in calculations
    is ``N - ddof``, where ``N`` represents the number of elements.
    This argument is applicable only when no ``nan`` is in the dataframe.

numeric_only : bool, default False
    Include only `float`, `int` or `boolean` data.

    .. versionchanged:: 2.0.0
        The default value of ``numeric_only`` is now ``False``.

Returns
-------
DataFrame
    The covariance matrix of the series of the DataFrame.

See Also
--------
Series.cov : Compute covariance with another Series.
core.window.ewm.ExponentialMovingWindow.cov : Exponential weighted sample
    covariance.
core.window.expanding.Expanding.cov : Expanding sample covariance.
core.window.rolling.Rolling.cov : Rolling sample covariance.

Notes
-----
Returns the covariance matrix of the DataFrame's time series.
The covariance is normalized by N-ddof.

For DataFrames that have Series that are missing data (assuming that
data is `missing at random
<https://en.wikipedia.org/wiki/Missing_data#Missing_at_random>`__)
the returned covariance matrix will be an unbiased estimate
of the variance and covariance between the member Series.

However, for many applications this estimate may not be acceptable
because the estimate covariance matrix is not guaranteed to be positive
semi-definite. This could lead to estimate correlations having
absolute values which are greater than one, and/or a non-invertible
covariance matrix. See `Estimation of covariance matrices
<https://en.wikipedia.org/w/index.php?title=Estimation_of_covariance_
matrices>`__ for more details.

Examples
--------
>>> df = pd.DataFrame(
...     {
...         "age": [2, 3, 4, 6, 6, 1, 2, 1],
...         "weight": [2.1, 3.2, 4.1, 6.5, 3.3, 2.1, 4.1, 1.9],
...         "pet": ["dog", "cat", "dog", "cat", "dog", "cat", "dog", "cat"],
...     }
... )
>>> df
   age  weight  pet
0    2     2.1  dog
1    3     3.2  cat
2    4     4.1  dog
3    6     6.5  cat
4    6     3.3  dog
5    1     2.1  cat
6    2     4.1  dog
7    1     1.9  cat
>>> df.groupby("pet").cov()
                 age    weight
pet
cat age     5.583333  4.975000
    weight  4.975000  4.529167
dog age     3.666667  0.333333
    weight  0.333333  0.893333
r  )r  r  ru   r  )rQ   r  r  ru   r   s   &&&& rK   r  DataFrameGroupBy.cov  s(    H ##{L $ 
 rN   c               L    V ^8  d   QhRRRRRRRRR	RR
RRRRRRRRRRRRRRR/# )rF   r@   zIndexLabel | Noner  rw   r  r  r  r  r  r  sharexshareyr  r  layoutztuple[int, int] | NonerK  r  r  rx   r   rI   )rJ   s   "rK   rL   r/    s     ~ ~!~ 	~
 ~ ~ ~ ~ ~ ~ ,~ '~ "~ ~  !~rN   c           !     f    V P                   ! RRVRVRVRVRVRVRVRVR	V	R
V
RVRVRVRVRV/VB pV# )aT  
Make a histogram of the DataFrame's columns.

A `histogram`_ is a representation of the distribution of data.
This function calls :meth:`matplotlib.pyplot.hist`, on each series in
the DataFrame, resulting in one histogram per column.

.. _histogram: https://en.wikipedia.org/wiki/Histogram

Parameters
----------
column : str or sequence, optional
    If passed, will be used to limit data to a subset of columns.
by : object, optional
    If passed, then used to form histograms for separate groups.
grid : bool, default True
    Whether to show axis grid lines.
xlabelsize : int, default None
    If specified changes the x-axis label size.
xrot : float, default None
    Rotation of x axis labels. For example, a value of 90 displays the
    x labels rotated 90 degrees clockwise.
ylabelsize : int, default None
    If specified changes the y-axis label size.
yrot : float, default None
    Rotation of y axis labels. For example, a value of 90 displays the
    y labels rotated 90 degrees clockwise.
ax : Matplotlib axes object, default None
    The axes to plot the histogram on.
sharex : bool, default True if ax is None else False
    In case subplots=True, share x axis and set some x axis labels to
    invisible; defaults to True if ax is None otherwise False if an ax
    is passed in.
    Note that passing in both an ax and sharex=True will alter all x axis
    labels for all subplots in a figure.
sharey : bool, default False
    In case subplots=True, share y axis and set some y axis labels to
    invisible.
figsize : tuple, optional
    The size in inches of the figure to create. Uses the value in
    `matplotlib.rcParams` by default.
layout : tuple, optional
    Tuple of (rows, columns) for the layout of the histograms.
bins : int or sequence, default 10
    Number of histogram bins to be used. If an integer is given, bins + 1
    bin edges are calculated and returned. If bins is a sequence, gives
    bin edges, including left edge of first bin and right edge of last
    bin. In this case, bins is returned unmodified.

backend : str, default None
    Backend to use instead of the backend specified in the option
    ``plotting.backend``. For instance, 'matplotlib'. Alternatively, to
    specify the ``plotting.backend`` for the whole session, set
    ``pd.options.plotting.backend``.

legend : bool, default False
    Whether to show the legend.

**kwargs
    All other plotting keyword arguments to be passed to
    :meth:`matplotlib.pyplot.hist`.

Returns
-------
matplotlib.Axes or numpy.ndarray
    A ``matplotlib.Axes`` object or an array of ``Axes`` objects, depending on
    the layout and grouping.

See Also
--------
matplotlib.pyplot.hist : Plot a histogram using matplotlib.

Examples
--------
This example draws a histogram based on the length and width of
some animals, displayed in three bins

.. plot::
    :context: close-figs

    >>> data = {
    ...     "length": [1.5, 0.5, 1.2, 0.9, 3],
    ...     "width": [0.7, 0.2, 0.15, 0.2, 1.1],
    ... }
    >>> index = ["pig", "rabbit", "duck", "chicken", "horse"]
    >>> df = pd.DataFrame(data, index=index)
    >>> hist = df.groupby("length").hist(bins=3)
r@   r  r  r  r  r  r  r  r  r  r  r  rK  r  r   r  r  )rQ   r@   r  r  r  r  r  r  r  r  r  r  r  rK  r  r   rD   r   s   &&&&&&&&&&&&&&&&, rK   r  DataFrameGroupBy.hist  s    V ## 

 
 	

 "
 
 "
 
 
 
 
 
 
 
 
  !
" #
& rN   c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
rF   r  r   droprw   r   r4   ru   rG   r$   rI   )rJ   s   "rK   rL   r/  }  sC     Q Q!Q Q "	Q
 Q 
QrN   c                |    \         P                  ! R\        \        4       R7       V P	                  RVVVVR7      pV# )a  
Compute pairwise correlation.

.. deprecated:: 3.0.0

Pairwise correlation is computed between rows or columns of
DataFrame with rows or columns of Series or DataFrame. DataFrames
are first aligned along both axes before computing the
correlations.

Parameters
----------
other : DataFrame, Series
    Object with which to compute correlations.
drop : bool, default False
    Drop missing indices from result.
method : {'pearson', 'kendall', 'spearman'} or callable
    Method of correlation:

    * pearson : standard correlation coefficient
    * kendall : Kendall Tau correlation coefficient
    * spearman : Spearman rank correlation
    * callable: callable with input two 1d ndarrays
        and returning a float.

numeric_only : bool, default False
    Include only `float`, `int` or `boolean` data.

    .. versionchanged:: 2.0.0
        The default value of ``numeric_only`` is now ``False``.

Returns
-------
Series
    Pairwise correlations.

See Also
--------
DataFrame.corr : Compute pairwise correlation of columns.

Examples
--------
>>> df1 = pd.DataFrame(
...     {
...         "Day": [1, 1, 1, 2, 2, 2, 3, 3, 3],
...         "Data": [6, 6, 8, 5, 4, 2, 7, 3, 9],
...     }
... )
>>> df2 = pd.DataFrame(
...     {
...         "Day": [1, 1, 1, 2, 2, 2, 3, 3, 3],
...         "Data": [5, 3, 8, 3, 1, 1, 2, 3, 6],
...     }
... )

>>> df1.groupby("Day").corrwith(df2)
         Data  Day
Day
1    0.917663  NaN
2    0.755929  NaN
3    0.576557  NaN
z'DataFrameGroupBy.corrwith is deprecated)
stacklevelcorrwith)r  r  r   ru   )warningswarnr   r   r  )rQ   r  r  r   ru   r   s   &&&&& rK   r  DataFrameGroupBy.corrwith}  sJ    J 	5')	

 ##% $ 
 rN   rI   rP   r  r  r  r  )NFTFT)r  rV  F)NrV  F)NNTNNNNNFFNNr  NF)Fr  F)(r[   r\   r]   r^   r   r  r   r"  r   r@  r   r  r   )_DataFrameGroupBy__examples_dataframe_docr   r^  r_  r%  rY   r  r   rs   r  r:  r  r  r/   boxplotrl  rn  r  r  r  r  r  r  r  r  rd   r  r  s   @rK   r  r  <  s   x xT xt C1."IV*?X.0<d  &0	2 hT
D T
 T
l$"HR3h	( 	(.:`&+@DB84OlFWPFWP $GuNn]~H
Tg
R  6QfgR~@Q QrN   r  c               (    V ^8  d   QhRRRRRRRR/# )rF   rn   r$   r  r   r   rG   rI   )rJ   s   "rK   rL   rL     s,      	$+=rN   c                   ^ RI Hp \        V\        4      '       d   VP                  P                  V P                  4      '       dJ   V! V.\        VP                  4      ,          ^RR7      pVP                  Vn        VP                  Vn        M\V P                  \        P                  ! VP                  \        VP                  4      ^34      VP                  VP                  R7      p\        V\        4      '       g   Q hV# \        V\        4      '       dD   VP                  P                  VP                  4      '       g   VP                  V4      ^ ,          # V# )r9  r   T)r   r  r  )r=   r   r   r,   r   is_r   r   r   r  r~  r   r$   _align_frame)rn   r  r   r   	res_frames   &&&  rK   ra  ra    s     #v 99==##us5=='99PTUI %I#kkIO((

S%5q$9:kk ) I
 )Y////	C	#	#CIIMM%++,F,F&q))
rN   )h__conditional_annotations__r_   
__future__r   collectionsr   collections.abcr   ra   	functoolsr   textwrapr   typingr   r   r	   r
   r   r   r  numpyr  pandas._libsr   pandas._libs.hashtabler   pandas.errorsr   r   pandas.util._decoratorsr   pandas.util._exceptionsr   pandas.core.dtypes.commonr   r   r   r   r   r   r   pandas.core.dtypes.dtypesr   r   pandas.core.dtypes.inferencer   pandas.core.dtypes.missingr   r   pandas.corer   pandas.core.applyr    r!   r"   r#   pandas.core.commoncorecommonr   pandas.core.framer$   pandas.core.groupbyr%   pandas.core.groupby.groupbyr&   r'   pandas.core.indexes.apir(   r)   r*   r+   pandas.core.seriesr,   pandas.core.sortingr-   pandas.core.util.numba_r.   pandas.plottingr/   r0   r1   pandas._typingr2   r3   r4   r5   r6   r7   r8   r=   r9   pandas.core.genericr:   r   r;   r`   r<   	dataclassr?   rf   r  ra  )r  s   @rK   <module>r     si   #  $       ! - / 4   5
 #  !   ' $  & / 3 1
   #+ Xc3h//	9 / ~& HJ/ J/  J/Z  |GFO | !|~;  Qwy) Q !Qh<rN   