Path: blob/main/crates/polars-python/src/expr/rolling.rs
7889 views
use polars::prelude::*;1use polars_utils::python_function::PythonObject;2use pyo3::prelude::*;34use crate::PyExpr;5use crate::conversion::Wrap;6use crate::error::PyPolarsErr;78#[pymethods]9impl PyExpr {10#[pyo3(signature = (window_size, weights, min_periods, center))]11fn rolling_sum(12&self,13window_size: usize,14weights: Option<Vec<f64>>,15min_periods: Option<usize>,16center: bool,17) -> Self {18let min_periods = min_periods.unwrap_or(window_size);19let options = RollingOptionsFixedWindow {20window_size,21weights,22min_periods,23center,24..Default::default()25};26self.inner.clone().rolling_sum(options).into()27}2829#[pyo3(signature = (by, window_size, min_periods, closed))]30fn rolling_sum_by(31&self,32by: PyExpr,33window_size: &str,34min_periods: usize,35closed: Wrap<ClosedWindow>,36) -> PyResult<Self> {37let options = RollingOptionsDynamicWindow {38window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,39min_periods,40closed_window: closed.0,41fn_params: None,42};43Ok(self.inner.clone().rolling_sum_by(by.inner, options).into())44}4546#[pyo3(signature = (window_size, weights, min_periods, center))]47fn rolling_min(48&self,49window_size: usize,50weights: Option<Vec<f64>>,51min_periods: Option<usize>,52center: bool,53) -> Self {54let min_periods = min_periods.unwrap_or(window_size);55let options = RollingOptionsFixedWindow {56window_size,57weights,58min_periods,59center,60..Default::default()61};62self.inner.clone().rolling_min(options).into()63}6465#[pyo3(signature = (by, window_size, min_periods, closed))]66fn rolling_min_by(67&self,68by: PyExpr,69window_size: &str,70min_periods: usize,71closed: Wrap<ClosedWindow>,72) -> PyResult<Self> {73let options = RollingOptionsDynamicWindow {74window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,75min_periods,76closed_window: closed.0,77fn_params: None,78};79Ok(self.inner.clone().rolling_min_by(by.inner, options).into())80}8182#[pyo3(signature = (window_size, weights, min_periods, center))]83fn rolling_max(84&self,85window_size: usize,86weights: Option<Vec<f64>>,87min_periods: Option<usize>,88center: bool,89) -> Self {90let min_periods = min_periods.unwrap_or(window_size);91let options = RollingOptionsFixedWindow {92window_size,93weights,94min_periods,95center,96..Default::default()97};98self.inner.clone().rolling_max(options).into()99}100#[pyo3(signature = (by, window_size, min_periods, closed))]101fn rolling_max_by(102&self,103by: PyExpr,104window_size: &str,105min_periods: usize,106closed: Wrap<ClosedWindow>,107) -> PyResult<Self> {108let options = RollingOptionsDynamicWindow {109window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,110min_periods,111closed_window: closed.0,112fn_params: None,113};114Ok(self.inner.clone().rolling_max_by(by.inner, options).into())115}116117#[pyo3(signature = (window_size, weights, min_periods, center))]118fn rolling_mean(119&self,120window_size: usize,121weights: Option<Vec<f64>>,122min_periods: Option<usize>,123center: bool,124) -> Self {125let min_periods = min_periods.unwrap_or(window_size);126let options = RollingOptionsFixedWindow {127window_size,128weights,129min_periods,130center,131..Default::default()132};133134self.inner.clone().rolling_mean(options).into()135}136137#[pyo3(signature = (by, window_size, min_periods, closed))]138fn rolling_mean_by(139&self,140by: PyExpr,141window_size: &str,142min_periods: usize,143closed: Wrap<ClosedWindow>,144) -> PyResult<Self> {145let options = RollingOptionsDynamicWindow {146window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,147min_periods,148closed_window: closed.0,149fn_params: None,150};151152Ok(self.inner.clone().rolling_mean_by(by.inner, options).into())153}154155#[pyo3(signature = (window_size, weights, min_periods, center, ddof))]156fn rolling_std(157&self,158window_size: usize,159weights: Option<Vec<f64>>,160min_periods: Option<usize>,161center: bool,162ddof: u8,163) -> Self {164let min_periods = min_periods.unwrap_or(window_size);165let options = RollingOptionsFixedWindow {166window_size,167weights,168min_periods,169center,170fn_params: Some(RollingFnParams::Var(RollingVarParams { ddof })),171};172173self.inner.clone().rolling_std(options).into()174}175176#[pyo3(signature = (by, window_size, min_periods, closed, ddof))]177fn rolling_std_by(178&self,179by: PyExpr,180window_size: &str,181min_periods: usize,182closed: Wrap<ClosedWindow>,183ddof: u8,184) -> PyResult<Self> {185let options = RollingOptionsDynamicWindow {186window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,187min_periods,188closed_window: closed.0,189fn_params: Some(RollingFnParams::Var(RollingVarParams { ddof })),190};191192Ok(self.inner.clone().rolling_std_by(by.inner, options).into())193}194195#[pyo3(signature = (window_size, weights, min_periods, center, ddof))]196fn rolling_var(197&self,198window_size: usize,199weights: Option<Vec<f64>>,200min_periods: Option<usize>,201center: bool,202ddof: u8,203) -> Self {204let min_periods = min_periods.unwrap_or(window_size);205let options = RollingOptionsFixedWindow {206window_size,207weights,208min_periods,209center,210fn_params: Some(RollingFnParams::Var(RollingVarParams { ddof })),211};212213self.inner.clone().rolling_var(options).into()214}215216#[pyo3(signature = (by, window_size, min_periods, closed, ddof))]217fn rolling_var_by(218&self,219by: PyExpr,220window_size: &str,221min_periods: usize,222closed: Wrap<ClosedWindow>,223ddof: u8,224) -> PyResult<Self> {225let options = RollingOptionsDynamicWindow {226window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,227min_periods,228closed_window: closed.0,229fn_params: Some(RollingFnParams::Var(RollingVarParams { ddof })),230};231232Ok(self.inner.clone().rolling_var_by(by.inner, options).into())233}234235#[pyo3(signature = (window_size, weights, min_periods, center))]236fn rolling_median(237&self,238window_size: usize,239weights: Option<Vec<f64>>,240min_periods: Option<usize>,241center: bool,242) -> Self {243let min_periods = min_periods.unwrap_or(window_size);244let options = RollingOptionsFixedWindow {245window_size,246min_periods,247weights,248center,249fn_params: None,250};251self.inner.clone().rolling_median(options).into()252}253254#[pyo3(signature = (by, window_size, min_periods, closed))]255fn rolling_median_by(256&self,257by: PyExpr,258window_size: &str,259min_periods: usize,260closed: Wrap<ClosedWindow>,261) -> PyResult<Self> {262let options = RollingOptionsDynamicWindow {263window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,264min_periods,265closed_window: closed.0,266fn_params: None,267};268Ok(self269.inner270.clone()271.rolling_median_by(by.inner, options)272.into())273}274275#[pyo3(signature = (quantile, interpolation, window_size, weights, min_periods, center))]276fn rolling_quantile(277&self,278quantile: f64,279interpolation: Wrap<QuantileMethod>,280window_size: usize,281weights: Option<Vec<f64>>,282min_periods: Option<usize>,283center: bool,284) -> Self {285let min_periods = min_periods.unwrap_or(window_size);286let options = RollingOptionsFixedWindow {287window_size,288weights,289min_periods,290center,291fn_params: None,292};293294self.inner295.clone()296.rolling_quantile(interpolation.0, quantile, options)297.into()298}299300#[pyo3(signature = (by, quantile, interpolation, window_size, min_periods, closed))]301fn rolling_quantile_by(302&self,303by: PyExpr,304quantile: f64,305interpolation: Wrap<QuantileMethod>,306window_size: &str,307min_periods: usize,308closed: Wrap<ClosedWindow>,309) -> PyResult<Self> {310let options = RollingOptionsDynamicWindow {311window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,312min_periods,313closed_window: closed.0,314fn_params: None,315};316317Ok(self318.inner319.clone()320.rolling_quantile_by(by.inner, interpolation.0, quantile, options)321.into())322}323324#[pyo3(signature = (window_size, method, seed, min_samples, center))]325fn rolling_rank(326&self,327window_size: usize,328method: Wrap<RollingRankMethod>,329seed: Option<u64>,330min_samples: Option<usize>,331center: bool,332) -> Self {333let min_samples = min_samples.unwrap_or(window_size);334let options = RollingOptionsFixedWindow {335window_size,336min_periods: min_samples,337weights: None,338center,339fn_params: Some(RollingFnParams::Rank {340method: method.0,341seed,342}),343};344345self.inner.clone().rolling_rank(options).into()346}347348#[pyo3(signature = (by, window_size, method, seed, min_samples, closed))]349fn rolling_rank_by(350&self,351by: PyExpr,352window_size: &str,353method: Wrap<RollingRankMethod>,354seed: Option<u64>,355min_samples: usize,356closed: Wrap<ClosedWindow>,357) -> PyResult<Self> {358let options = RollingOptionsDynamicWindow {359window_size: Duration::try_parse(window_size).map_err(PyPolarsErr::from)?,360min_periods: min_samples,361closed_window: closed.0,362fn_params: Some(RollingFnParams::Rank {363method: method.0,364seed,365}),366};367368Ok(self.inner.clone().rolling_rank_by(by.inner, options).into())369}370371#[pyo3(signature = (window_size, bias, min_periods, center))]372fn rolling_skew(373&self,374window_size: usize,375bias: bool,376min_periods: Option<usize>,377center: bool,378) -> Self {379let min_periods = min_periods.unwrap_or(window_size);380let options = RollingOptionsFixedWindow {381window_size,382weights: None,383min_periods,384center,385fn_params: Some(RollingFnParams::Skew { bias }),386};387388self.inner.clone().rolling_skew(options).into()389}390391#[pyo3(signature = (window_size, fisher, bias, min_periods, center))]392fn rolling_kurtosis(393&self,394window_size: usize,395fisher: bool,396bias: bool,397min_periods: Option<usize>,398center: bool,399) -> Self {400let min_periods = min_periods.unwrap_or(window_size);401let options = RollingOptionsFixedWindow {402window_size,403weights: None,404min_periods,405center,406fn_params: Some(RollingFnParams::Kurtosis { fisher, bias }),407};408409self.inner.clone().rolling_kurtosis(options).into()410}411412#[pyo3(signature = (lambda, window_size, weights, min_periods, center))]413fn rolling_map(414&self,415lambda: Py<PyAny>,416window_size: usize,417weights: Option<Vec<f64>>,418min_periods: Option<usize>,419center: bool,420) -> Self {421let min_periods = min_periods.unwrap_or(window_size);422let options = RollingOptionsFixedWindow {423window_size,424weights,425min_periods,426center,427..Default::default()428};429let function = PlanCallback::new_python(PythonObject(lambda));430431self.inner.clone().rolling_map(function, options).into()432}433}434435436