Path: blob/main/crates/polars-core/src/series/implementations/time.rs
8424 views
//! This module exists to reduce compilation times.1//!2//! All the data types are backed by a physical type in memory e.g. Date -> i32, Datetime-> i64.3//!4//! Series lead to code implementations of all traits. Whereas there are a lot of duplicates due to5//! data types being backed by the same physical type. In this module we reduce compile times by6//! opting for a little more run time cost. We cast to the physical type -> apply the operation and7//! (depending on the result) cast back to the original type8//!910use super::*;11#[cfg(feature = "algorithm_group_by")]12use crate::frame::group_by::*;13use crate::prelude::*;1415unsafe impl IntoSeries for TimeChunked {16fn into_series(self) -> Series {17Series(Arc::new(SeriesWrap(self)))18}19}2021impl private::PrivateSeries for SeriesWrap<TimeChunked> {22fn compute_len(&mut self) {23self.0.physical_mut().compute_len()24}2526fn _field(&self) -> Cow<'_, Field> {27Cow::Owned(self.0.field())28}2930fn _dtype(&self) -> &DataType {31self.0.dtype()32}3334fn _get_flags(&self) -> StatisticsFlags {35self.0.physical().get_flags()36}3738fn _set_flags(&mut self, flags: StatisticsFlags) {39self.0.physical_mut().set_flags(flags)40}4142#[cfg(feature = "zip_with")]43fn zip_with_same_type(&self, mask: &BooleanChunked, other: &Series) -> PolarsResult<Series> {44let other = other.to_physical_repr().into_owned();45self.046.physical()47.zip_with(mask, other.as_ref().as_ref())48.map(|ca| ca.into_time().into_series())49}5051fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {52self.0.physical().into_total_eq_inner()53}54fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {55self.0.physical().into_total_ord_inner()56}5758fn vec_hash(59&self,60random_state: PlSeedableRandomStateQuality,61buf: &mut Vec<u64>,62) -> PolarsResult<()> {63self.0.physical().vec_hash(random_state, buf)?;64Ok(())65}6667fn vec_hash_combine(68&self,69build_hasher: PlSeedableRandomStateQuality,70hashes: &mut [u64],71) -> PolarsResult<()> {72self.0.physical().vec_hash_combine(build_hasher, hashes)?;73Ok(())74}7576#[cfg(feature = "algorithm_group_by")]77unsafe fn agg_min(&self, groups: &GroupsType) -> Series {78self.0.physical().agg_min(groups).into_time().into_series()79}8081#[cfg(feature = "algorithm_group_by")]82unsafe fn agg_max(&self, groups: &GroupsType) -> Series {83self.0.physical().agg_max(groups).into_time().into_series()84}85#[cfg(feature = "algorithm_group_by")]86unsafe fn agg_arg_min(&self, groups: &GroupsType) -> Series {87self.0.physical().agg_arg_min(groups)88}8990#[cfg(feature = "algorithm_group_by")]91unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {92self.0.physical().agg_arg_max(groups)93}9495#[cfg(feature = "algorithm_group_by")]96unsafe fn agg_list(&self, groups: &GroupsType) -> Series {97// we cannot cast and dispatch as the inner type of the list would be incorrect98self.099.physical()100.agg_list(groups)101.cast(&DataType::List(Box::new(self.dtype().clone())))102.unwrap()103}104105fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {106let rhs = rhs.time().map_err(|_| polars_err!(InvalidOperation: "cannot subtract a {} dtype with a series of type: {}", self.dtype(), rhs.dtype()))?;107108let phys = self109.0110.physical()111.subtract(&rhs.physical().clone().into_series())?;112113Ok(phys.into_duration(TimeUnit::Nanoseconds))114}115116fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {117polars_bail!(opq = add, DataType::Time, rhs.dtype());118}119120fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {121polars_bail!(opq = mul, self.0.dtype(), rhs.dtype());122}123124fn divide(&self, rhs: &Series) -> PolarsResult<Series> {125polars_bail!(opq = div, self.0.dtype(), rhs.dtype());126}127128fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {129polars_bail!(opq = rem, self.0.dtype(), rhs.dtype());130}131132#[cfg(feature = "algorithm_group_by")]133fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {134self.0.physical().group_tuples(multithreaded, sorted)135}136137fn arg_sort_multiple(138&self,139by: &[Column],140options: &SortMultipleOptions,141) -> PolarsResult<IdxCa> {142self.0.physical().arg_sort_multiple(by, options)143}144}145146impl SeriesTrait for SeriesWrap<TimeChunked> {147fn rename(&mut self, name: PlSmallStr) {148self.0.rename(name);149}150151fn chunk_lengths(&self) -> ChunkLenIter<'_> {152self.0.physical().chunk_lengths()153}154fn name(&self) -> &PlSmallStr {155self.0.name()156}157158fn chunks(&self) -> &Vec<ArrayRef> {159self.0.physical().chunks()160}161162unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {163self.0.physical_mut().chunks_mut()164}165166fn shrink_to_fit(&mut self) {167self.0.physical_mut().shrink_to_fit()168}169170fn slice(&self, offset: i64, length: usize) -> Series {171self.0.slice(offset, length).into_series()172}173fn split_at(&self, offset: i64) -> (Series, Series) {174let (a, b) = self.0.split_at(offset);175(a.into_series(), b.into_series())176}177178fn _sum_as_f64(&self) -> f64 {179self.0.physical()._sum_as_f64()180}181182fn mean(&self) -> Option<f64> {183self.0.physical().mean()184}185186fn median(&self) -> Option<f64> {187self.0.physical().median()188}189190fn append(&mut self, other: &Series) -> PolarsResult<()> {191polars_ensure!(self.0.dtype() == other.dtype(), append);192let mut other = other.to_physical_repr().into_owned();193self.0194.physical_mut()195.append_owned(std::mem::take(other._get_inner_mut().as_mut()))196}197198fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {199polars_ensure!(self.0.dtype() == other.dtype(), append);200self.0.physical_mut().append_owned(std::mem::take(201&mut other202._get_inner_mut()203.as_any_mut()204.downcast_mut::<TimeChunked>()205.unwrap()206.phys,207))208}209210fn extend(&mut self, other: &Series) -> PolarsResult<()> {211polars_ensure!(self.0.dtype() == other.dtype(), extend);212// 3 refs213// ref Cow214// ref SeriesTrait215// ref ChunkedArray216let other = other.to_physical_repr();217self.0218.physical_mut()219.extend(other.as_ref().as_ref().as_ref())?;220Ok(())221}222223fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {224self.0225.physical()226.filter(filter)227.map(|ca| ca.into_time().into_series())228}229230fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {231Ok(self.0.physical().take(indices)?.into_time().into_series())232}233234unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {235self.0236.physical()237.take_unchecked(indices)238.into_time()239.into_series()240}241242fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {243Ok(self.0.physical().take(indices)?.into_time().into_series())244}245246unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {247self.0248.physical()249.take_unchecked(indices)250.into_time()251.into_series()252}253254fn deposit(&self, validity: &Bitmap) -> Series {255self.0256.physical()257.deposit(validity)258.into_time()259.into_series()260}261262fn len(&self) -> usize {263self.0.len()264}265266fn rechunk(&self) -> Series {267self.0268.physical()269.rechunk()270.into_owned()271.into_time()272.into_series()273}274275fn new_from_index(&self, index: usize, length: usize) -> Series {276self.0277.physical()278.new_from_index(index, length)279.into_time()280.into_series()281}282283fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {284match dtype {285DataType::String => Ok(self286.0287.clone()288.into_series()289.time()290.unwrap()291.to_string("%T")292.into_series()),293_ => self.0.cast_with_options(dtype, cast_options),294}295}296297#[inline]298unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {299self.0.get_any_value_unchecked(index)300}301302fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {303Ok(self304.0305.physical()306.sort_with(options)307.into_time()308.into_series())309}310311fn arg_sort(&self, options: SortOptions) -> IdxCa {312self.0.physical().arg_sort(options)313}314315fn null_count(&self) -> usize {316self.0.null_count()317}318319fn has_nulls(&self) -> bool {320self.0.has_nulls()321}322323#[cfg(feature = "algorithm_group_by")]324fn unique(&self) -> PolarsResult<Series> {325self.0326.physical()327.unique()328.map(|ca| ca.into_time().into_series())329}330331#[cfg(feature = "algorithm_group_by")]332fn n_unique(&self) -> PolarsResult<usize> {333self.0.physical().n_unique()334}335336#[cfg(feature = "algorithm_group_by")]337fn arg_unique(&self) -> PolarsResult<IdxCa> {338self.0.physical().arg_unique()339}340341fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)> {342ChunkUnique::unique_id(self.0.physical())343}344345fn is_null(&self) -> BooleanChunked {346self.0.is_null()347}348349fn is_not_null(&self) -> BooleanChunked {350self.0.is_not_null()351}352353fn reverse(&self) -> Series {354self.0.physical().reverse().into_time().into_series()355}356357fn as_single_ptr(&mut self) -> PolarsResult<usize> {358self.0.physical_mut().as_single_ptr()359}360361fn shift(&self, periods: i64) -> Series {362self.0.physical().shift(periods).into_time().into_series()363}364365fn max_reduce(&self) -> PolarsResult<Scalar> {366let sc = self.0.physical().max_reduce();367let av = sc.value().as_time();368Ok(Scalar::new(self.dtype().clone(), av))369}370371fn min_reduce(&self) -> PolarsResult<Scalar> {372let sc = self.0.physical().min_reduce();373let av = sc.value().as_time();374Ok(Scalar::new(self.dtype().clone(), av))375}376377fn mean_reduce(&self) -> PolarsResult<Scalar> {378let mean = self.mean().map(|v| v as i64);379let av = AnyValue::from(mean).as_time();380Ok(Scalar::new(self.dtype().clone(), av))381}382383fn median_reduce(&self) -> PolarsResult<Scalar> {384let median = self.median().map(|v| v as i64);385let av = AnyValue::from(median).as_time();386Ok(Scalar::new(self.dtype().clone(), av))387}388389fn quantile_reduce(&self, quantile: f64, method: QuantileMethod) -> PolarsResult<Scalar> {390let quantile = self.0.physical().quantile_reduce(quantile, method)?;391let av = quantile.value().cast(&DataType::Int64);392Ok(Scalar::new(self.dtype().clone(), av.as_time()))393}394395fn quantiles_reduce(&self, quantiles: &[f64], method: QuantileMethod) -> PolarsResult<Scalar> {396let result = self.0.physical().quantiles_reduce(quantiles, method)?;397if let AnyValue::List(float_s) = result.value() {398let float_ca = float_s.f64().unwrap();399let int_s = float_ca400.iter()401.map(|v: Option<f64>| v.map(|f| f as i64))402.collect::<Int64Chunked>()403.into_time()404.into_series();405Ok(Scalar::new(406DataType::List(Box::new(self.dtype().clone())),407AnyValue::List(int_s),408))409} else {410polars_bail!(ComputeError: "expected list scalar from quantiles_reduce")411}412}413414#[cfg(feature = "approx_unique")]415fn approx_n_unique(&self) -> PolarsResult<IdxSize> {416Ok(ChunkApproxNUnique::approx_n_unique(self.0.physical()))417}418419fn clone_inner(&self) -> Arc<dyn SeriesTrait> {420Arc::new(SeriesWrap(Clone::clone(&self.0)))421}422423fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {424self.0.physical().find_validity_mismatch(other, idxs)425}426427fn as_any(&self) -> &dyn Any {428&self.0429}430431fn as_any_mut(&mut self) -> &mut dyn Any {432&mut self.0433}434435fn as_phys_any(&self) -> &dyn Any {436self.0.physical()437}438439fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {440self as _441}442}443444impl private::PrivateSeriesNumeric for SeriesWrap<TimeChunked> {445fn bit_repr(&self) -> Option<BitRepr> {446Some(self.0.physical().to_bit_repr())447}448}449450451