3131import bigframes .dtypes
3232import bigframes .operations as ops
3333import bigframes .operations .aggregations as agg_ops
34+ import bigframes .operations .array_ops as arr_ops
3435import bigframes .operations .bool_ops as bool_ops
3536import bigframes .operations .comparison_ops as comp_ops
37+ import bigframes .operations .date_ops as date_ops
3638import bigframes .operations .datetime_ops as dt_ops
39+ import bigframes .operations .frequency_ops as freq_ops
3740import bigframes .operations .generic_ops as gen_ops
3841import bigframes .operations .json_ops as json_ops
3942import bigframes .operations .numeric_ops as num_ops
@@ -74,6 +77,20 @@ def decorator(func):
7477
7578
7679if polars_installed :
80+ _FREQ_MAPPING = {
81+ "Y" : "1y" ,
82+ "Q" : "1q" ,
83+ "M" : "1mo" ,
84+ "W" : "1w" ,
85+ "D" : "1d" ,
86+ "h" : "1h" ,
87+ "min" : "1m" ,
88+ "s" : "1s" ,
89+ "ms" : "1ms" ,
90+ "us" : "1us" ,
91+ "ns" : "1ns" ,
92+ }
93+
7794 _DTYPE_MAPPING = {
7895 # Direct mappings
7996 bigframes .dtypes .INT_DTYPE : pl .Int64 (),
@@ -329,11 +346,48 @@ def _(self, op: ops.ScalarOp, input: pl.Expr) -> pl.Expr:
329346 else :
330347 return pl .any_horizontal (* (input .str .ends_with (pat ) for pat in op .pat ))
331348
349+ @compile_op .register (freq_ops .FloorDtOp )
350+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
351+ assert isinstance (op , freq_ops .FloorDtOp )
352+ return input .dt .truncate (every = _FREQ_MAPPING [op .freq ])
353+
332354 @compile_op .register (dt_ops .StrftimeOp )
333355 def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
334356 assert isinstance (op , dt_ops .StrftimeOp )
335357 return input .dt .strftime (op .date_format )
336358
359+ @compile_op .register (date_ops .YearOp )
360+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
361+ return input .dt .year ()
362+
363+ @compile_op .register (date_ops .QuarterOp )
364+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
365+ return input .dt .quarter ()
366+
367+ @compile_op .register (date_ops .MonthOp )
368+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
369+ return input .dt .month ()
370+
371+ @compile_op .register (date_ops .DayOfWeekOp )
372+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
373+ return input .dt .weekday () - 1
374+
375+ @compile_op .register (date_ops .DayOp )
376+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
377+ return input .dt .day ()
378+
379+ @compile_op .register (date_ops .IsoYearOp )
380+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
381+ return input .dt .iso_year ()
382+
383+ @compile_op .register (date_ops .IsoWeekOp )
384+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
385+ return input .dt .week ()
386+
387+ @compile_op .register (date_ops .IsoDayOp )
388+ def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
389+ return input .dt .weekday ()
390+
337391 @compile_op .register (dt_ops .ParseDatetimeOp )
338392 def _ (self , op : ops .ScalarOp , input : pl .Expr ) -> pl .Expr :
339393 assert isinstance (op , dt_ops .ParseDatetimeOp )
@@ -353,6 +407,36 @@ def _(self, op: ops.ScalarOp, input: pl.Expr) -> pl.Expr:
353407 assert isinstance (op , json_ops .JSONDecode )
354408 return input .str .json_decode (_DTYPE_MAPPING [op .to_type ])
355409
410+ @compile_op .register (arr_ops .ToArrayOp )
411+ def _ (self , op : ops .ToArrayOp , * inputs : pl .Expr ) -> pl .Expr :
412+ return pl .concat_list (* inputs )
413+
414+ @compile_op .register (arr_ops .ArrayReduceOp )
415+ def _ (self , op : ops .ArrayReduceOp , input : pl .Expr ) -> pl .Expr :
416+ # TODO: Unify this with general aggregation compilation?
417+ if isinstance (op .aggregation , agg_ops .MinOp ):
418+ return input .list .min ()
419+ if isinstance (op .aggregation , agg_ops .MaxOp ):
420+ return input .list .max ()
421+ if isinstance (op .aggregation , agg_ops .SumOp ):
422+ return input .list .sum ()
423+ if isinstance (op .aggregation , agg_ops .MeanOp ):
424+ return input .list .mean ()
425+ if isinstance (op .aggregation , agg_ops .CountOp ):
426+ return input .list .len ()
427+ if isinstance (op .aggregation , agg_ops .StdOp ):
428+ return input .list .std ()
429+ if isinstance (op .aggregation , agg_ops .VarOp ):
430+ return input .list .var ()
431+ if isinstance (op .aggregation , agg_ops .AnyOp ):
432+ return input .list .any ()
433+ if isinstance (op .aggregation , agg_ops .AllOp ):
434+ return input .list .all ()
435+ else :
436+ raise NotImplementedError (
437+ f"Haven't implemented array aggregation: { op .aggregation } "
438+ )
439+
356440 @dataclasses .dataclass (frozen = True )
357441 class PolarsAggregateCompiler :
358442 scalar_compiler = PolarsExpressionCompiler ()
0 commit comments