Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/series/series_trait.rs
8475 views
1
use std::any::Any;
2
use std::borrow::Cow;
3
4
use arrow::bitmap::{Bitmap, BitmapBuilder};
5
use polars_compute::rolling::QuantileMethod;
6
#[cfg(feature = "serde")]
7
use serde::{Deserialize, Serialize};
8
9
use crate::chunked_array::cast::CastOptions;
10
#[cfg(feature = "object")]
11
use crate::chunked_array::object::PolarsObjectSafe;
12
use crate::prelude::*;
13
use crate::utils::{first_non_null, last_non_null};
14
15
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
16
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17
#[cfg_attr(feature = "dsl-schema", derive(schemars::JsonSchema))]
18
pub enum IsSorted {
19
Ascending,
20
Descending,
21
Not,
22
}
23
24
impl IsSorted {
25
pub fn reverse(self) -> Self {
26
use IsSorted::*;
27
match self {
28
Ascending => Descending,
29
Descending => Ascending,
30
Not => Not,
31
}
32
}
33
}
34
35
pub enum BitRepr {
36
U8(UInt8Chunked),
37
U16(UInt16Chunked),
38
U32(UInt32Chunked),
39
U64(UInt64Chunked),
40
#[cfg(feature = "dtype-u128")]
41
U128(UInt128Chunked),
42
}
43
44
pub(crate) mod private {
45
use polars_utils::aliases::PlSeedableRandomStateQuality;
46
47
use super::*;
48
use crate::chunked_array::flags::StatisticsFlags;
49
use crate::chunked_array::ops::compare_inner::{TotalEqInner, TotalOrdInner};
50
51
pub trait PrivateSeriesNumeric {
52
/// Return a bit representation
53
///
54
/// If there is no available bit representation this returns `None`.
55
fn bit_repr(&self) -> Option<BitRepr>;
56
}
57
58
pub trait PrivateSeries {
59
#[cfg(feature = "object")]
60
fn get_list_builder(
61
&self,
62
_name: PlSmallStr,
63
_values_capacity: usize,
64
_list_capacity: usize,
65
) -> Box<dyn ListBuilderTrait> {
66
invalid_operation_panic!(get_list_builder, self)
67
}
68
69
/// Get field (used in schema)
70
fn _field(&self) -> Cow<'_, Field>;
71
72
fn _dtype(&self) -> &DataType;
73
74
fn compute_len(&mut self);
75
76
fn _get_flags(&self) -> StatisticsFlags;
77
78
fn _set_flags(&mut self, flags: StatisticsFlags);
79
80
unsafe fn equal_element(
81
&self,
82
_idx_self: usize,
83
_idx_other: usize,
84
_other: &Series,
85
) -> bool {
86
invalid_operation_panic!(equal_element, self)
87
}
88
#[expect(clippy::wrong_self_convention)]
89
fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a>;
90
#[expect(clippy::wrong_self_convention)]
91
fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a>;
92
93
fn vec_hash(
94
&self,
95
_build_hasher: PlSeedableRandomStateQuality,
96
_buf: &mut Vec<u64>,
97
) -> PolarsResult<()>;
98
fn vec_hash_combine(
99
&self,
100
_build_hasher: PlSeedableRandomStateQuality,
101
_hashes: &mut [u64],
102
) -> PolarsResult<()>;
103
104
/// # Safety
105
///
106
/// Does no bounds checks, groups must be correct.
107
#[cfg(feature = "algorithm_group_by")]
108
unsafe fn agg_min(&self, groups: &GroupsType) -> Series {
109
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
110
}
111
/// # Safety
112
///
113
/// Does no bounds checks, groups must be correct.
114
#[cfg(feature = "algorithm_group_by")]
115
unsafe fn agg_max(&self, groups: &GroupsType) -> Series {
116
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
117
}
118
/// # Safety
119
///
120
/// Does no bounds checks, groups must be correct.
121
#[cfg(feature = "algorithm_group_by")]
122
unsafe fn agg_arg_min(&self, groups: &GroupsType) -> Series {
123
Series::full_null(self._field().name().clone(), groups.len(), &IDX_DTYPE)
124
}
125
126
/// # Safety
127
///
128
/// Does no bounds checks, groups must be correct.
129
#[cfg(feature = "algorithm_group_by")]
130
unsafe fn agg_arg_max(&self, groups: &GroupsType) -> Series {
131
Series::full_null(self._field().name().clone(), groups.len(), &IDX_DTYPE)
132
}
133
134
/// If the [`DataType`] is one of `{Int8, UInt8, Int16, UInt16}` the `Series` is
135
/// first cast to `Int64` to prevent overflow issues.
136
#[cfg(feature = "algorithm_group_by")]
137
unsafe fn agg_sum(&self, groups: &GroupsType) -> Series {
138
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
139
}
140
/// # Safety
141
///
142
/// Does no bounds checks, groups must be correct.
143
#[cfg(feature = "algorithm_group_by")]
144
unsafe fn agg_std(&self, groups: &GroupsType, _ddof: u8) -> Series {
145
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
146
}
147
/// # Safety
148
///
149
/// Does no bounds checks, groups must be correct.
150
#[cfg(feature = "algorithm_group_by")]
151
unsafe fn agg_var(&self, groups: &GroupsType, _ddof: u8) -> Series {
152
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
153
}
154
/// # Safety
155
///
156
/// Does no bounds checks, groups must be correct.
157
#[cfg(feature = "algorithm_group_by")]
158
unsafe fn agg_list(&self, groups: &GroupsType) -> Series {
159
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
160
}
161
162
/// # Safety
163
///
164
/// Does no bounds checks, groups must be correct.
165
#[cfg(feature = "bitwise")]
166
unsafe fn agg_and(&self, groups: &GroupsType) -> Series {
167
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
168
}
169
170
/// # Safety
171
///
172
/// Does no bounds checks, groups must be correct.
173
#[cfg(feature = "bitwise")]
174
unsafe fn agg_or(&self, groups: &GroupsType) -> Series {
175
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
176
}
177
178
/// # Safety
179
///
180
/// Does no bounds checks, groups must be correct.
181
#[cfg(feature = "bitwise")]
182
unsafe fn agg_xor(&self, groups: &GroupsType) -> Series {
183
Series::full_null(self._field().name().clone(), groups.len(), self._dtype())
184
}
185
186
fn subtract(&self, _rhs: &Series) -> PolarsResult<Series> {
187
polars_bail!(opq = subtract, self._dtype());
188
}
189
fn add_to(&self, _rhs: &Series) -> PolarsResult<Series> {
190
polars_bail!(opq = add, self._dtype());
191
}
192
fn multiply(&self, _rhs: &Series) -> PolarsResult<Series> {
193
polars_bail!(opq = multiply, self._dtype());
194
}
195
fn divide(&self, _rhs: &Series) -> PolarsResult<Series> {
196
polars_bail!(opq = divide, self._dtype());
197
}
198
fn remainder(&self, _rhs: &Series) -> PolarsResult<Series> {
199
polars_bail!(opq = remainder, self._dtype());
200
}
201
#[cfg(feature = "algorithm_group_by")]
202
fn group_tuples(&self, _multithreaded: bool, _sorted: bool) -> PolarsResult<GroupsType> {
203
polars_bail!(opq = group_tuples, self._dtype());
204
}
205
#[cfg(feature = "zip_with")]
206
fn zip_with_same_type(
207
&self,
208
_mask: &BooleanChunked,
209
_other: &Series,
210
) -> PolarsResult<Series> {
211
polars_bail!(opq = zip_with_same_type, self._dtype());
212
}
213
214
#[allow(unused_variables)]
215
fn arg_sort_multiple(
216
&self,
217
by: &[Column],
218
_options: &SortMultipleOptions,
219
) -> PolarsResult<IdxCa> {
220
polars_bail!(opq = arg_sort_multiple, self._dtype());
221
}
222
}
223
}
224
225
pub trait SeriesTrait:
226
Send + Sync + private::PrivateSeries + private::PrivateSeriesNumeric
227
{
228
/// Rename the Series.
229
fn rename(&mut self, name: PlSmallStr);
230
231
/// Get the lengths of the underlying chunks
232
fn chunk_lengths(&self) -> ChunkLenIter<'_>;
233
234
/// Name of series.
235
fn name(&self) -> &PlSmallStr;
236
237
/// Get field (used in schema)
238
fn field(&self) -> Cow<'_, Field> {
239
self._field()
240
}
241
242
/// Get datatype of series.
243
fn dtype(&self) -> &DataType {
244
self._dtype()
245
}
246
247
/// Underlying chunks.
248
fn chunks(&self) -> &Vec<ArrayRef>;
249
250
/// Underlying chunks.
251
///
252
/// # Safety
253
/// The caller must ensure the length and the data types of `ArrayRef` does not change.
254
unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef>;
255
256
/// Number of chunks in this Series
257
fn n_chunks(&self) -> usize {
258
self.chunks().len()
259
}
260
261
/// Shrink the capacity of this array to fit its length.
262
fn shrink_to_fit(&mut self) {
263
// no-op
264
}
265
266
/// Take `num_elements` from the top as a zero copy view.
267
fn limit(&self, num_elements: usize) -> Series {
268
self.slice(0, num_elements)
269
}
270
271
/// Get a zero copy view of the data.
272
///
273
/// When offset is negative the offset is counted from the
274
/// end of the array
275
fn slice(&self, _offset: i64, _length: usize) -> Series;
276
277
/// Get a zero copy view of the data.
278
///
279
/// When offset is negative the offset is counted from the
280
/// end of the array
281
fn split_at(&self, _offset: i64) -> (Series, Series);
282
283
fn append(&mut self, other: &Series) -> PolarsResult<()>;
284
fn append_owned(&mut self, other: Series) -> PolarsResult<()>;
285
286
#[doc(hidden)]
287
fn extend(&mut self, _other: &Series) -> PolarsResult<()>;
288
289
/// Filter by boolean mask. This operation clones data.
290
fn filter(&self, _filter: &BooleanChunked) -> PolarsResult<Series>;
291
292
/// Take from `self` at the indexes given by `idx`.
293
///
294
/// Null values in `idx` because null values in the output array.
295
///
296
/// This operation is clone.
297
fn take(&self, _indices: &IdxCa) -> PolarsResult<Series>;
298
299
/// Take from `self` at the indexes given by `idx`.
300
///
301
/// Null values in `idx` because null values in the output array.
302
///
303
/// # Safety
304
/// This doesn't check any bounds.
305
unsafe fn take_unchecked(&self, _idx: &IdxCa) -> Series;
306
307
/// Take from `self` at the indexes given by `idx`.
308
///
309
/// This operation is clone.
310
fn take_slice(&self, _indices: &[IdxSize]) -> PolarsResult<Series>;
311
312
/// Take from `self` at the indexes given by `idx`.
313
///
314
/// # Safety
315
/// This doesn't check any bounds.
316
unsafe fn take_slice_unchecked(&self, _idx: &[IdxSize]) -> Series;
317
318
/// Get length of series.
319
fn len(&self) -> usize;
320
321
/// Check if Series is empty.
322
fn is_empty(&self) -> bool {
323
self.len() == 0
324
}
325
326
/// Aggregate all chunks to a contiguous array of memory.
327
fn rechunk(&self) -> Series;
328
329
fn rechunk_validity(&self) -> Option<Bitmap> {
330
if self.chunks().len() == 1 {
331
return self.chunks()[0].validity().cloned();
332
}
333
334
if !self.has_nulls() || self.is_empty() {
335
return None;
336
}
337
338
let mut bm = BitmapBuilder::with_capacity(self.len());
339
for arr in self.chunks() {
340
if let Some(v) = arr.validity() {
341
bm.extend_from_bitmap(v);
342
} else {
343
bm.extend_constant(arr.len(), true);
344
}
345
}
346
bm.into_opt_validity()
347
}
348
349
/// Drop all null values and return a new Series.
350
fn drop_nulls(&self) -> Series {
351
if self.null_count() == 0 {
352
Series(self.clone_inner())
353
} else {
354
self.filter(&self.is_not_null()).unwrap()
355
}
356
}
357
358
/// Returns the sum of the array as an f64.
359
fn _sum_as_f64(&self) -> f64 {
360
invalid_operation_panic!(_sum_as_f64, self)
361
}
362
363
/// Returns the mean value in the array
364
/// Returns an option because the array is nullable.
365
fn mean(&self) -> Option<f64> {
366
None
367
}
368
369
/// Returns the std value in the array
370
/// Returns an option because the array is nullable.
371
fn std(&self, _ddof: u8) -> Option<f64> {
372
None
373
}
374
375
/// Returns the var value in the array
376
/// Returns an option because the array is nullable.
377
fn var(&self, _ddof: u8) -> Option<f64> {
378
None
379
}
380
381
/// Returns the median value in the array
382
/// Returns an option because the array is nullable.
383
fn median(&self) -> Option<f64> {
384
None
385
}
386
387
/// Create a new Series filled with values from the given index.
388
///
389
/// # Example
390
///
391
/// ```rust
392
/// use polars_core::prelude::*;
393
/// let s = Series::new("a".into(), [0i32, 1, 8]);
394
/// let s2 = s.new_from_index(2, 4);
395
/// assert_eq!(Vec::from(s2.i32().unwrap()), &[Some(8), Some(8), Some(8), Some(8)])
396
/// ```
397
fn new_from_index(&self, _index: usize, _length: usize) -> Series;
398
399
/// Trim all lists of unused start and end elements recursively.
400
///
401
/// - `None` if nothing needed to be done.
402
/// - `Some(series)` if something changed.
403
fn trim_lists_to_normalized_offsets(&self) -> Option<Series> {
404
None
405
}
406
407
/// Propagate down nulls in nested types.
408
///
409
/// - `None` if nothing needed to be done.
410
/// - `Some(series)` if something changed.
411
fn propagate_nulls(&self) -> Option<Series> {
412
None
413
}
414
415
fn deposit(&self, validity: &Bitmap) -> Series;
416
417
/// Find the indices of elements where the null masks are different recursively.
418
fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>);
419
420
fn cast(&self, _dtype: &DataType, options: CastOptions) -> PolarsResult<Series>;
421
422
/// Get a single value by index. Don't use this operation for loops as a runtime cast is
423
/// needed for every iteration.
424
fn get(&self, index: usize) -> PolarsResult<AnyValue<'_>> {
425
polars_ensure!(index < self.len(), oob = index, self.len());
426
// SAFETY: Just did bounds check
427
let value = unsafe { self.get_unchecked(index) };
428
Ok(value)
429
}
430
431
/// Get a single value by index. Don't use this operation for loops as a runtime cast is
432
/// needed for every iteration.
433
///
434
/// This may refer to physical types
435
///
436
/// # Safety
437
/// Does not do any bounds checking
438
unsafe fn get_unchecked(&self, _index: usize) -> AnyValue<'_>;
439
440
fn sort_with(&self, _options: SortOptions) -> PolarsResult<Series> {
441
polars_bail!(opq = sort_with, self._dtype());
442
}
443
444
/// Retrieve the indexes needed for a sort.
445
#[allow(unused)]
446
fn arg_sort(&self, options: SortOptions) -> IdxCa {
447
invalid_operation_panic!(arg_sort, self)
448
}
449
450
/// Count the null values.
451
fn null_count(&self) -> usize;
452
453
/// Return if any the chunks in this [`ChunkedArray`] have nulls.
454
fn has_nulls(&self) -> bool;
455
456
/// Get unique values in the Series.
457
fn unique(&self) -> PolarsResult<Series> {
458
polars_bail!(opq = unique, self._dtype());
459
}
460
461
/// Get unique values in the Series.
462
///
463
/// A `null` value also counts as a unique value.
464
fn n_unique(&self) -> PolarsResult<usize> {
465
polars_bail!(opq = n_unique, self._dtype());
466
}
467
468
/// Get first indexes of unique values.
469
fn arg_unique(&self) -> PolarsResult<IdxCa> {
470
polars_bail!(opq = arg_unique, self._dtype());
471
}
472
473
/// Get dense ids for each unique value.
474
///
475
/// Returns: (n_unique, unique_ids)
476
fn unique_id(&self) -> PolarsResult<(IdxSize, Vec<IdxSize>)>;
477
478
/// Get a mask of the null values.
479
fn is_null(&self) -> BooleanChunked;
480
481
/// Get a mask of the non-null values.
482
fn is_not_null(&self) -> BooleanChunked;
483
484
/// return a Series in reversed order
485
fn reverse(&self) -> Series;
486
487
/// Rechunk and return a pointer to the start of the Series.
488
/// Only implemented for numeric types
489
fn as_single_ptr(&mut self) -> PolarsResult<usize> {
490
polars_bail!(opq = as_single_ptr, self._dtype());
491
}
492
493
/// Shift the values by a given period and fill the parts that will be empty due to this operation
494
/// with `Nones`.
495
///
496
/// *NOTE: If you want to fill the Nones with a value use the
497
/// [`shift` operation on `ChunkedArray<T>`](../chunked_array/ops/trait.ChunkShift.html).*
498
///
499
/// # Example
500
///
501
/// ```rust
502
/// # use polars_core::prelude::*;
503
/// fn example() -> PolarsResult<()> {
504
/// let s = Series::new("series".into(), &[1, 2, 3]);
505
///
506
/// let shifted = s.shift(1);
507
/// assert_eq!(Vec::from(shifted.i32()?), &[None, Some(1), Some(2)]);
508
///
509
/// let shifted = s.shift(-1);
510
/// assert_eq!(Vec::from(shifted.i32()?), &[Some(2), Some(3), None]);
511
///
512
/// let shifted = s.shift(2);
513
/// assert_eq!(Vec::from(shifted.i32()?), &[None, None, Some(1)]);
514
///
515
/// Ok(())
516
/// }
517
/// example();
518
/// ```
519
fn shift(&self, _periods: i64) -> Series;
520
521
/// Get the sum of the Series as a new Scalar.
522
///
523
/// If the [`DataType`] is one of `{Int8, UInt8, Int16, UInt16}` the `Series` is
524
/// first cast to `Int64` to prevent overflow issues.
525
fn sum_reduce(&self) -> PolarsResult<Scalar> {
526
polars_bail!(opq = sum, self._dtype());
527
}
528
/// Get the max of the Series as a new Series of length 1.
529
fn max_reduce(&self) -> PolarsResult<Scalar> {
530
polars_bail!(opq = max, self._dtype());
531
}
532
/// Get the min of the Series as a new Series of length 1.
533
fn min_reduce(&self) -> PolarsResult<Scalar> {
534
polars_bail!(opq = min, self._dtype());
535
}
536
/// Get the median of the Series as a new Series of length 1.
537
fn median_reduce(&self) -> PolarsResult<Scalar> {
538
polars_bail!(opq = median, self._dtype());
539
}
540
/// Get the mean of the Series as a new Scalar
541
fn mean_reduce(&self) -> PolarsResult<Scalar> {
542
polars_bail!(opq = mean, self._dtype());
543
}
544
/// Get the variance of the Series as a new Series of length 1.
545
fn var_reduce(&self, _ddof: u8) -> PolarsResult<Scalar> {
546
polars_bail!(opq = var, self._dtype());
547
}
548
/// Get the standard deviation of the Series as a new Series of length 1.
549
fn std_reduce(&self, _ddof: u8) -> PolarsResult<Scalar> {
550
polars_bail!(opq = std, self._dtype());
551
}
552
/// Get the quantile of the Series as a new Series of length 1.
553
fn quantile_reduce(&self, _quantile: f64, _method: QuantileMethod) -> PolarsResult<Scalar> {
554
polars_bail!(opq = quantile, self._dtype());
555
}
556
/// Get multiple quantiles of the ChunkedArray as a new `List` Scalar
557
fn quantiles_reduce(
558
&self,
559
_quantiles: &[f64],
560
_method: QuantileMethod,
561
) -> PolarsResult<Scalar> {
562
polars_bail!(opq = quantiles, self._dtype());
563
}
564
/// Get the bitwise AND of the Series as a new Series of length 1,
565
fn and_reduce(&self) -> PolarsResult<Scalar> {
566
polars_bail!(opq = and_reduce, self._dtype());
567
}
568
/// Get the bitwise OR of the Series as a new Series of length 1,
569
fn or_reduce(&self) -> PolarsResult<Scalar> {
570
polars_bail!(opq = or_reduce, self._dtype());
571
}
572
/// Get the bitwise XOR of the Series as a new Series of length 1,
573
fn xor_reduce(&self) -> PolarsResult<Scalar> {
574
polars_bail!(opq = xor_reduce, self._dtype());
575
}
576
577
/// Get the first element of the [`Series`] as a [`Scalar`]
578
///
579
/// If the [`Series`] is empty, a [`Scalar`] with a [`AnyValue::Null`] is returned.
580
fn first(&self) -> Scalar {
581
let dt = self.dtype();
582
let av = self.get(0).map_or(AnyValue::Null, AnyValue::into_static);
583
584
Scalar::new(dt.clone(), av)
585
}
586
587
/// Get the first non-null element of the [`Series`] as a [`Scalar`]
588
///
589
/// If the [`Series`] is empty, a [`Scalar`] with a [`AnyValue::Null`] is returned.
590
fn first_non_null(&self) -> Scalar {
591
let av = if self.len() == 0 {
592
AnyValue::Null
593
} else {
594
let idx = if self.has_nulls() {
595
first_non_null(self.chunks().iter().map(|c| c.as_ref())).unwrap_or(0)
596
} else {
597
0
598
};
599
self.get(idx).map_or(AnyValue::Null, AnyValue::into_static)
600
};
601
Scalar::new(self.dtype().clone(), av)
602
}
603
604
/// Get the last element of the [`Series`] as a [`Scalar`]
605
///
606
/// If the [`Series`] is empty, a [`Scalar`] with a [`AnyValue::Null`] is returned.
607
fn last(&self) -> Scalar {
608
let dt = self.dtype();
609
let av = if self.len() == 0 {
610
AnyValue::Null
611
} else {
612
// SAFETY: len-1 < len if len != 0
613
unsafe { self.get_unchecked(self.len() - 1) }.into_static()
614
};
615
616
Scalar::new(dt.clone(), av)
617
}
618
619
/// Get the last non-null element of the [`Series`] as a [`Scalar`]
620
///
621
/// If the [`Series`] is empty, a [`Scalar`] with a [`AnyValue::Null`] is returned.
622
fn last_non_null(&self) -> Scalar {
623
let n = self.len();
624
let av = if n == 0 {
625
AnyValue::Null
626
} else {
627
let idx = if self.has_nulls() {
628
last_non_null(self.chunks().iter().map(|c| c.as_ref()), n).unwrap_or(n - 1)
629
} else {
630
n - 1
631
};
632
// SAFETY: len-1 < len if len != 0
633
unsafe { self.get_unchecked(idx) }.into_static()
634
};
635
Scalar::new(self.dtype().clone(), av)
636
}
637
638
#[cfg(feature = "approx_unique")]
639
fn approx_n_unique(&self) -> PolarsResult<IdxSize> {
640
polars_bail!(opq = approx_n_unique, self._dtype());
641
}
642
643
/// Clone inner ChunkedArray and wrap in a new Arc
644
fn clone_inner(&self) -> Arc<dyn SeriesTrait>;
645
646
#[cfg(feature = "object")]
647
/// Get the value at this index as a downcastable Any trait ref.
648
fn get_object(&self, _index: usize) -> Option<&dyn PolarsObjectSafe> {
649
invalid_operation_panic!(get_object, self)
650
}
651
652
#[cfg(feature = "object")]
653
/// Get the value at this index as a downcastable Any trait ref.
654
///
655
/// # Safety
656
/// This function doesn't do any bound checks.
657
unsafe fn get_object_chunked_unchecked(
658
&self,
659
_chunk: usize,
660
_index: usize,
661
) -> Option<&dyn PolarsObjectSafe> {
662
invalid_operation_panic!(get_object_chunked_unchecked, self)
663
}
664
665
/// Get a hold of the [`ChunkedArray`], [`Logical`] or `NullChunked` as an `Any` trait
666
/// reference.
667
fn as_any(&self) -> &dyn Any;
668
669
/// Get a hold of the [`ChunkedArray`], [`Logical`] or `NullChunked` as an `Any` trait mutable
670
/// reference.
671
fn as_any_mut(&mut self) -> &mut dyn Any;
672
673
/// Get a hold of the [`ChunkedArray`] or `NullChunked` as an `Any` trait reference. This
674
/// pierces through `Logical` types to get the underlying physical array.
675
fn as_phys_any(&self) -> &dyn Any;
676
677
fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
678
679
#[cfg(feature = "checked_arithmetic")]
680
fn checked_div(&self, _rhs: &Series) -> PolarsResult<Series> {
681
polars_bail!(opq = checked_div, self._dtype());
682
}
683
684
#[cfg(feature = "rolling_window")]
685
/// Apply a custom function over a rolling/ moving window of the array.
686
/// This has quite some dynamic dispatch, so prefer rolling_min, max, mean, sum over this.
687
fn rolling_map(
688
&self,
689
_f: &dyn Fn(&Series) -> PolarsResult<Series>,
690
_options: RollingOptionsFixedWindow,
691
) -> PolarsResult<Series> {
692
polars_bail!(opq = rolling_map, self._dtype());
693
}
694
}
695
696
impl dyn SeriesTrait + '_ {
697
pub fn unpack<T: PolarsPhysicalType>(&self) -> PolarsResult<&ChunkedArray<T>> {
698
polars_ensure!(&T::get_static_dtype() == self.dtype(), unpack);
699
Ok(self.as_ref())
700
}
701
}
702
703