polars_core/series/implementations/
mod.rs1#![allow(unsafe_op_in_unsafe_fn)]
2#[cfg(feature = "dtype-array")]
3mod array;
4mod binary;
5mod binary_offset;
6mod boolean;
7#[cfg(feature = "dtype-categorical")]
8mod categorical;
9#[cfg(feature = "dtype-date")]
10mod date;
11#[cfg(feature = "dtype-datetime")]
12mod datetime;
13#[cfg(feature = "dtype-decimal")]
14mod decimal;
15#[cfg(feature = "dtype-duration")]
16mod duration;
17#[cfg(feature = "dtype-extension")]
18mod extension;
19mod floats;
20mod list;
21#[cfg(feature = "dtype-map")]
22mod map;
23pub(crate) mod null;
24#[cfg(feature = "object")]
25mod object;
26mod string;
27#[cfg(feature = "dtype-struct")]
28mod struct_;
29#[cfg(feature = "dtype-time")]
30mod time;
31
32use std::any::Any;
33use std::borrow::Cow;
34
35use arrow::bitmap::Bitmap;
36use polars_compute::rolling::QuantileMethod;
37use polars_utils::aliases::PlSeedableRandomStateQuality;
38
39use super::*;
40use crate::chunked_array::AsSinglePtr;
41use crate::chunked_array::ops::compare_inner::{
42 IntoTotalEqInner, IntoTotalOrdInner, TotalEqInner, TotalOrdInner,
43};
44
45#[repr(transparent)]
47pub(crate) struct SeriesWrap<T>(pub T);
48
49impl<T: PolarsDataType> From<ChunkedArray<T>> for SeriesWrap<ChunkedArray<T>> {
50 fn from(ca: ChunkedArray<T>) -> Self {
51 SeriesWrap(ca)
52 }
53}
54
55impl<T: PolarsDataType> Deref for SeriesWrap<ChunkedArray<T>> {
56 type Target = ChunkedArray<T>;
57
58 fn deref(&self) -> &Self::Target {
59 &self.0
60 }
61}
62
63unsafe impl<T: PolarsPhysicalType> IntoSeries for ChunkedArray<T> {
64 fn into_series(self) -> Series {
65 T::ca_into_series(self)
66 }
67}
68
69macro_rules! impl_dyn_series {
70 ($ca: ident, $pdt:ty) => {
71 impl private::PrivateSeries for SeriesWrap<$ca> {
72 fn compute_len(&mut self) {
73 self.0.compute_len()
74 }
75
76 fn _field(&self) -> Cow<'_, Field> {
77 Cow::Borrowed(self.0.ref_field())
78 }
79
80 fn _dtype(&self) -> &DataType {
81 self.0.ref_field().dtype()
82 }
83
84 fn _get_flags(&self) -> StatisticsFlags {
85 self.0.get_flags()
86 }
87
88 fn _set_flags(&mut self, flags: StatisticsFlags) {
89 self.0.set_flags(flags)
90 }
91
92 #[cfg(feature = "zip_with")]
93 fn zip_with_same_type(
94 &self,
95 mask: &BooleanChunked,
96 other: &Series,
97 ) -> PolarsResult<Series> {
98 ChunkZip::zip_with(&self.0, mask, other.as_ref().as_ref())
99 .map(|ca| ca.into_series())
100 }
101 fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {
102 (&self.0).into_total_eq_inner()
103 }
104 fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {
105 (&self.0).into_total_ord_inner()
106 }
107
108 fn vec_hash(
109 &self,
110 random_state: PlSeedableRandomStateQuality,
111 buf: &mut Vec<u64>,
112 ) -> PolarsResult<()> {
113 self.0.vec_hash(random_state, buf)?;
114 Ok(())
115 }
116
117 fn vec_hash_combine(
118 &self,
119 build_hasher: PlSeedableRandomStateQuality,
120 hashes: &mut [u64],
121 ) -> PolarsResult<()> {
122 self.0.vec_hash_combine(build_hasher, hashes)?;
123 Ok(())
124 }
125
126 #[cfg(feature = "algorithm_group_by")]
127 unsafe fn agg_min(&self, groups: &GroupsType) -> Series {
128 self.0.agg_min(groups)
129 }
130
131 #[cfg(feature = "algorithm_group_by")]
132 unsafe fn agg_max(&self, groups: &GroupsType) -> Series {
133 self.0.agg_max(groups)
134 }
135
136 #[cfg(feature = "algorithm_group_by")]
137 unsafe fn agg_arg_min(&self, groups: &GroupsType) -> Series {
138 self.0.agg_arg_min(groups)
139 }
140
141 #[cfg(feature = "algorithm_group_by")]
142 unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {
143 self.0.agg_arg_max(groups)
144 }
145
146 #[cfg(feature = "algorithm_group_by")]
147 unsafe fn agg_sum(&self, groups: &GroupsType) -> Series {
148 use DataType::*;
149 match self.dtype() {
150 Int8 | UInt8 | Int16 | UInt16 => self
151 .cast(&Int64, CastOptions::Overflowing)
152 .unwrap()
153 .agg_sum(groups),
154 _ => self.0.agg_sum(groups),
155 }
156 }
157
158 #[cfg(feature = "algorithm_group_by")]
159 unsafe fn agg_std(&self, groups: &GroupsType, ddof: u8) -> Series {
160 self.0.agg_std(groups, ddof)
161 }
162
163 #[cfg(feature = "algorithm_group_by")]
164 unsafe fn agg_var(&self, groups: &GroupsType, ddof: u8) -> Series {
165 self.0.agg_var(groups, ddof)
166 }
167
168 #[cfg(feature = "algorithm_group_by")]
169 unsafe fn agg_list(&self, groups: &GroupsType) -> Series {
170 self.0.agg_list(groups)
171 }
172
173 #[cfg(feature = "bitwise")]
174 unsafe fn agg_and(&self, groups: &GroupsType) -> Series {
175 self.0.agg_and(groups)
176 }
177 #[cfg(feature = "bitwise")]
178 unsafe fn agg_or(&self, groups: &GroupsType) -> Series {
179 self.0.agg_or(groups)
180 }
181 #[cfg(feature = "bitwise")]
182 unsafe fn agg_xor(&self, groups: &GroupsType) -> Series {
183 self.0.agg_xor(groups)
184 }
185
186 fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {
187 NumOpsDispatch::subtract(&self.0, rhs)
188 }
189 fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {
190 NumOpsDispatch::add_to(&self.0, rhs)
191 }
192 fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {
193 NumOpsDispatch::multiply(&self.0, rhs)
194 }
195 fn divide(&self, rhs: &Series) -> PolarsResult<Series> {
196 NumOpsDispatch::divide(&self.0, rhs)
197 }
198 fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {
199 NumOpsDispatch::remainder(&self.0, rhs)
200 }
201 #[cfg(feature = "algorithm_group_by")]
202 fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {
203 IntoGroupsType::group_tuples(&self.0, multithreaded, sorted)
204 }
205
206 fn arg_sort_multiple(
207 &self,
208 by: &[Column],
209 options: &SortMultipleOptions,
210 ) -> PolarsResult<IdxCa> {
211 self.0.arg_sort_multiple(by, options)
212 }
213 }
214
215 impl SeriesTrait for SeriesWrap<$ca> {
216 #[cfg(feature = "rolling_window")]
217 fn rolling_map(
218 &self,
219 _f: &dyn Fn(&Series) -> PolarsResult<Series>,
220 _options: RollingOptionsFixedWindow,
221 ) -> PolarsResult<Series> {
222 ChunkRollApply::rolling_map(&self.0, _f, _options).map(|ca| ca.into_series())
223 }
224
225 fn rename(&mut self, name: PlSmallStr) {
226 self.0.rename(name);
227 }
228
229 fn chunk_lengths(&self) -> ChunkLenIter<'_> {
230 self.0.chunk_lengths()
231 }
232 fn name(&self) -> &PlSmallStr {
233 self.0.name()
234 }
235
236 fn chunks(&self) -> &Vec<ArrayRef> {
237 self.0.chunks()
238 }
239 unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {
240 self.0.chunks_mut()
241 }
242 fn shrink_to_fit(&mut self) {
243 self.0.shrink_to_fit()
244 }
245
246 fn slice(&self, offset: i64, length: usize) -> Series {
247 self.0.slice(offset, length).into_series()
248 }
249
250 fn split_at(&self, offset: i64) -> (Series, Series) {
251 let (a, b) = self.0.split_at(offset);
252 (a.into_series(), b.into_series())
253 }
254
255 fn append(&mut self, other: &Series) -> PolarsResult<()> {
256 polars_ensure!(self.0.dtype() == other.dtype(), append);
257 self.0.append(other.as_ref().as_ref())?;
258 Ok(())
259 }
260 fn append_owned(&mut self, other: Series) -> PolarsResult<()> {
261 polars_ensure!(self.0.dtype() == other.dtype(), append);
262 self.0.append_owned(other.take_inner())
263 }
264
265 fn extend(&mut self, other: &Series) -> PolarsResult<()> {
266 polars_ensure!(self.0.dtype() == other.dtype(), extend);
267 self.0.extend(other.as_ref().as_ref())?;
268 Ok(())
269 }
270
271 fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {
272 ChunkFilter::filter(&self.0, filter).map(|ca| ca.into_series())
273 }
274
275 fn _sum_as_f64(&self) -> f64 {
276 self.0._sum_as_f64()
277 }
278
279 fn mean(&self) -> Option<f64> {
280 self.0.mean()
281 }
282
283 fn median(&self) -> Option<f64> {
284 self.0.median()
285 }
286
287 fn std(&self, ddof: u8) -> Option<f64> {
288 self.0.std(ddof)
289 }
290
291 fn var(&self, ddof: u8) -> Option<f64> {
292 self.0.var(ddof)
293 }
294
295 fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {
296 Ok(self.0.take(indices)?.into_series())
297 }
298
299 unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {
300 self.0.take_unchecked(indices).into_series()
301 }
302
303 fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {
304 Ok(self.0.take(indices)?.into_series())
305 }
306
307 unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {
308 self.0.take_unchecked(indices).into_series()
309 }
310
311 fn deposit(&self, validity: &Bitmap) -> Series {
312 self.0.deposit(validity).into_series()
313 }
314
315 fn len(&self) -> usize {
316 self.0.len()
317 }
318
319 fn rechunk(&self) -> Series {
320 self.0.rechunk().into_owned().into_series()
321 }
322
323 fn with_validity(&self, validity: Option<Bitmap>) -> Series {
324 self.0.clone().with_validity(validity).into_series()
325 }
326
327 fn new_from_index(&self, index: usize, length: usize) -> Series {
328 ChunkExpandAtIndex::new_from_index(&self.0, index, length).into_series()
329 }
330
331 fn cast(&self, dtype: &DataType, options: CastOptions) -> PolarsResult<Series> {
332 self.0.cast_with_options(dtype, options)
333 }
334
335 #[inline]
336 unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {
337 self.0.get_any_value_unchecked(index)
338 }
339
340 fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {
341 Ok(ChunkSort::sort_with(&self.0, options).into_series())
342 }
343
344 fn arg_sort(&self, options: SortOptions) -> IdxCa {
345 ChunkSort::arg_sort(&self.0, options)
346 }
347
348 fn null_count(&self) -> usize {
349 self.0.null_count()
350 }
351
352 fn has_nulls(&self) -> bool {
353 self.0.has_nulls()
354 }
355
356 #[cfg(feature = "algorithm_group_by")]
357 fn unique(&self) -> PolarsResult<Series> {
358 ChunkUnique::unique(&self.0).map(|ca| ca.into_series())
359 }
360
361 #[cfg(feature = "algorithm_group_by")]
362 fn n_unique(&self) -> PolarsResult<usize> {
363 ChunkUnique::n_unique(&self.0)
364 }
365
366 #[cfg(feature = "algorithm_group_by")]
367 fn arg_unique(&self) -> PolarsResult<IdxCa> {
368 ChunkUnique::arg_unique(&self.0)
369 }
370
371 #[cfg(feature = "algorithm_group_by")]
372 fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)> {
373 ChunkUnique::unique_id(&self.0)
374 }
375
376 fn is_null(&self) -> BooleanChunked {
377 self.0.is_null()
378 }
379
380 fn is_not_null(&self) -> BooleanChunked {
381 self.0.is_not_null()
382 }
383
384 fn reverse(&self) -> Series {
385 ChunkReverse::reverse(&self.0).into_series()
386 }
387
388 fn as_single_ptr(&mut self) -> PolarsResult<usize> {
389 self.0.as_single_ptr()
390 }
391
392 fn shift(&self, periods: i64) -> Series {
393 ChunkShift::shift(&self.0, periods).into_series()
394 }
395
396 fn sum_reduce(&self) -> PolarsResult<Scalar> {
397 Ok(ChunkAggSeries::sum_reduce(&self.0))
398 }
399 fn max_reduce(&self) -> PolarsResult<Scalar> {
400 Ok(ChunkAggSeries::max_reduce(&self.0))
401 }
402 fn min_reduce(&self) -> PolarsResult<Scalar> {
403 Ok(ChunkAggSeries::min_reduce(&self.0))
404 }
405 fn mean_reduce(&self) -> PolarsResult<Scalar> {
406 Ok(Scalar::new(DataType::Float64, self.mean().into()))
407 }
408 fn median_reduce(&self) -> PolarsResult<Scalar> {
409 Ok(QuantileAggSeries::median_reduce(&self.0))
410 }
411 fn var_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {
412 Ok(VarAggSeries::var_reduce(&self.0, ddof))
413 }
414 fn std_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {
415 Ok(VarAggSeries::std_reduce(&self.0, ddof))
416 }
417
418 fn quantile_reduce(
419 &self,
420 quantile: f64,
421 method: QuantileMethod,
422 ) -> PolarsResult<Scalar> {
423 QuantileAggSeries::quantile_reduce(&self.0, quantile, method)
424 }
425
426 fn quantiles_reduce(
427 &self,
428 quantiles: &[f64],
429 method: QuantileMethod,
430 ) -> PolarsResult<Scalar> {
431 QuantileAggSeries::quantiles_reduce(&self.0, quantiles, method)
432 }
433
434 #[cfg(feature = "bitwise")]
435 fn and_reduce(&self) -> PolarsResult<Scalar> {
436 let dt = <$pdt as PolarsDataType>::get_static_dtype();
437 let av = self.0.and_reduce().map_or(AnyValue::Null, Into::into);
438
439 Ok(Scalar::new(dt, av))
440 }
441
442 #[cfg(feature = "bitwise")]
443 fn or_reduce(&self) -> PolarsResult<Scalar> {
444 let dt = <$pdt as PolarsDataType>::get_static_dtype();
445 let av = self.0.or_reduce().map_or(AnyValue::Null, Into::into);
446
447 Ok(Scalar::new(dt, av))
448 }
449
450 #[cfg(feature = "bitwise")]
451 fn xor_reduce(&self) -> PolarsResult<Scalar> {
452 let dt = <$pdt as PolarsDataType>::get_static_dtype();
453 let av = self.0.xor_reduce().map_or(AnyValue::Null, Into::into);
454
455 Ok(Scalar::new(dt, av))
456 }
457
458 #[cfg(feature = "approx_unique")]
459 fn approx_n_unique(&self) -> PolarsResult<IdxSize> {
460 Ok(ChunkApproxNUnique::approx_n_unique(&self.0))
461 }
462
463 fn clone_inner(&self) -> Arc<dyn SeriesTrait> {
464 Arc::new(SeriesWrap(Clone::clone(&self.0)))
465 }
466
467 fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {
468 self.0.find_validity_mismatch(other, idxs)
469 }
470
471 #[cfg(feature = "checked_arithmetic")]
472 fn checked_div(&self, rhs: &Series) -> PolarsResult<Series> {
473 self.0.checked_div(rhs)
474 }
475
476 fn as_any(&self) -> &dyn Any {
477 &self.0
478 }
479
480 fn as_any_mut(&mut self) -> &mut dyn Any {
481 &mut self.0
482 }
483
484 fn as_phys_any(&self) -> &dyn Any {
485 &self.0
486 }
487
488 fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
489 self as _
490 }
491 }
492 };
493}
494
495#[cfg(feature = "dtype-u8")]
496impl_dyn_series!(UInt8Chunked, UInt8Type);
497#[cfg(feature = "dtype-u16")]
498impl_dyn_series!(UInt16Chunked, UInt16Type);
499impl_dyn_series!(UInt32Chunked, UInt32Type);
500impl_dyn_series!(UInt64Chunked, UInt64Type);
501#[cfg(feature = "dtype-u128")]
502impl_dyn_series!(UInt128Chunked, UInt128Type);
503#[cfg(feature = "dtype-i8")]
504impl_dyn_series!(Int8Chunked, Int8Type);
505#[cfg(feature = "dtype-i16")]
506impl_dyn_series!(Int16Chunked, Int16Type);
507impl_dyn_series!(Int32Chunked, Int32Type);
508impl_dyn_series!(Int64Chunked, Int64Type);
509#[cfg(feature = "dtype-i128")]
510impl_dyn_series!(Int128Chunked, Int128Type);
511
512impl<T: PolarsNumericType> private::PrivateSeriesNumeric for SeriesWrap<ChunkedArray<T>> {
513 fn bit_repr(&self) -> Option<BitRepr> {
514 Some(self.0.to_bit_repr())
515 }
516}
517
518impl private::PrivateSeriesNumeric for SeriesWrap<StringChunked> {
519 fn bit_repr(&self) -> Option<BitRepr> {
520 None
521 }
522}
523impl private::PrivateSeriesNumeric for SeriesWrap<BinaryChunked> {
524 fn bit_repr(&self) -> Option<BitRepr> {
525 None
526 }
527}
528impl private::PrivateSeriesNumeric for SeriesWrap<BinaryOffsetChunked> {
529 fn bit_repr(&self) -> Option<BitRepr> {
530 None
531 }
532}
533impl private::PrivateSeriesNumeric for SeriesWrap<ListChunked> {
534 fn bit_repr(&self) -> Option<BitRepr> {
535 None
536 }
537}
538#[cfg(feature = "dtype-array")]
539impl private::PrivateSeriesNumeric for SeriesWrap<ArrayChunked> {
540 fn bit_repr(&self) -> Option<BitRepr> {
541 None
542 }
543}
544impl private::PrivateSeriesNumeric for SeriesWrap<BooleanChunked> {
545 fn bit_repr(&self) -> Option<BitRepr> {
546 let repr = self
547 .0
548 .cast_with_options(&DataType::UInt32, CastOptions::NonStrict)
549 .unwrap()
550 .u32()
551 .unwrap()
552 .clone();
553
554 Some(BitRepr::U32(repr))
555 }
556}