use DataType::*;
use polars::prelude::*;
use pyo3::prelude::*;
use super::PySeries;
use crate::conversion::Wrap;
use crate::utils::EnterPolarsExt;
fn scalar_to_py(scalar: PyResult<Scalar>, py: Python<'_>) -> PyResult<Bound<'_, PyAny>> {
Wrap(scalar?.as_any_value()).into_pyobject(py)
}
#[pymethods]
impl PySeries {
fn any(&self, py: Python<'_>, ignore_nulls: bool) -> PyResult<Option<bool>> {
py.enter_polars(|| {
let s = self.series.read();
let s = s.bool()?;
PolarsResult::Ok(if ignore_nulls {
Some(s.any())
} else {
s.any_kleene()
})
})
}
fn all(&self, py: Python<'_>, ignore_nulls: bool) -> PyResult<Option<bool>> {
py.enter_polars(|| {
let s = self.series.read();
let s = s.bool()?;
PolarsResult::Ok(if ignore_nulls {
Some(s.all())
} else {
s.all_kleene()
})
})
}
fn arg_max(&self, py: Python) -> PyResult<Option<usize>> {
py.enter_polars_ok(|| self.series.read().arg_max())
}
fn arg_min(&self, py: Python) -> PyResult<Option<usize>> {
py.enter_polars_ok(|| self.series.read().arg_min())
}
fn min<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().min_reduce()), py)
}
fn max<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().max_reduce()), py)
}
fn mean<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let s = self.series.read();
match s.dtype() {
Boolean => scalar_to_py(
py.enter_polars(|| s.cast(&DataType::UInt8).unwrap().mean_reduce()),
py,
),
dt if dt.is_temporal() => scalar_to_py(py.enter_polars(|| s.mean_reduce()), py),
_ => Ok(s.mean().into_pyobject(py)?),
}
}
fn median<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let s = self.series.read();
match s.dtype() {
Boolean => scalar_to_py(
py.enter_polars(|| s.cast(&DataType::UInt8).unwrap().median_reduce()),
py,
),
dt if dt.is_temporal() => scalar_to_py(py.enter_polars(|| s.median_reduce()), py),
_ => Ok(s.median().into_pyobject(py)?),
}
}
fn product<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().product()), py)
}
fn quantile<'py>(
&self,
py: Python<'py>,
quantile: Bound<'py, PyAny>,
interpolation: Wrap<QuantileMethod>,
) -> PyResult<Bound<'py, PyAny>> {
if let Ok(q_float) = quantile.extract::<f64>() {
scalar_to_py(
py.enter_polars(|| self.series.read().quantile_reduce(q_float, interpolation.0)),
py,
)
} else if let Ok(q_list) = quantile.extract::<Vec<f64>>() {
scalar_to_py(
py.enter_polars(|| {
self.series
.read()
.quantiles_reduce(&q_list, interpolation.0)
}),
py,
)
} else {
Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(
"quantile must be a float or a list of floats",
))
}
}
fn std<'py>(&self, py: Python<'py>, ddof: u8) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().std_reduce(ddof)), py)
}
fn var<'py>(&self, py: Python<'py>, ddof: u8) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().var_reduce(ddof)), py)
}
fn sum<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().sum_reduce()), py)
}
fn first<'py>(&self, py: Python<'py>, ignore_nulls: bool) -> PyResult<Bound<'py, PyAny>> {
let result = if ignore_nulls {
py.enter_polars_ok(|| self.series.read().first_non_null())
} else {
py.enter_polars_ok(|| self.series.read().first())
};
scalar_to_py(result, py)
}
fn last<'py>(&self, py: Python<'py>, ignore_nulls: bool) -> PyResult<Bound<'py, PyAny>> {
let result = if ignore_nulls {
py.enter_polars_ok(|| self.series.read().last_non_null())
} else {
py.enter_polars_ok(|| self.series.read().last())
};
scalar_to_py(result, py)
}
#[cfg(feature = "approx_unique")]
fn approx_n_unique(&self, py: Python) -> PyResult<IdxSize> {
py.enter_polars(|| self.series.read().approx_n_unique())
}
#[cfg(feature = "bitwise")]
fn bitwise_and<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().and_reduce()), py)
}
#[cfg(feature = "bitwise")]
fn bitwise_or<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().or_reduce()), py)
}
#[cfg(feature = "bitwise")]
fn bitwise_xor<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
scalar_to_py(py.enter_polars(|| self.series.read().xor_reduce()), py)
}
}