polars_python/series/
aggregation.rs1use DataType::*;
2use polars::prelude::*;
3use pyo3::prelude::*;
4
5use super::PySeries;
6use crate::conversion::Wrap;
7use crate::utils::EnterPolarsExt;
8
9fn scalar_to_py(scalar: PyResult<Scalar>, py: Python<'_>) -> PyResult<Bound<'_, PyAny>> {
10 Wrap(scalar?.as_any_value()).into_pyobject(py)
11}
12
13#[pymethods]
14impl PySeries {
15 fn any(&self, py: Python<'_>, ignore_nulls: bool) -> PyResult<Option<bool>> {
16 py.enter_polars(|| {
17 let s = self.series.read();
18 let s = s.bool()?;
19 PolarsResult::Ok(if ignore_nulls {
20 Some(s.any())
21 } else {
22 s.any_kleene()
23 })
24 })
25 }
26
27 fn all(&self, py: Python<'_>, ignore_nulls: bool) -> PyResult<Option<bool>> {
28 py.enter_polars(|| {
29 let s = self.series.read();
30 let s = s.bool()?;
31 PolarsResult::Ok(if ignore_nulls {
32 Some(s.all())
33 } else {
34 s.all_kleene()
35 })
36 })
37 }
38
39 fn arg_max(&self, py: Python) -> PyResult<Option<usize>> {
40 py.enter_polars_ok(|| self.series.read().arg_max())
41 }
42
43 fn arg_min(&self, py: Python) -> PyResult<Option<usize>> {
44 py.enter_polars_ok(|| self.series.read().arg_min())
45 }
46
47 fn min<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
48 scalar_to_py(py.enter_polars(|| self.series.read().min_reduce()), py)
49 }
50
51 fn max<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
52 scalar_to_py(py.enter_polars(|| self.series.read().max_reduce()), py)
53 }
54
55 fn mean<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
56 let s = self.series.read();
57 match s.dtype() {
58 Boolean => scalar_to_py(
59 py.enter_polars_ok(|| s.cast(&DataType::UInt8).unwrap().mean_reduce()),
60 py,
61 ),
62 dt if dt.is_temporal() => scalar_to_py(py.enter_polars_ok(|| s.mean_reduce()), py),
64 _ => Ok(s.mean().into_pyobject(py)?),
65 }
66 }
67
68 fn median<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
69 let s = self.series.read();
70 match s.dtype() {
71 Boolean => scalar_to_py(
72 py.enter_polars(|| s.cast(&DataType::UInt8).unwrap().median_reduce()),
73 py,
74 ),
75 dt if dt.is_temporal() => scalar_to_py(py.enter_polars(|| s.median_reduce()), py),
77 _ => Ok(s.median().into_pyobject(py)?),
78 }
79 }
80
81 fn product<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
82 scalar_to_py(py.enter_polars(|| self.series.read().product()), py)
83 }
84
85 fn quantile<'py>(
86 &self,
87 py: Python<'py>,
88 quantile: f64,
89 interpolation: Wrap<QuantileMethod>,
90 ) -> PyResult<Bound<'py, PyAny>> {
91 scalar_to_py(
92 py.enter_polars(|| {
93 self.series
94 .read()
95 .quantile_reduce(quantile, interpolation.0)
96 }),
97 py,
98 )
99 }
100
101 fn std<'py>(&self, py: Python<'py>, ddof: u8) -> PyResult<Bound<'py, PyAny>> {
102 scalar_to_py(py.enter_polars(|| self.series.read().std_reduce(ddof)), py)
103 }
104
105 fn var<'py>(&self, py: Python<'py>, ddof: u8) -> PyResult<Bound<'py, PyAny>> {
106 scalar_to_py(py.enter_polars(|| self.series.read().var_reduce(ddof)), py)
107 }
108
109 fn sum<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
110 scalar_to_py(py.enter_polars(|| self.series.read().sum_reduce()), py)
111 }
112
113 fn first<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
114 scalar_to_py(py.enter_polars_ok(|| self.series.read().first()), py)
115 }
116
117 fn last<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
118 scalar_to_py(py.enter_polars_ok(|| self.series.read().last()), py)
119 }
120
121 #[cfg(feature = "approx_unique")]
122 fn approx_n_unique(&self, py: Python) -> PyResult<IdxSize> {
123 py.enter_polars(|| self.series.read().approx_n_unique())
124 }
125
126 #[cfg(feature = "bitwise")]
127 fn bitwise_and<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
128 scalar_to_py(py.enter_polars(|| self.series.read().and_reduce()), py)
129 }
130
131 #[cfg(feature = "bitwise")]
132 fn bitwise_or<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
133 scalar_to_py(py.enter_polars(|| self.series.read().or_reduce()), py)
134 }
135
136 #[cfg(feature = "bitwise")]
137 fn bitwise_xor<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
138 scalar_to_py(py.enter_polars(|| self.series.read().xor_reduce()), py)
139 }
140}