Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-ops/src/chunked_array/array/min_max.rs
6939 views
1
use arrow::array::{Array, PrimitiveArray};
2
use polars_compute::min_max::MinMaxKernel;
3
use polars_core::prelude::*;
4
use polars_core::with_match_physical_numeric_polars_type;
5
6
fn array_agg<T, S, F1, F2>(
7
values: &PrimitiveArray<T>,
8
width: usize,
9
slice_agg: F1,
10
arr_agg: F2,
11
) -> PrimitiveArray<S>
12
where
13
T: NumericNative,
14
S: NumericNative,
15
F1: Fn(&[T]) -> Option<S>,
16
F2: Fn(&PrimitiveArray<T>) -> Option<S>,
17
{
18
if values.null_count() == 0 {
19
let values = values.values().as_slice();
20
values
21
.chunks_exact(width)
22
.map(|sl| slice_agg(sl).unwrap())
23
.collect_arr()
24
} else {
25
(0..values.len())
26
.step_by(width)
27
.map(|start| {
28
// SAFETY: This value array from a FixedSizeListArray,
29
// we can ensure that `start + width` will not out out range
30
let sliced = unsafe { values.clone().sliced_unchecked(start, width) };
31
arr_agg(&sliced)
32
})
33
.collect_arr()
34
}
35
}
36
37
pub(super) enum AggType {
38
Min,
39
Max,
40
}
41
42
fn agg_min<T>(values: &PrimitiveArray<T>, width: usize) -> PrimitiveArray<T>
43
where
44
T: NumericNative,
45
PrimitiveArray<T>: for<'a> MinMaxKernel<Scalar<'a> = T>,
46
[T]: for<'a> MinMaxKernel<Scalar<'a> = T>,
47
{
48
array_agg(
49
values,
50
width,
51
MinMaxKernel::min_ignore_nan_kernel,
52
MinMaxKernel::min_ignore_nan_kernel,
53
)
54
}
55
56
fn agg_max<T>(values: &PrimitiveArray<T>, width: usize) -> PrimitiveArray<T>
57
where
58
T: NumericNative,
59
PrimitiveArray<T>: for<'a> MinMaxKernel<Scalar<'a> = T>,
60
[T]: for<'a> MinMaxKernel<Scalar<'a> = T>,
61
{
62
array_agg(
63
values,
64
width,
65
MinMaxKernel::max_ignore_nan_kernel,
66
MinMaxKernel::max_ignore_nan_kernel,
67
)
68
}
69
70
pub(super) fn array_dispatch(
71
name: PlSmallStr,
72
values: &Series,
73
width: usize,
74
agg_type: AggType,
75
) -> Series {
76
let chunks: Vec<ArrayRef> = with_match_physical_numeric_polars_type!(values.dtype(), |$T| {
77
let ca: &ChunkedArray<$T> = values.as_ref().as_ref().as_ref();
78
ca.downcast_iter().map(|arr| {
79
match agg_type {
80
AggType::Min => Box::new(agg_min(arr, width)) as ArrayRef,
81
AggType::Max => Box::new(agg_max(arr, width)) as ArrayRef,
82
}
83
}).collect()
84
});
85
Series::try_from((name, chunks)).unwrap()
86
}
87
88