Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/series/implementations/duration.rs
6940 views
1
use polars_compute::rolling::QuantileMethod;
2
3
use super::*;
4
use crate::chunked_array::comparison::*;
5
#[cfg(feature = "algorithm_group_by")]
6
use crate::frame::group_by::*;
7
use crate::prelude::*;
8
9
unsafe impl IntoSeries for DurationChunked {
10
fn into_series(self) -> Series {
11
Series(Arc::new(SeriesWrap(self)))
12
}
13
}
14
15
impl private::PrivateSeriesNumeric for SeriesWrap<DurationChunked> {
16
fn bit_repr(&self) -> Option<BitRepr> {
17
Some(self.0.physical().to_bit_repr())
18
}
19
}
20
21
impl private::PrivateSeries for SeriesWrap<DurationChunked> {
22
fn compute_len(&mut self) {
23
self.0.physical_mut().compute_len()
24
}
25
fn _field(&self) -> Cow<'_, Field> {
26
Cow::Owned(self.0.field())
27
}
28
fn _dtype(&self) -> &DataType {
29
self.0.dtype()
30
}
31
32
fn _set_flags(&mut self, flags: StatisticsFlags) {
33
self.0.physical_mut().set_flags(flags)
34
}
35
36
fn _get_flags(&self) -> StatisticsFlags {
37
self.0.physical().get_flags()
38
}
39
40
unsafe fn equal_element(&self, idx_self: usize, idx_other: usize, other: &Series) -> bool {
41
self.0.physical().equal_element(idx_self, idx_other, other)
42
}
43
44
#[cfg(feature = "zip_with")]
45
fn zip_with_same_type(&self, mask: &BooleanChunked, other: &Series) -> PolarsResult<Series> {
46
let other = other.to_physical_repr().into_owned();
47
self.0
48
.physical()
49
.zip_with(mask, other.as_ref().as_ref())
50
.map(|ca| ca.into_duration(self.0.time_unit()).into_series())
51
}
52
53
fn into_total_eq_inner<'a>(&'a self) -> Box<dyn TotalEqInner + 'a> {
54
self.0.physical().into_total_eq_inner()
55
}
56
fn into_total_ord_inner<'a>(&'a self) -> Box<dyn TotalOrdInner + 'a> {
57
self.0.physical().into_total_ord_inner()
58
}
59
60
fn vec_hash(
61
&self,
62
random_state: PlSeedableRandomStateQuality,
63
buf: &mut Vec<u64>,
64
) -> PolarsResult<()> {
65
self.0.physical().vec_hash(random_state, buf)?;
66
Ok(())
67
}
68
69
fn vec_hash_combine(
70
&self,
71
build_hasher: PlSeedableRandomStateQuality,
72
hashes: &mut [u64],
73
) -> PolarsResult<()> {
74
self.0.physical().vec_hash_combine(build_hasher, hashes)?;
75
Ok(())
76
}
77
78
#[cfg(feature = "algorithm_group_by")]
79
unsafe fn agg_min(&self, groups: &GroupsType) -> Series {
80
self.0
81
.physical()
82
.agg_min(groups)
83
.into_duration(self.0.time_unit())
84
.into_series()
85
}
86
87
#[cfg(feature = "algorithm_group_by")]
88
unsafe fn agg_max(&self, groups: &GroupsType) -> Series {
89
self.0
90
.physical()
91
.agg_max(groups)
92
.into_duration(self.0.time_unit())
93
.into_series()
94
}
95
96
#[cfg(feature = "algorithm_group_by")]
97
unsafe fn agg_sum(&self, groups: &GroupsType) -> Series {
98
self.0
99
.physical()
100
.agg_sum(groups)
101
.into_duration(self.0.time_unit())
102
.into_series()
103
}
104
105
#[cfg(feature = "algorithm_group_by")]
106
unsafe fn agg_std(&self, groups: &GroupsType, ddof: u8) -> Series {
107
self.0
108
.physical()
109
.agg_std(groups, ddof)
110
// cast f64 back to physical type
111
.cast(&DataType::Int64)
112
.unwrap()
113
.into_duration(self.0.time_unit())
114
.into_series()
115
}
116
117
#[cfg(feature = "algorithm_group_by")]
118
unsafe fn agg_var(&self, groups: &GroupsType, ddof: u8) -> Series {
119
self.0
120
.physical()
121
.agg_var(groups, ddof)
122
// cast f64 back to physical type
123
.cast(&DataType::Int64)
124
.unwrap()
125
.into_duration(self.0.time_unit())
126
.into_series()
127
}
128
129
#[cfg(feature = "algorithm_group_by")]
130
unsafe fn agg_list(&self, groups: &GroupsType) -> Series {
131
// we cannot cast and dispatch as the inner type of the list would be incorrect
132
self.0
133
.physical()
134
.agg_list(groups)
135
.cast(&DataType::List(Box::new(self.dtype().clone())))
136
.unwrap()
137
}
138
139
fn subtract(&self, rhs: &Series) -> PolarsResult<Series> {
140
match (self.dtype(), rhs.dtype()) {
141
(DataType::Duration(tu), DataType::Duration(tur)) => {
142
polars_ensure!(tu == tur, InvalidOperation: "units are different");
143
let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
144
let rhs = rhs.cast(&DataType::Int64).unwrap();
145
Ok(lhs.subtract(&rhs)?.into_duration(*tu).into_series())
146
},
147
(dtl, dtr) => polars_bail!(opq = sub, dtl, dtr),
148
}
149
}
150
fn add_to(&self, rhs: &Series) -> PolarsResult<Series> {
151
match (self.dtype(), rhs.dtype()) {
152
(DataType::Duration(tu), DataType::Duration(tur)) => {
153
polars_ensure!(tu == tur, InvalidOperation: "units are different");
154
let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
155
let rhs = rhs.cast(&DataType::Int64).unwrap();
156
Ok(lhs.add_to(&rhs)?.into_duration(*tu).into_series())
157
},
158
(DataType::Duration(tu), DataType::Date) => {
159
let one_day_in_tu: i64 = match tu {
160
TimeUnit::Milliseconds => 86_400_000,
161
TimeUnit::Microseconds => 86_400_000_000,
162
TimeUnit::Nanoseconds => 86_400_000_000_000,
163
};
164
let lhs =
165
self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap() / one_day_in_tu;
166
let rhs = rhs
167
.cast(&DataType::Int32)
168
.unwrap()
169
.cast(&DataType::Int64)
170
.unwrap();
171
Ok(lhs
172
.add_to(&rhs)?
173
.cast(&DataType::Int32)?
174
.into_date()
175
.into_series())
176
},
177
(DataType::Duration(tu), DataType::Datetime(tur, tz)) => {
178
polars_ensure!(tu == tur, InvalidOperation: "units are different");
179
let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
180
let rhs = rhs.cast(&DataType::Int64).unwrap();
181
Ok(lhs
182
.add_to(&rhs)?
183
.into_datetime(*tu, tz.clone())
184
.into_series())
185
},
186
(dtl, dtr) => polars_bail!(opq = add, dtl, dtr),
187
}
188
}
189
fn multiply(&self, rhs: &Series) -> PolarsResult<Series> {
190
let tul = self.0.time_unit();
191
match rhs.dtype() {
192
DataType::Int64 => Ok((&self.0.phys * rhs.i64().unwrap())
193
.into_duration(tul)
194
.into_series()),
195
dt if dt.is_integer() => {
196
let rhs = rhs.cast(&DataType::Int64)?;
197
self.multiply(&rhs)
198
},
199
dt if dt.is_float() => {
200
let phys = &self.0.phys;
201
let phys_float = phys.cast(dt).unwrap();
202
let out = std::ops::Mul::mul(&phys_float, rhs)?
203
.cast(&DataType::Int64)
204
.unwrap();
205
let phys = out.i64().unwrap().clone();
206
Ok(phys.into_duration(tul).into_series())
207
},
208
_ => {
209
polars_bail!(opq = mul, self.dtype(), rhs.dtype());
210
},
211
}
212
}
213
fn divide(&self, rhs: &Series) -> PolarsResult<Series> {
214
let tul = self.0.time_unit();
215
match rhs.dtype() {
216
DataType::Duration(tur) => {
217
if tul == *tur {
218
// Returns a constant as f64.
219
Ok(std::ops::Div::div(
220
&self.0.phys.cast(&DataType::Float64).unwrap(),
221
&rhs.duration()
222
.unwrap()
223
.phys
224
.cast(&DataType::Float64)
225
.unwrap(),
226
)?
227
.into_series())
228
} else {
229
let rhs = rhs.cast(self.dtype())?;
230
self.divide(&rhs)
231
}
232
},
233
DataType::Int64 => Ok((&self.0.phys / rhs.i64().unwrap())
234
.into_duration(tul)
235
.into_series()),
236
dt if dt.is_integer() => {
237
let rhs = rhs.cast(&DataType::Int64)?;
238
self.divide(&rhs)
239
},
240
dt if dt.is_float() => {
241
let phys = &self.0.phys;
242
let phys_float = phys.cast(dt).unwrap();
243
let out = std::ops::Div::div(&phys_float, rhs)?
244
.cast(&DataType::Int64)
245
.unwrap();
246
let phys = out.i64().unwrap().clone();
247
Ok(phys.into_duration(tul).into_series())
248
},
249
_ => {
250
polars_bail!(opq = div, self.dtype(), rhs.dtype());
251
},
252
}
253
}
254
fn remainder(&self, rhs: &Series) -> PolarsResult<Series> {
255
polars_ensure!(self.dtype() == rhs.dtype(), InvalidOperation: "dtypes and units must be equal in duration arithmetic");
256
let lhs = self.cast(&DataType::Int64, CastOptions::NonStrict).unwrap();
257
let rhs = rhs.cast(&DataType::Int64).unwrap();
258
Ok(lhs
259
.remainder(&rhs)?
260
.into_duration(self.0.time_unit())
261
.into_series())
262
}
263
#[cfg(feature = "algorithm_group_by")]
264
fn group_tuples(&self, multithreaded: bool, sorted: bool) -> PolarsResult<GroupsType> {
265
self.0.physical().group_tuples(multithreaded, sorted)
266
}
267
268
fn arg_sort_multiple(
269
&self,
270
by: &[Column],
271
options: &SortMultipleOptions,
272
) -> PolarsResult<IdxCa> {
273
self.0.physical().arg_sort_multiple(by, options)
274
}
275
}
276
277
impl SeriesTrait for SeriesWrap<DurationChunked> {
278
fn rename(&mut self, name: PlSmallStr) {
279
self.0.rename(name);
280
}
281
282
fn chunk_lengths(&self) -> ChunkLenIter<'_> {
283
self.0.physical().chunk_lengths()
284
}
285
fn name(&self) -> &PlSmallStr {
286
self.0.name()
287
}
288
289
fn chunks(&self) -> &Vec<ArrayRef> {
290
self.0.physical().chunks()
291
}
292
unsafe fn chunks_mut(&mut self) -> &mut Vec<ArrayRef> {
293
self.0.physical_mut().chunks_mut()
294
}
295
296
fn shrink_to_fit(&mut self) {
297
self.0.physical_mut().shrink_to_fit()
298
}
299
300
fn slice(&self, offset: i64, length: usize) -> Series {
301
self.0.slice(offset, length).into_series()
302
}
303
304
fn split_at(&self, offset: i64) -> (Series, Series) {
305
let (a, b) = self.0.split_at(offset);
306
(a.into_series(), b.into_series())
307
}
308
309
fn _sum_as_f64(&self) -> f64 {
310
self.0.physical()._sum_as_f64()
311
}
312
313
fn mean(&self) -> Option<f64> {
314
self.0.physical().mean()
315
}
316
317
fn median(&self) -> Option<f64> {
318
self.0.physical().median()
319
}
320
321
fn std(&self, ddof: u8) -> Option<f64> {
322
self.0.physical().std(ddof)
323
}
324
325
fn var(&self, ddof: u8) -> Option<f64> {
326
self.0.physical().var(ddof)
327
}
328
329
fn append(&mut self, other: &Series) -> PolarsResult<()> {
330
polars_ensure!(self.0.dtype() == other.dtype(), append);
331
let mut other = other.to_physical_repr().into_owned();
332
self.0
333
.physical_mut()
334
.append_owned(std::mem::take(other._get_inner_mut().as_mut()))
335
}
336
fn append_owned(&mut self, mut other: Series) -> PolarsResult<()> {
337
polars_ensure!(self.0.dtype() == other.dtype(), append);
338
self.0.physical_mut().append_owned(std::mem::take(
339
&mut other
340
._get_inner_mut()
341
.as_any_mut()
342
.downcast_mut::<DurationChunked>()
343
.unwrap()
344
.phys,
345
))
346
}
347
348
fn extend(&mut self, other: &Series) -> PolarsResult<()> {
349
polars_ensure!(self.0.dtype() == other.dtype(), extend);
350
let other = other.to_physical_repr();
351
self.0
352
.physical_mut()
353
.extend(other.as_ref().as_ref().as_ref())?;
354
Ok(())
355
}
356
357
fn filter(&self, filter: &BooleanChunked) -> PolarsResult<Series> {
358
self.0
359
.physical()
360
.filter(filter)
361
.map(|ca| ca.into_duration(self.0.time_unit()).into_series())
362
}
363
364
fn take(&self, indices: &IdxCa) -> PolarsResult<Series> {
365
Ok(self
366
.0
367
.physical()
368
.take(indices)?
369
.into_duration(self.0.time_unit())
370
.into_series())
371
}
372
373
unsafe fn take_unchecked(&self, indices: &IdxCa) -> Series {
374
self.0
375
.physical()
376
.take_unchecked(indices)
377
.into_duration(self.0.time_unit())
378
.into_series()
379
}
380
381
fn take_slice(&self, indices: &[IdxSize]) -> PolarsResult<Series> {
382
Ok(self
383
.0
384
.physical()
385
.take(indices)?
386
.into_duration(self.0.time_unit())
387
.into_series())
388
}
389
390
unsafe fn take_slice_unchecked(&self, indices: &[IdxSize]) -> Series {
391
self.0
392
.physical()
393
.take_unchecked(indices)
394
.into_duration(self.0.time_unit())
395
.into_series()
396
}
397
398
fn len(&self) -> usize {
399
self.0.len()
400
}
401
402
fn rechunk(&self) -> Series {
403
self.0
404
.physical()
405
.rechunk()
406
.into_owned()
407
.into_duration(self.0.time_unit())
408
.into_series()
409
}
410
411
fn new_from_index(&self, index: usize, length: usize) -> Series {
412
self.0
413
.physical()
414
.new_from_index(index, length)
415
.into_duration(self.0.time_unit())
416
.into_series()
417
}
418
419
fn cast(&self, dtype: &DataType, cast_options: CastOptions) -> PolarsResult<Series> {
420
self.0.cast_with_options(dtype, cast_options)
421
}
422
423
#[inline]
424
unsafe fn get_unchecked(&self, index: usize) -> AnyValue<'_> {
425
self.0.get_any_value_unchecked(index)
426
}
427
428
fn sort_with(&self, options: SortOptions) -> PolarsResult<Series> {
429
Ok(self
430
.0
431
.physical()
432
.sort_with(options)
433
.into_duration(self.0.time_unit())
434
.into_series())
435
}
436
437
fn arg_sort(&self, options: SortOptions) -> IdxCa {
438
self.0.physical().arg_sort(options)
439
}
440
441
fn null_count(&self) -> usize {
442
self.0.null_count()
443
}
444
445
fn has_nulls(&self) -> bool {
446
self.0.has_nulls()
447
}
448
449
#[cfg(feature = "algorithm_group_by")]
450
fn unique(&self) -> PolarsResult<Series> {
451
self.0
452
.physical()
453
.unique()
454
.map(|ca| ca.into_duration(self.0.time_unit()).into_series())
455
}
456
457
#[cfg(feature = "algorithm_group_by")]
458
fn n_unique(&self) -> PolarsResult<usize> {
459
self.0.physical().n_unique()
460
}
461
462
#[cfg(feature = "algorithm_group_by")]
463
fn arg_unique(&self) -> PolarsResult<IdxCa> {
464
self.0.physical().arg_unique()
465
}
466
467
fn is_null(&self) -> BooleanChunked {
468
self.0.is_null()
469
}
470
471
fn is_not_null(&self) -> BooleanChunked {
472
self.0.is_not_null()
473
}
474
475
fn reverse(&self) -> Series {
476
self.0
477
.physical()
478
.reverse()
479
.into_duration(self.0.time_unit())
480
.into_series()
481
}
482
483
fn as_single_ptr(&mut self) -> PolarsResult<usize> {
484
self.0.physical_mut().as_single_ptr()
485
}
486
487
fn shift(&self, periods: i64) -> Series {
488
self.0
489
.physical()
490
.shift(periods)
491
.into_duration(self.0.time_unit())
492
.into_series()
493
}
494
495
fn sum_reduce(&self) -> PolarsResult<Scalar> {
496
let sc = self.0.physical().sum_reduce();
497
let v = sc.value().as_duration(self.0.time_unit());
498
Ok(Scalar::new(self.dtype().clone(), v))
499
}
500
501
fn max_reduce(&self) -> PolarsResult<Scalar> {
502
let sc = self.0.physical().max_reduce();
503
let v = sc.value().as_duration(self.0.time_unit());
504
Ok(Scalar::new(self.dtype().clone(), v))
505
}
506
fn min_reduce(&self) -> PolarsResult<Scalar> {
507
let sc = self.0.physical().min_reduce();
508
let v = sc.value().as_duration(self.0.time_unit());
509
Ok(Scalar::new(self.dtype().clone(), v))
510
}
511
fn std_reduce(&self, ddof: u8) -> PolarsResult<Scalar> {
512
let sc = self.0.physical().std_reduce(ddof);
513
let to = self.dtype().to_physical();
514
let v = sc.value().cast(&to);
515
Ok(Scalar::new(
516
self.dtype().clone(),
517
v.as_duration(self.0.time_unit()),
518
))
519
}
520
521
fn median_reduce(&self) -> PolarsResult<Scalar> {
522
let v: AnyValue = self.median().map(|v| v as i64).into();
523
let to = self.dtype().to_physical();
524
let v = v.cast(&to);
525
Ok(Scalar::new(
526
self.dtype().clone(),
527
v.as_duration(self.0.time_unit()),
528
))
529
}
530
fn quantile_reduce(&self, quantile: f64, method: QuantileMethod) -> PolarsResult<Scalar> {
531
let v = self.0.physical().quantile_reduce(quantile, method)?;
532
let to = self.dtype().to_physical();
533
let v = v.value().cast(&to);
534
Ok(Scalar::new(
535
self.dtype().clone(),
536
v.as_duration(self.0.time_unit()),
537
))
538
}
539
540
fn clone_inner(&self) -> Arc<dyn SeriesTrait> {
541
Arc::new(SeriesWrap(Clone::clone(&self.0)))
542
}
543
544
fn find_validity_mismatch(&self, other: &Series, idxs: &mut Vec<IdxSize>) {
545
self.0.physical().find_validity_mismatch(other, idxs)
546
}
547
548
fn as_any(&self) -> &dyn Any {
549
&self.0
550
}
551
552
fn as_any_mut(&mut self) -> &mut dyn Any {
553
&mut self.0
554
}
555
556
fn as_phys_any(&self) -> &dyn Any {
557
self.0.physical()
558
}
559
560
fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
561
self as _
562
}
563
}
564
565