polars_ops/series/ops/
arg_min_max.rs1use polars_core::chunked_array::arg_min_max::{
2 arg_max_binary, arg_max_bool, arg_max_numeric, arg_max_str, arg_min_binary, arg_min_bool,
3 arg_min_numeric, arg_min_str,
4};
5#[cfg(feature = "dtype-categorical")]
6use polars_core::chunked_array::arg_min_max::{arg_max_cat, arg_min_cat};
7#[cfg(feature = "dtype-categorical")]
8use polars_core::with_match_categorical_physical_type;
9
10use super::*;
11
12pub trait ArgAgg {
14 fn arg_min(&self) -> Option<usize>;
16 fn arg_max(&self) -> Option<usize>;
18}
19
20macro_rules! with_match_physical_numeric_polars_type {(
21 $key_type:expr, | $_:tt $T:ident | $($body:tt)*
22) => ({
23 macro_rules! __with_ty__ {( $_ $T:ident ) => ( $($body)* )}
24 use DataType::*;
25 match $key_type {
26 #[cfg(feature = "dtype-i8")]
27 Int8 => __with_ty__! { Int8Type },
28 #[cfg(feature = "dtype-i16")]
29 Int16 => __with_ty__! { Int16Type },
30 Int32 => __with_ty__! { Int32Type },
31 Int64 => __with_ty__! { Int64Type },
32 #[cfg(feature = "dtype-i128")]
33 Int128 => __with_ty__! { Int128Type },
34 #[cfg(feature = "dtype-u8")]
35 UInt8 => __with_ty__! { UInt8Type },
36 #[cfg(feature = "dtype-u16")]
37 UInt16 => __with_ty__! { UInt16Type },
38 UInt32 => __with_ty__! { UInt32Type },
39 UInt64 => __with_ty__! { UInt64Type },
40 #[cfg(feature = "dtype-u128")]
41 UInt128 => __with_ty__! { UInt128Type },
42 #[cfg(feature = "dtype-f16")]
43 Float16 => __with_ty__! { Float16Type },
44 Float32 => __with_ty__! { Float32Type },
45 Float64 => __with_ty__! { Float64Type },
46 dt => panic!("not implemented for dtype {:?}", dt),
47 }
48})}
49
50impl ArgAgg for Series {
51 fn arg_min(&self) -> Option<usize> {
52 use DataType::*;
53 let phys_s = self.to_physical_repr();
54 match self.dtype() {
55 #[cfg(feature = "dtype-categorical")]
56 Categorical(cats, _) => {
57 with_match_categorical_physical_type!(cats.physical(), |$C| {
58 arg_min_cat(self.cat::<$C>().unwrap())
59 })
60 },
61 #[cfg(feature = "dtype-categorical")]
62 Enum(_, _) => phys_s.arg_min(),
63 #[cfg(feature = "dtype-decimal")]
64 Decimal(_, _) => phys_s.arg_min(),
65 Date | Datetime(_, _) | Duration(_) | Time => phys_s.arg_min(),
66 String => arg_min_str(self.str().unwrap()),
67 Binary => arg_min_binary(self.binary().unwrap()),
68 Boolean => arg_min_bool(self.bool().unwrap()),
69 dt if dt.is_primitive_numeric() => {
70 with_match_physical_numeric_polars_type!(phys_s.dtype(), |$T| {
71 let ca: &ChunkedArray<$T> = phys_s.as_ref().as_ref().as_ref();
72 arg_min_numeric(ca)
73 })
74 },
75 _ => None,
76 }
77 }
78
79 fn arg_max(&self) -> Option<usize> {
80 use DataType::*;
81 let phys_s = self.to_physical_repr();
82 match self.dtype() {
83 #[cfg(feature = "dtype-categorical")]
84 Categorical(cats, _) => {
85 with_match_categorical_physical_type!(cats.physical(), |$C| {
86 arg_max_cat(self.cat::<$C>().unwrap())
87 })
88 },
89 #[cfg(feature = "dtype-categorical")]
90 Enum(_, _) => phys_s.arg_max(),
91 #[cfg(feature = "dtype-decimal")]
92 Decimal(_, _) => phys_s.arg_max(),
93 Date | Datetime(_, _) | Duration(_) | Time => phys_s.arg_max(),
94 String => arg_max_str(self.str().unwrap()),
95 Binary => arg_max_binary(self.binary().unwrap()),
96 Boolean => arg_max_bool(self.bool().unwrap()),
97 dt if dt.is_primitive_numeric() => {
98 with_match_physical_numeric_polars_type!(phys_s.dtype(), |$T| {
99 let ca: &ChunkedArray<$T> = phys_s.as_ref().as_ref().as_ref();
100 arg_max_numeric(ca)
101 })
102 },
103 _ => None,
104 }
105 }
106}