L i ddlmZddlmZddlmZmZmZmZm Z m Z ddl m Z m Z mZmZmZmZmZmZmZmZddlmZmZerddlmZmZmZmZddlmZgdZ e d d d Z! dd Z"Gdde eefZ#Gdde#e efe e efZ$Gdde#eefe eefZ%Gdde%eefe eee!fZ&Gdde&e ee!fe$e efe e ee!fZ'y)) annotations)chain) TYPE_CHECKINGAnyCallableClassVarProtocolTypeVar) CompliantDataFrameTCompliantDataFrameT_coCompliantExprT_contraCompliantFrameTCompliantFrameT_coDepthTrackingExprAnyDepthTrackingExprT_contraEagerExprT_contraImplExprT_contraNarwhalsAggregation)is_sequence_of zip_strict)IterableIteratorMappingSequence)ImplExpr)CompliantGroupByDepthTrackingGroupBy EagerGroupByNativeAggregationT_cozstr | Callable[..., Any]T)bound covariantcVfd|D}ttj|S)Nc3@K|]}|jywN)_evaluate_aliases).0exprframes b/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/narwhals/_compliant/group_by.py z$_evaluate_aliases..$s :D$  ' :s)listr from_iterable)r(exprsits` r)r%r%!s% ;E :B ##B' ((cJeZdZUded<eddZ ddZd dZy) rr_compliant_framec|jSr$)r1selfs r) compliantzCompliantGroupBy.compliant+s$$$r/cyr$)r4compliant_framekeysdrop_null_keyss r)__init__zCompliantGroupBy.__init__/sr/cyr$r7)r4r-s r)aggzCompliantGroupBy.agg8r/N)returnr)r8rr9z/Sequence[CompliantExprT_contra] | Sequence[str]r:boolr?None)r-r r?r)__name__ __module__ __qualname____annotations__propertyr5r;r=r7r/r)rr(sK %%+>   Lr/rceZdZddZy)DataFrameGroupBycyr$r7r3s r)__iter__zDataFrameGroupBy.__iter__?r>r/N)r?z,Iterator[tuple[Any, CompliantDataFrameT_co]])rBrCrDrJr7r/r)rHrH;sLr/rHc>eZdZ ddZe ddZy)ParseKeysGroupByct|trt|}|||jfS|j ||S)N)r9)rstrr+copy_parse_expr_keys)r4r8r9keys_strs r) _parse_keyszParseKeysGroupBy._parse_keysFs@ $ $DzH"Hhmmo= =$$_4$@@r/c  td|jDdz d fd }|Dcgc]}|j|}}t||Dcgc]b\}}|jx}r5|j j r|jj|n|j||dd}}}|j|t||ttj|fScc}wcc}}w)a#Parses key expressions to set up `.agg` operation with correct information. Since keys are expressions, it's possible to alias any such key to match other dataframe column names. In order to match polars behavior and not overwrite columns when evaluating keys: - We evaluate what the output key names should be, in order to remap temporary column names to the expected ones, and to exclude those from unnamed expressions in `.agg(...)` context (see https://github.com/narwhals-dev/narwhals/pull/2325#issuecomment-2800004520) - Create temporary names for evaluated key expressions that are guaranteed to have no overlap with any existing column name. - Add these temporary columns to the compliant dataframe. c3DK|]}tt|ywr$)lenrN)r&cs r)r*z4ParseKeysGroupBy._parse_expr_keys..bsKac#a&kKs cNt|}d|ddt|z dz zS)N__tmp)rNrU)keykey_strtmp_name_lengths r)_temporary_namez:ParseKeysGroupBy._parse_expr_keys.._temporary_nameds3#hGwitC?S\+IA+M$N#OP Pr/r)r\rNr?rN)maxcolumnsr%r _metadataexpansion_kindis_multi_outputnamemapalias with_columnsr+rr,) r8r9r_r' keys_aliasesr\ new_namesmetadata safe_keysr^s @r)rPz!ParseKeysGroupBy._parse_expr_keysPs$K?3J3JKKaO Q MQQD..?Q Q#-T<"@  Y MM))x/F/F/V/V/X HHLL )?9Q<89 :   )O ( () 4 oy 9 $$\2 3  R s C6A'C;N)r8rr9z*Sequence[ImplExprT_contra] | Sequence[str]r?,tuple[CompliantFrameT, list[str], list[str]])r8rr9zSequence[ImplExprT_contra]r?rm)rBrCrDrR staticmethodrPr7r/r)rLrLBsSA(A9A 6 A% (% 0J% 5% % r/rLcveZdZUdZded< d dZed dZe d dZed dZ eddZ y )rzf`CompliantGroupBy` variant, deals with `Eager` and other backends that utilize `CompliantExpr._depth`.z+ClassVar[Mapping[NarwhalsAggregation, Any]] _REMAP_AGGSc|D]R}|j|r|jjjj }d|d}t |y)NzsNon-trivial complex aggregation found. Hint: you were probably trying to apply a non-elementary aggregation with az table. Please rewrite your query such that group-by aggregations are elementary. For example, instead of: df.group_by('a').agg(nw.col('b').round(2).mean()) use: df.with_columns(nw.col('b').round(2)).group_by('a').agg(nw.col('b').mean()) ) _is_simpler5_implementationrelower ValueError)r4r-r'remsgs r)_ensure_all_simplez'DepthTrackingGroupBy._ensure_all_simplesc &D??4(~~55::@@Bbhjj!o% &r/c`|jxr|j||jvS)zNReturn `True` is we can efficiently use `expr` in a native `group_by` context.)_is_elementary _leaf_namerpclsr's r)rrzDepthTrackingGroupBy._is_simples*""$P)=)PPr/c:|jj||S)zReplace `name`, with some native representation. Arguments: name: Name of a `nw.Expr` aggregation method. )rpget)r|res r)_remap_expr_namez%DepthTrackingGroupBy._remap_expr_names""4..r/c\t|jjjS)z=Return the last function name in the chain defined by `expr`.)nextrbop_nodes_reversedrer{s r)rzzDepthTrackingGroupBy._leaf_names"DNN4467<<>>r/N)r-z#Sequence[DepthTrackingExprT_contra]r?rA)r'rr?r@)reNarwhalsAggregation | Anyr?r)r'rr?r)r'rr?zdict[str, Any]) rBrCrD__doc__rErw classmethodrrrrzrr7r/r)rryszq<< & QQ/,/ //==??r/rc eZdZy)rN)rBrCrDr7r/r)rrsr/rN)r(rr-z(Iterable[ImplExpr[CompliantFrameT, Any]]r?z list[str])( __future__r itertoolsrtypingrrrrr r narwhals._compliant.typingr r r rrrrrrrnarwhals._utilsrrcollections.abcrrrrnarwhals._compliant.exprr__all__rr%rrHrLrrr7r/r)rs;"LL   7EE1 G#= ) )#K))Lx 24I IJL&L+-BBC #%: :;L4 _&667 _. ./4 n5?_&??@ _79N NO5?p,.?AVVW(*;;< "35J JKr/