Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-plan/src/plans/aexpr/builder.rs
8422 views
1
use polars_core::chunked_array::cast::CastOptions;
2
use polars_core::prelude::{DataType, ExplodeOptions, SortMultipleOptions, SortOptions};
3
use polars_core::scalar::Scalar;
4
use polars_utils::IdxSize;
5
use polars_utils::arena::{Arena, Node};
6
use polars_utils::pl_str::PlSmallStr;
7
8
use super::{AExpr, IRAggExpr, IRBooleanFunction, IRFunctionExpr, RowEncodingVariant};
9
use crate::dsl::Operator;
10
use crate::plans::{ExprIR, LiteralValue, OutputName};
11
12
#[derive(Clone, Copy)]
13
pub struct AExprBuilder {
14
node: Node,
15
}
16
17
impl AExprBuilder {
18
pub fn new_from_node(node: Node) -> Self {
19
Self { node }
20
}
21
22
pub fn new_from_aexpr(expr: AExpr, arena: &mut Arena<AExpr>) -> Self {
23
Self::new_from_node(arena.add(expr))
24
}
25
26
pub fn lit(lit: LiteralValue, arena: &mut Arena<AExpr>) -> Self {
27
Self::new_from_aexpr(AExpr::Literal(lit), arena)
28
}
29
30
pub fn lit_scalar(scalar: Scalar, arena: &mut Arena<AExpr>) -> Self {
31
Self::lit(LiteralValue::Scalar(scalar), arena)
32
}
33
34
pub fn col(name: impl Into<PlSmallStr>, arena: &mut Arena<AExpr>) -> Self {
35
Self::new_from_aexpr(AExpr::Column(name.into()), arena)
36
}
37
38
pub fn dataframe_length(arena: &mut Arena<AExpr>) -> Self {
39
Self::new_from_aexpr(AExpr::Len, arena)
40
}
41
42
pub fn function(
43
input: Vec<ExprIR>,
44
function: IRFunctionExpr,
45
arena: &mut Arena<AExpr>,
46
) -> Self {
47
let options = function.function_options();
48
Self::new_from_aexpr(
49
AExpr::Function {
50
input,
51
function,
52
options,
53
},
54
arena,
55
)
56
}
57
58
pub fn map_as_expr_ir<F: Fn(ExprIR, &mut Arena<AExpr>) -> AExpr>(
59
self,
60
mapper: F,
61
arena: &mut Arena<AExpr>,
62
) -> Self {
63
let eir = ExprIR::from_node(self.node, arena);
64
65
let ae = mapper(eir, arena);
66
let node = arena.add(ae);
67
Self { node }
68
}
69
70
pub fn row_encode(
71
exprs: Vec<ExprIR>,
72
dtypes: Vec<DataType>,
73
variant: RowEncodingVariant,
74
arena: &mut Arena<AExpr>,
75
) -> Self {
76
Self::function(exprs, IRFunctionExpr::RowEncode(dtypes, variant), arena)
77
}
78
79
pub fn cast(self, dtype: DataType, arena: &mut Arena<AExpr>) -> Self {
80
Self {
81
node: arena.add(AExpr::Cast {
82
expr: self.node,
83
dtype,
84
options: CastOptions::Strict,
85
}),
86
}
87
}
88
89
pub fn binary_op(
90
self,
91
other: impl IntoAExprBuilder,
92
op: Operator,
93
arena: &mut Arena<AExpr>,
94
) -> Self {
95
Self {
96
node: arena.add(AExpr::BinaryExpr {
97
left: self.node,
98
op,
99
right: other.into_aexpr_builder().node,
100
}),
101
}
102
}
103
104
pub fn agg(agg: IRAggExpr, arena: &mut Arena<AExpr>) -> Self {
105
Self::new_from_aexpr(AExpr::Agg(agg), arena)
106
}
107
108
pub fn first(self, arena: &mut Arena<AExpr>) -> Self {
109
Self::agg(IRAggExpr::First(self.node()), arena)
110
}
111
112
pub fn first_non_null(self, arena: &mut Arena<AExpr>) -> Self {
113
Self::agg(IRAggExpr::FirstNonNull(self.node()), arena)
114
}
115
116
pub fn last(self, arena: &mut Arena<AExpr>) -> Self {
117
Self::agg(IRAggExpr::Last(self.node()), arena)
118
}
119
120
pub fn last_non_null(self, arena: &mut Arena<AExpr>) -> Self {
121
Self::agg(IRAggExpr::LastNonNull(self.node()), arena)
122
}
123
124
pub fn min(self, arena: &mut Arena<AExpr>) -> Self {
125
Self::agg(
126
IRAggExpr::Min {
127
input: self.node(),
128
propagate_nans: false,
129
},
130
arena,
131
)
132
}
133
134
pub fn max(self, arena: &mut Arena<AExpr>) -> Self {
135
Self::agg(
136
IRAggExpr::Max {
137
input: self.node(),
138
propagate_nans: false,
139
},
140
arena,
141
)
142
}
143
144
pub fn nan_min(self, arena: &mut Arena<AExpr>) -> Self {
145
Self::agg(
146
IRAggExpr::Min {
147
input: self.node(),
148
propagate_nans: true,
149
},
150
arena,
151
)
152
}
153
154
pub fn nan_max(self, arena: &mut Arena<AExpr>) -> Self {
155
Self::agg(
156
IRAggExpr::Max {
157
input: self.node(),
158
propagate_nans: true,
159
},
160
arena,
161
)
162
}
163
164
pub fn min_by(self, by: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
165
let by = by.into_aexpr_builder().expr_ir_retain_name(arena);
166
Self::function(
167
vec![self.expr_ir_retain_name(arena), by],
168
IRFunctionExpr::MinBy,
169
arena,
170
)
171
}
172
173
pub fn max_by(self, by: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
174
let by = by.into_aexpr_builder().expr_ir_retain_name(arena);
175
Self::function(
176
vec![self.expr_ir_retain_name(arena), by],
177
IRFunctionExpr::MaxBy,
178
arena,
179
)
180
}
181
182
pub fn sum(self, arena: &mut Arena<AExpr>) -> Self {
183
Self::agg(IRAggExpr::Sum(self.node()), arena)
184
}
185
186
pub fn len(self, arena: &mut Arena<AExpr>) -> Self {
187
Self::agg(
188
IRAggExpr::Count {
189
input: self.node(),
190
include_nulls: true,
191
},
192
arena,
193
)
194
}
195
196
pub fn any_horizontal(exprs: Vec<ExprIR>, arena: &mut Arena<AExpr>) -> Self {
197
Self::function(
198
exprs,
199
IRFunctionExpr::Boolean(IRBooleanFunction::AnyHorizontal),
200
arena,
201
)
202
}
203
204
pub fn all_horizontal(exprs: Vec<ExprIR>, arena: &mut Arena<AExpr>) -> Self {
205
Self::function(
206
exprs,
207
IRFunctionExpr::Boolean(IRBooleanFunction::AllHorizontal),
208
arena,
209
)
210
}
211
212
pub fn count(self, arena: &mut Arena<AExpr>) -> Self {
213
Self::agg(
214
IRAggExpr::Count {
215
input: self.node(),
216
include_nulls: false,
217
},
218
arena,
219
)
220
}
221
222
pub fn count_opt_nulls(self, include_nulls: bool, arena: &mut Arena<AExpr>) -> Self {
223
Self::agg(
224
IRAggExpr::Count {
225
input: self.node(),
226
include_nulls,
227
},
228
arena,
229
)
230
}
231
232
pub fn explode(self, arena: &mut Arena<AExpr>, options: ExplodeOptions) -> Self {
233
Self::new_from_aexpr(
234
AExpr::Explode {
235
expr: self.node(),
236
options,
237
},
238
arena,
239
)
240
}
241
242
pub fn sort(self, options: SortOptions, arena: &mut Arena<AExpr>) -> Self {
243
Self::new_from_aexpr(
244
AExpr::Sort {
245
expr: self.node(),
246
options,
247
},
248
arena,
249
)
250
}
251
252
pub fn sort_by(
253
self,
254
by: Vec<Node>,
255
options: SortMultipleOptions,
256
arena: &mut Arena<AExpr>,
257
) -> Self {
258
Self::new_from_aexpr(
259
AExpr::SortBy {
260
expr: self.node(),
261
by,
262
sort_options: options,
263
},
264
arena,
265
)
266
}
267
268
pub fn filter(self, by: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
269
Self::new_from_aexpr(
270
AExpr::Filter {
271
input: self.node(),
272
by: by.into_aexpr_builder().node(),
273
},
274
arena,
275
)
276
}
277
278
pub fn when_then_otherwise(
279
when: impl IntoAExprBuilder,
280
then: impl IntoAExprBuilder,
281
otherwise: impl IntoAExprBuilder,
282
arena: &mut Arena<AExpr>,
283
) -> Self {
284
when.into_aexpr_builder().ternary(then, otherwise, arena)
285
}
286
287
pub fn ternary(
288
self,
289
truthy: impl IntoAExprBuilder,
290
falsy: impl IntoAExprBuilder,
291
arena: &mut Arena<AExpr>,
292
) -> Self {
293
Self::new_from_aexpr(
294
AExpr::Ternary {
295
predicate: self.into_aexpr_builder().node(),
296
truthy: truthy.into_aexpr_builder().node(),
297
falsy: falsy.into_aexpr_builder().node(),
298
},
299
arena,
300
)
301
}
302
303
pub fn shift(self, periods: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
304
Self::function(
305
vec![
306
self.expr_ir_unnamed(),
307
periods.into_aexpr_builder().expr_ir_unnamed(),
308
],
309
IRFunctionExpr::Shift,
310
arena,
311
)
312
}
313
314
pub fn slice(
315
self,
316
offset: impl IntoAExprBuilder,
317
length: impl IntoAExprBuilder,
318
arena: &mut Arena<AExpr>,
319
) -> Self {
320
Self::new_from_aexpr(
321
AExpr::Slice {
322
input: self.into_aexpr_builder().node(),
323
offset: offset.into_aexpr_builder().node(),
324
length: length.into_aexpr_builder().node(),
325
},
326
arena,
327
)
328
}
329
330
#[cfg(feature = "is_in")]
331
pub fn is_in(
332
self,
333
other: impl IntoAExprBuilder,
334
nulls_equal: bool,
335
arena: &mut Arena<AExpr>,
336
) -> Self {
337
Self::function(
338
vec![
339
self.expr_ir_unnamed(),
340
other.into_aexpr_builder().expr_ir_unnamed(),
341
],
342
IRFunctionExpr::Boolean(IRBooleanFunction::IsIn { nulls_equal }),
343
arena,
344
)
345
}
346
347
pub fn to_physical(self, arena: &mut Arena<AExpr>) -> Self {
348
Self::function(
349
vec![self.expr_ir_unnamed()],
350
IRFunctionExpr::ToPhysical,
351
arena,
352
)
353
}
354
355
#[cfg(feature = "abs")]
356
pub fn abs(self, arena: &mut Arena<AExpr>) -> Self {
357
Self::function(vec![self.expr_ir_unnamed()], IRFunctionExpr::Abs, arena)
358
}
359
360
pub fn negate(self, arena: &mut Arena<AExpr>) -> Self {
361
Self::function(vec![self.expr_ir_unnamed()], IRFunctionExpr::Negate, arena)
362
}
363
364
pub fn not(self, arena: &mut Arena<AExpr>) -> Self {
365
Self::function(
366
vec![self.expr_ir_unnamed()],
367
IRFunctionExpr::Boolean(IRBooleanFunction::Not),
368
arena,
369
)
370
}
371
372
pub fn null_count(self, arena: &mut Arena<AExpr>) -> Self {
373
Self::function(
374
vec![self.expr_ir_unnamed()],
375
IRFunctionExpr::NullCount,
376
arena,
377
)
378
}
379
380
pub fn is_null(self, arena: &mut Arena<AExpr>) -> Self {
381
Self::function(
382
vec![self.expr_ir_unnamed()],
383
IRFunctionExpr::Boolean(IRBooleanFunction::IsNull),
384
arena,
385
)
386
}
387
388
pub fn is_not_null(self, arena: &mut Arena<AExpr>) -> Self {
389
Self::function(
390
vec![self.expr_ir_unnamed()],
391
IRFunctionExpr::Boolean(IRBooleanFunction::IsNotNull),
392
arena,
393
)
394
}
395
396
pub fn is_nan(self, arena: &mut Arena<AExpr>) -> Self {
397
Self::function(
398
vec![self.expr_ir_unnamed()],
399
IRFunctionExpr::Boolean(IRBooleanFunction::IsNan),
400
arena,
401
)
402
}
403
404
pub fn is_not_nan(self, arena: &mut Arena<AExpr>) -> Self {
405
Self::function(
406
vec![self.expr_ir_unnamed()],
407
IRFunctionExpr::Boolean(IRBooleanFunction::IsNotNan),
408
arena,
409
)
410
}
411
412
pub fn has_no_nulls(self, arena: &mut Arena<AExpr>) -> Self {
413
let nc = self.null_count(arena);
414
let idx_zero = Self::lit_scalar(Scalar::from(0 as IdxSize), arena);
415
nc.eq(idx_zero, arena)
416
}
417
418
pub fn has_nulls(self, arena: &mut Arena<AExpr>) -> Self {
419
let nc = self.null_count(arena);
420
let idx_zero = Self::lit_scalar(Scalar::from(0 as IdxSize), arena);
421
nc.gt(idx_zero, arena)
422
}
423
424
pub fn drop_nulls(self, arena: &mut Arena<AExpr>) -> Self {
425
Self::function(
426
vec![self.expr_ir_retain_name(arena)],
427
IRFunctionExpr::DropNulls,
428
arena,
429
)
430
}
431
432
pub fn drop_nans(self, arena: &mut Arena<AExpr>) -> Self {
433
Self::function(
434
vec![self.expr_ir_retain_name(arena)],
435
IRFunctionExpr::DropNans,
436
arena,
437
)
438
}
439
440
pub fn eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
441
self.binary_op(other, Operator::Eq, arena)
442
}
443
444
pub fn eq_validity(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
445
self.binary_op(other, Operator::EqValidity, arena)
446
}
447
448
pub fn not_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
449
self.binary_op(other, Operator::NotEq, arena)
450
}
451
452
pub fn not_eq_validity(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
453
self.binary_op(other, Operator::NotEqValidity, arena)
454
}
455
456
pub fn lt(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
457
self.binary_op(other, Operator::Lt, arena)
458
}
459
460
pub fn lt_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
461
self.binary_op(other, Operator::LtEq, arena)
462
}
463
464
pub fn gt(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
465
self.binary_op(other, Operator::Gt, arena)
466
}
467
468
pub fn gt_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
469
self.binary_op(other, Operator::GtEq, arena)
470
}
471
472
pub fn plus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
473
self.binary_op(other, Operator::Plus, arena)
474
}
475
476
pub fn minus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
477
self.binary_op(other, Operator::Minus, arena)
478
}
479
480
pub fn multiply(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
481
self.binary_op(other, Operator::Multiply, arena)
482
}
483
484
pub fn divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
485
self.binary_op(other, Operator::RustDivide, arena)
486
}
487
488
pub fn true_divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
489
self.binary_op(other, Operator::TrueDivide, arena)
490
}
491
492
pub fn floor_divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
493
self.binary_op(other, Operator::FloorDivide, arena)
494
}
495
496
pub fn modulus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
497
self.binary_op(other, Operator::Modulus, arena)
498
}
499
500
pub fn and(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
501
self.binary_op(other, Operator::And, arena)
502
}
503
504
pub fn or(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
505
self.binary_op(other, Operator::Or, arena)
506
}
507
508
pub fn xor(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
509
self.binary_op(other, Operator::Xor, arena)
510
}
511
512
pub fn logical_and(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
513
self.binary_op(other, Operator::LogicalAnd, arena)
514
}
515
516
pub fn logical_or(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
517
self.binary_op(other, Operator::LogicalOr, arena)
518
}
519
520
pub fn expr_ir(self, name: impl Into<PlSmallStr>) -> ExprIR {
521
ExprIR::new(self.node(), OutputName::Alias(name.into()))
522
}
523
524
pub fn expr_ir_retain_name(self, arena: &Arena<AExpr>) -> ExprIR {
525
ExprIR::from_node(self.node(), arena)
526
}
527
528
pub fn expr_ir_unnamed(self) -> ExprIR {
529
self.expr_ir(PlSmallStr::EMPTY)
530
}
531
532
pub fn node(self) -> Node {
533
self.node
534
}
535
}
536
537
pub trait IntoAExprBuilder {
538
fn into_aexpr_builder(self) -> AExprBuilder;
539
}
540
541
impl IntoAExprBuilder for Node {
542
fn into_aexpr_builder(self) -> AExprBuilder {
543
AExprBuilder { node: self }
544
}
545
}
546
547
impl IntoAExprBuilder for AExprBuilder {
548
fn into_aexpr_builder(self) -> AExprBuilder {
549
self
550
}
551
}
552
553