polars_plan/dsl/
array.rs

1use polars_core::prelude::*;
2#[cfg(feature = "array_to_struct")]
3use polars_ops::chunked_array::array::{
4    ArrToStructNameGenerator, ToStruct, arr_default_struct_name_gen,
5};
6
7use crate::dsl::function_expr::ArrayFunction;
8use crate::prelude::*;
9
10/// Specialized expressions for [`Series`] of [`DataType::Array`].
11pub struct ArrayNameSpace(pub Expr);
12
13impl ArrayNameSpace {
14    pub fn len(self) -> Expr {
15        self.0
16            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Length))
17    }
18    /// Compute the maximum of the items in every subarray.
19    pub fn max(self) -> Expr {
20        self.0
21            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Max))
22    }
23
24    /// Compute the minimum of the items in every subarray.
25    pub fn min(self) -> Expr {
26        self.0
27            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Min))
28    }
29
30    /// Compute the sum of the items in every subarray.
31    pub fn sum(self) -> Expr {
32        self.0
33            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Sum))
34    }
35
36    /// Compute the std of the items in every subarray.
37    pub fn std(self, ddof: u8) -> Expr {
38        self.0
39            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Std(ddof)))
40    }
41
42    /// Compute the var of the items in every subarray.
43    pub fn var(self, ddof: u8) -> Expr {
44        self.0
45            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Var(ddof)))
46    }
47
48    /// Compute the median of the items in every subarray.
49    pub fn median(self) -> Expr {
50        self.0
51            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Median))
52    }
53
54    /// Keep only the unique values in every sub-array.
55    pub fn unique(self) -> Expr {
56        self.0
57            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Unique(false)))
58    }
59
60    /// Keep only the unique values in every sub-array.
61    pub fn unique_stable(self) -> Expr {
62        self.0
63            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Unique(true)))
64    }
65
66    pub fn n_unique(self) -> Expr {
67        self.0
68            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::NUnique))
69    }
70
71    /// Cast the Array column to List column with the same inner data type.
72    pub fn to_list(self) -> Expr {
73        self.0
74            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::ToList))
75    }
76
77    #[cfg(feature = "array_any_all")]
78    /// Evaluate whether all boolean values are true for every subarray.
79    pub fn all(self) -> Expr {
80        self.0
81            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::All))
82    }
83
84    #[cfg(feature = "array_any_all")]
85    /// Evaluate whether any boolean value is true for every subarray
86    pub fn any(self) -> Expr {
87        self.0
88            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Any))
89    }
90
91    pub fn sort(self, options: SortOptions) -> Expr {
92        self.0
93            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Sort(options)))
94    }
95
96    pub fn reverse(self) -> Expr {
97        self.0
98            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Reverse))
99    }
100
101    pub fn arg_min(self) -> Expr {
102        self.0
103            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::ArgMin))
104    }
105
106    pub fn arg_max(self) -> Expr {
107        self.0
108            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::ArgMax))
109    }
110
111    /// Get items in every sub-array by index.
112    pub fn get(self, index: Expr, null_on_oob: bool) -> Expr {
113        self.0.map_binary(
114            FunctionExpr::ArrayExpr(ArrayFunction::Get(null_on_oob)),
115            index,
116        )
117    }
118
119    /// Join all string items in a sub-array and place a separator between them.
120    /// # Error
121    /// Raise if inner type of array is not `DataType::String`.
122    pub fn join(self, separator: Expr, ignore_nulls: bool) -> Expr {
123        self.0.map_binary(
124            FunctionExpr::ArrayExpr(ArrayFunction::Join(ignore_nulls)),
125            separator,
126        )
127    }
128
129    #[cfg(feature = "is_in")]
130    /// Check if the sub-array contains specific element
131    pub fn contains<E: Into<Expr>>(self, other: E) -> Expr {
132        self.0.map_binary(
133            FunctionExpr::ArrayExpr(ArrayFunction::Contains),
134            other.into(),
135        )
136    }
137
138    #[cfg(feature = "array_count")]
139    /// Count how often the value produced by ``element`` occurs.
140    pub fn count_matches<E: Into<Expr>>(self, element: E) -> Expr {
141        self.0.map_binary(
142            FunctionExpr::ArrayExpr(ArrayFunction::CountMatches),
143            element.into(),
144        )
145    }
146
147    #[cfg(feature = "array_to_struct")]
148    pub fn to_struct(self, name_generator: Option<ArrToStructNameGenerator>) -> PolarsResult<Expr> {
149        Ok(self
150            .0
151            .map(
152                move |s| {
153                    s.array()?
154                        .to_struct(name_generator.clone())
155                        .map(|s| Some(s.into_column()))
156                },
157                GetOutput::map_dtype(move |dt: &DataType| {
158                    let DataType::Array(inner, width) = dt else {
159                        polars_bail!(InvalidOperation: "expected Array type, got: {}", dt)
160                    };
161
162                    let fields = (0..*width)
163                        .map(|i| {
164                            let name = arr_default_struct_name_gen(i);
165                            Field::new(name, inner.as_ref().clone())
166                        })
167                        .collect();
168                    Ok(DataType::Struct(fields))
169                }),
170            )
171            .with_fmt("arr.to_struct"))
172    }
173
174    /// Shift every sub-array.
175    pub fn shift(self, n: Expr) -> Expr {
176        self.0
177            .map_binary(FunctionExpr::ArrayExpr(ArrayFunction::Shift), n)
178    }
179    /// Returns a column with a separate row for every array element.
180    pub fn explode(self) -> Expr {
181        self.0
182            .map_unary(FunctionExpr::ArrayExpr(ArrayFunction::Explode {
183                skip_empty: false,
184            }))
185    }
186}