polars-df 0.8.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -1
  3. data/Cargo.lock +159 -66
  4. data/Cargo.toml +0 -3
  5. data/LICENSE.txt +1 -1
  6. data/README.md +3 -2
  7. data/ext/polars/Cargo.toml +18 -8
  8. data/ext/polars/src/batched_csv.rs +7 -5
  9. data/ext/polars/src/conversion/anyvalue.rs +186 -0
  10. data/ext/polars/src/conversion/chunked_array.rs +140 -0
  11. data/ext/polars/src/{conversion.rs → conversion/mod.rs} +273 -342
  12. data/ext/polars/src/dataframe.rs +108 -66
  13. data/ext/polars/src/expr/array.rs +78 -0
  14. data/ext/polars/src/expr/datetime.rs +29 -58
  15. data/ext/polars/src/expr/general.rs +83 -36
  16. data/ext/polars/src/expr/list.rs +58 -6
  17. data/ext/polars/src/expr/meta.rs +48 -0
  18. data/ext/polars/src/expr/rolling.rs +1 -0
  19. data/ext/polars/src/expr/string.rs +62 -11
  20. data/ext/polars/src/expr/struct.rs +8 -4
  21. data/ext/polars/src/file.rs +158 -11
  22. data/ext/polars/src/functions/aggregation.rs +6 -0
  23. data/ext/polars/src/functions/lazy.rs +120 -50
  24. data/ext/polars/src/functions/meta.rs +45 -1
  25. data/ext/polars/src/functions/string_cache.rs +14 -0
  26. data/ext/polars/src/functions/whenthen.rs +47 -17
  27. data/ext/polars/src/{lazyframe.rs → lazyframe/mod.rs} +195 -40
  28. data/ext/polars/src/lib.rs +246 -179
  29. data/ext/polars/src/map/dataframe.rs +17 -9
  30. data/ext/polars/src/series/aggregation.rs +20 -0
  31. data/ext/polars/src/series/mod.rs +35 -4
  32. data/lib/polars/array_expr.rb +453 -0
  33. data/lib/polars/array_name_space.rb +346 -0
  34. data/lib/polars/batched_csv_reader.rb +4 -2
  35. data/lib/polars/cat_expr.rb +24 -0
  36. data/lib/polars/cat_name_space.rb +75 -0
  37. data/lib/polars/config.rb +2 -2
  38. data/lib/polars/data_frame.rb +306 -96
  39. data/lib/polars/data_types.rb +191 -28
  40. data/lib/polars/date_time_expr.rb +41 -18
  41. data/lib/polars/date_time_name_space.rb +9 -3
  42. data/lib/polars/exceptions.rb +12 -1
  43. data/lib/polars/expr.rb +898 -215
  44. data/lib/polars/functions/aggregation/horizontal.rb +246 -0
  45. data/lib/polars/functions/aggregation/vertical.rb +282 -0
  46. data/lib/polars/functions/as_datatype.rb +248 -0
  47. data/lib/polars/functions/col.rb +47 -0
  48. data/lib/polars/functions/eager.rb +182 -0
  49. data/lib/polars/functions/lazy.rb +1280 -0
  50. data/lib/polars/functions/len.rb +49 -0
  51. data/lib/polars/functions/lit.rb +35 -0
  52. data/lib/polars/functions/random.rb +16 -0
  53. data/lib/polars/functions/range/date_range.rb +103 -0
  54. data/lib/polars/functions/range/int_range.rb +51 -0
  55. data/lib/polars/functions/repeat.rb +144 -0
  56. data/lib/polars/functions/whenthen.rb +96 -0
  57. data/lib/polars/functions.rb +29 -416
  58. data/lib/polars/group_by.rb +2 -2
  59. data/lib/polars/io.rb +36 -31
  60. data/lib/polars/lazy_frame.rb +405 -88
  61. data/lib/polars/list_expr.rb +158 -8
  62. data/lib/polars/list_name_space.rb +102 -0
  63. data/lib/polars/meta_expr.rb +175 -7
  64. data/lib/polars/series.rb +282 -41
  65. data/lib/polars/string_cache.rb +75 -0
  66. data/lib/polars/string_expr.rb +413 -96
  67. data/lib/polars/string_name_space.rb +4 -4
  68. data/lib/polars/testing.rb +507 -0
  69. data/lib/polars/utils.rb +106 -8
  70. data/lib/polars/version.rb +1 -1
  71. data/lib/polars/whenthen.rb +83 -0
  72. data/lib/polars.rb +16 -4
  73. metadata +37 -8
  74. data/lib/polars/lazy_functions.rb +0 -1181
  75. data/lib/polars/when.rb +0 -16
  76. data/lib/polars/when_then.rb +0 -19
@@ -6,16 +6,17 @@ use polars::frame::row::{rows_to_schema_supertypes, Row};
6
6
  use polars::frame::NullStrategy;
7
7
  use polars::io::avro::AvroCompression;
8
8
  use polars::io::mmap::ReaderBytes;
9
- use polars::io::RowCount;
9
+ use polars::io::RowIndex;
10
10
  use polars::prelude::pivot::{pivot, pivot_stable};
11
11
  use polars::prelude::*;
12
12
  use polars_core::utils::try_get_supertype;
13
13
  use std::cell::RefCell;
14
14
  use std::io::{BufWriter, Cursor};
15
+ use std::num::NonZeroUsize;
15
16
  use std::ops::Deref;
16
17
 
17
18
  use crate::conversion::*;
18
- use crate::file::{get_file_like, get_mmap_bytes_reader};
19
+ use crate::file::{get_either_file, get_file_like, get_mmap_bytes_reader, EitherRustRubyFile};
19
20
  use crate::map::dataframe::{
20
21
  apply_lambda_unknown, apply_lambda_with_bool_out_type, apply_lambda_with_primitive_out_type,
21
22
  apply_lambda_with_utf8_out_type,
@@ -45,44 +46,51 @@ impl RbDataFrame {
45
46
  fn finish_from_rows(
46
47
  rows: Vec<Row>,
47
48
  infer_schema_length: Option<usize>,
48
- schema_overwrite: Option<Schema>,
49
+ schema: Option<Schema>,
50
+ schema_overrides_by_idx: Option<Vec<(usize, DataType)>>,
49
51
  ) -> RbResult<Self> {
50
- // object builder must be registered.
52
+ // Object builder must be registered
51
53
  crate::on_startup::register_object_builder();
52
54
 
53
- let schema =
55
+ let mut final_schema =
54
56
  rows_to_schema_supertypes(&rows, infer_schema_length.map(|n| std::cmp::max(1, n)))
55
57
  .map_err(RbPolarsErr::from)?;
56
- // replace inferred nulls with boolean
57
- let fields = schema.iter_fields().map(|mut fld| match fld.data_type() {
58
- DataType::Null => {
59
- // fld.coerce(DataType::Boolean);
60
- fld
61
- }
62
- DataType::Decimal(_, _) => {
63
- fld.coerce(DataType::Decimal(None, None));
64
- fld
58
+
59
+ // Erase scale from inferred decimals.
60
+ for dtype in final_schema.iter_dtypes_mut() {
61
+ if let DataType::Decimal(_, _) = dtype {
62
+ *dtype = DataType::Decimal(None, None)
65
63
  }
66
- _ => fld,
67
- });
68
- let mut schema = Schema::from_iter(fields);
64
+ }
69
65
 
70
- if let Some(schema_overwrite) = schema_overwrite {
71
- for (i, (name, dtype)) in schema_overwrite.into_iter().enumerate() {
72
- if let Some((name_, dtype_)) = schema.get_at_index_mut(i) {
66
+ // Integrate explicit/inferred schema.
67
+ if let Some(schema) = schema {
68
+ for (i, (name, dtype)) in schema.into_iter().enumerate() {
69
+ if let Some((name_, dtype_)) = final_schema.get_at_index_mut(i) {
73
70
  *name_ = name;
74
71
 
75
- // if user sets dtype unknown, we use the inferred datatype
72
+ // If schema dtype is Unknown, overwrite with inferred datatype.
76
73
  if !matches!(dtype, DataType::Unknown) {
77
74
  *dtype_ = dtype;
78
75
  }
79
76
  } else {
80
- schema.with_column(name, dtype);
77
+ final_schema.with_column(name, dtype);
81
78
  }
82
79
  }
83
80
  }
84
81
 
85
- let df = DataFrame::from_rows_and_schema(&rows, &schema).map_err(RbPolarsErr::from)?;
82
+ // Optional per-field overrides; these supersede default/inferred dtypes.
83
+ if let Some(overrides) = schema_overrides_by_idx {
84
+ for (i, dtype) in overrides {
85
+ if let Some((_, dtype_)) = final_schema.get_at_index_mut(i) {
86
+ if !matches!(dtype, DataType::Unknown) {
87
+ *dtype_ = dtype;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ let df =
93
+ DataFrame::from_rows_and_schema(&rows, &final_schema).map_err(RbPolarsErr::from)?;
86
94
  Ok(df.into())
87
95
  }
88
96
 
@@ -125,15 +133,16 @@ impl RbDataFrame {
125
133
  let null_values = Option::<Wrap<NullValues>>::try_convert(arguments[19])?;
126
134
  let try_parse_dates = bool::try_convert(arguments[20])?;
127
135
  let skip_rows_after_header = usize::try_convert(arguments[21])?;
128
- let row_count = Option::<(String, IdxSize)>::try_convert(arguments[22])?;
136
+ let row_index = Option::<(String, IdxSize)>::try_convert(arguments[22])?;
129
137
  let sample_size = usize::try_convert(arguments[23])?;
130
138
  let eol_char = String::try_convert(arguments[24])?;
139
+ let truncate_ragged_lines = bool::try_convert(arguments[25])?;
131
140
  // end arguments
132
141
 
133
142
  let null_values = null_values.map(|w| w.0);
134
143
  let eol_char = eol_char.as_bytes()[0];
135
144
 
136
- let row_count = row_count.map(|(name, offset)| RowCount { name, offset });
145
+ let row_index = row_index.map(|(name, offset)| RowIndex { name, offset });
137
146
 
138
147
  let quote_char = if let Some(s) = quote_char {
139
148
  if s.is_empty() {
@@ -186,8 +195,9 @@ impl RbDataFrame {
186
195
  .with_quote_char(quote_char)
187
196
  .with_end_of_line_char(eol_char)
188
197
  .with_skip_rows_after_header(skip_rows_after_header)
189
- .with_row_count(row_count)
198
+ .with_row_index(row_index)
190
199
  .sample_size(sample_size)
200
+ .truncate_ragged_lines(truncate_ragged_lines)
191
201
  .finish()
192
202
  .map_err(RbPolarsErr::from)?;
193
203
  Ok(df.into())
@@ -200,24 +210,39 @@ impl RbDataFrame {
200
210
  projection: Option<Vec<usize>>,
201
211
  n_rows: Option<usize>,
202
212
  parallel: Wrap<ParallelStrategy>,
203
- row_count: Option<(String, IdxSize)>,
213
+ row_index: Option<(String, IdxSize)>,
204
214
  low_memory: bool,
205
215
  use_statistics: bool,
206
216
  rechunk: bool,
207
217
  ) -> RbResult<Self> {
208
- let row_count = row_count.map(|(name, offset)| RowCount { name, offset });
209
- let mmap_bytes_r = get_mmap_bytes_reader(rb_f)?;
210
- let df = ParquetReader::new(mmap_bytes_r)
211
- .with_projection(projection)
212
- .with_columns(columns)
213
- .read_parallel(parallel.0)
214
- .with_n_rows(n_rows)
215
- .with_row_count(row_count)
216
- .set_low_memory(low_memory)
217
- .use_statistics(use_statistics)
218
- .set_rechunk(rechunk)
219
- .finish()
220
- .map_err(RbPolarsErr::from)?;
218
+ use EitherRustRubyFile::*;
219
+
220
+ let row_index = row_index.map(|(name, offset)| RowIndex { name, offset });
221
+ let result = match get_either_file(rb_f, false)? {
222
+ Rb(f) => {
223
+ let buf = f.as_buffer();
224
+ ParquetReader::new(buf)
225
+ .with_projection(projection)
226
+ .with_columns(columns)
227
+ .read_parallel(parallel.0)
228
+ .with_n_rows(n_rows)
229
+ .with_row_index(row_index)
230
+ .set_low_memory(low_memory)
231
+ .use_statistics(use_statistics)
232
+ .set_rechunk(rechunk)
233
+ .finish()
234
+ }
235
+ Rust(f) => ParquetReader::new(f.into_inner())
236
+ .with_projection(projection)
237
+ .with_columns(columns)
238
+ .read_parallel(parallel.0)
239
+ .with_n_rows(n_rows)
240
+ .with_row_index(row_index)
241
+ .use_statistics(use_statistics)
242
+ .set_rechunk(rechunk)
243
+ .finish(),
244
+ };
245
+ let df = result.map_err(RbPolarsErr::from)?;
221
246
  Ok(RbDataFrame::new(df))
222
247
  }
223
248
 
@@ -226,16 +251,16 @@ impl RbDataFrame {
226
251
  columns: Option<Vec<String>>,
227
252
  projection: Option<Vec<usize>>,
228
253
  n_rows: Option<usize>,
229
- row_count: Option<(String, IdxSize)>,
254
+ row_index: Option<(String, IdxSize)>,
230
255
  memory_map: bool,
231
256
  ) -> RbResult<Self> {
232
- let row_count = row_count.map(|(name, offset)| RowCount { name, offset });
257
+ let row_index = row_index.map(|(name, offset)| RowIndex { name, offset });
233
258
  let mmap_bytes_r = get_mmap_bytes_reader(rb_f)?;
234
259
  let df = IpcReader::new(mmap_bytes_r)
235
260
  .with_projection(projection)
236
261
  .with_columns(columns)
237
262
  .with_n_rows(n_rows)
238
- .with_row_count(row_count)
263
+ .with_row_index(row_index)
239
264
  .memory_mapped(memory_map)
240
265
  .finish()
241
266
  .map_err(RbPolarsErr::from)?;
@@ -352,7 +377,7 @@ impl RbDataFrame {
352
377
  pub fn read_rows(
353
378
  rb_rows: RArray,
354
379
  infer_schema_length: Option<usize>,
355
- schema_overwrite: Option<Wrap<Schema>>,
380
+ schema: Option<Wrap<Schema>>,
356
381
  ) -> RbResult<Self> {
357
382
  let mut rows = Vec::with_capacity(rb_rows.len());
358
383
  for v in rb_rows.each() {
@@ -363,30 +388,34 @@ impl RbDataFrame {
363
388
  }
364
389
  rows.push(Row(row));
365
390
  }
366
- Self::finish_from_rows(
367
- rows,
368
- infer_schema_length,
369
- schema_overwrite.map(|wrap| wrap.0),
370
- )
391
+ Self::finish_from_rows(rows, infer_schema_length, schema.map(|wrap| wrap.0), None)
371
392
  }
372
393
 
373
394
  pub fn read_hashes(
374
395
  dicts: Value,
375
396
  infer_schema_length: Option<usize>,
376
- schema_overwrite: Option<Wrap<Schema>>,
397
+ schema: Option<Wrap<Schema>>,
398
+ schema_overrides: Option<Wrap<Schema>>,
377
399
  ) -> RbResult<Self> {
378
- let (rows, mut names) = dicts_to_rows(&dicts, infer_schema_length.unwrap_or(50))?;
400
+ let mut schema_columns = PlIndexSet::new();
401
+ if let Some(s) = &schema {
402
+ schema_columns.extend(s.0.iter_names().map(|n| n.to_string()))
403
+ }
404
+ let (rows, names) = dicts_to_rows(&dicts, infer_schema_length, schema_columns)?;
379
405
 
380
- // ensure the new names are used
381
- if let Some(schema) = &schema_overwrite {
382
- for (new_name, name) in schema.0.iter_names().zip(names.iter_mut()) {
383
- *name = new_name.to_string();
406
+ let mut schema_overrides_by_idx: Vec<(usize, DataType)> = Vec::new();
407
+ if let Some(overrides) = schema_overrides {
408
+ for (idx, name) in names.iter().enumerate() {
409
+ if let Some(dtype) = overrides.0.get(name) {
410
+ schema_overrides_by_idx.push((idx, dtype.clone()));
411
+ }
384
412
  }
385
413
  }
386
414
  let rbdf = Self::finish_from_rows(
387
415
  rows,
388
416
  infer_schema_length,
389
- schema_overwrite.map(|wrap| wrap.0),
417
+ schema.map(|wrap| wrap.0),
418
+ Some(schema_overrides_by_idx),
390
419
  )?;
391
420
 
392
421
  unsafe {
@@ -427,13 +456,14 @@ impl RbDataFrame {
427
456
  include_header: bool,
428
457
  separator: u8,
429
458
  quote_char: u8,
430
- batch_size: usize,
459
+ batch_size: Wrap<NonZeroUsize>,
431
460
  datetime_format: Option<String>,
432
461
  date_format: Option<String>,
433
462
  time_format: Option<String>,
434
463
  float_precision: Option<usize>,
435
464
  null_value: Option<String>,
436
465
  ) -> RbResult<()> {
466
+ let batch_size = batch_size.0;
437
467
  let null = null_value.unwrap_or_default();
438
468
 
439
469
  if let Ok(s) = String::try_convert(rb_f) {
@@ -563,6 +593,7 @@ impl RbDataFrame {
563
593
  compression_level: Option<i32>,
564
594
  statistics: bool,
565
595
  row_group_size: Option<usize>,
596
+ data_page_size: Option<usize>,
566
597
  ) -> RbResult<()> {
567
598
  let compression = parse_parquet_compression(&compression, compression_level)?;
568
599
 
@@ -572,10 +603,18 @@ impl RbDataFrame {
572
603
  .with_compression(compression)
573
604
  .with_statistics(statistics)
574
605
  .with_row_group_size(row_group_size)
606
+ .with_data_page_size(data_page_size)
575
607
  .finish(&mut self.df.borrow_mut())
576
608
  .map_err(RbPolarsErr::from)?;
577
609
  } else {
578
- todo!();
610
+ let buf = get_file_like(rb_f, true)?;
611
+ ParquetWriter::new(buf)
612
+ .with_compression(compression)
613
+ .with_statistics(statistics)
614
+ .with_row_group_size(row_group_size)
615
+ .with_data_page_size(data_page_size)
616
+ .finish(&mut self.df.borrow_mut())
617
+ .map_err(RbPolarsErr::from)?;
579
618
  }
580
619
 
581
620
  Ok(())
@@ -794,12 +833,11 @@ impl RbDataFrame {
794
833
  self.df.borrow().get_column_index(&name)
795
834
  }
796
835
 
797
- // TODO remove clone
798
- pub fn column(&self, name: String) -> RbResult<RbSeries> {
836
+ pub fn get_column(&self, name: String) -> RbResult<RbSeries> {
799
837
  self.df
800
838
  .borrow()
801
839
  .column(&name)
802
- .map(|v| v.clone().into())
840
+ .map(|s| RbSeries::new(s.clone()))
803
841
  .map_err(RbPolarsErr::from)
804
842
  }
805
843
 
@@ -887,11 +925,11 @@ impl RbDataFrame {
887
925
  }
888
926
  }
889
927
 
890
- pub fn with_row_count(&self, name: String, offset: Option<IdxSize>) -> RbResult<Self> {
928
+ pub fn with_row_index(&self, name: String, offset: Option<IdxSize>) -> RbResult<Self> {
891
929
  let df = self
892
930
  .df
893
931
  .borrow()
894
- .with_row_count(&name, offset)
932
+ .with_row_index(&name, offset)
895
933
  .map_err(RbPolarsErr::from)?;
896
934
  Ok(df.into())
897
935
  }
@@ -922,9 +960,9 @@ impl RbDataFrame {
922
960
  #[allow(clippy::too_many_arguments)]
923
961
  pub fn pivot_expr(
924
962
  &self,
925
- values: Vec<String>,
926
963
  index: Vec<String>,
927
964
  columns: Vec<String>,
965
+ values: Option<Vec<String>>,
928
966
  maintain_order: bool,
929
967
  sort_columns: bool,
930
968
  aggregate_expr: Option<&RbExpr>,
@@ -937,9 +975,9 @@ impl RbDataFrame {
937
975
  let agg_expr = aggregate_expr.map(|aggregate_expr| aggregate_expr.inner.clone());
938
976
  let df = fun(
939
977
  &self.df.borrow(),
940
- values,
941
978
  index,
942
979
  columns,
980
+ values,
943
981
  sort_columns,
944
982
  agg_expr,
945
983
  separator.as_deref(),
@@ -1121,7 +1159,7 @@ impl RbDataFrame {
1121
1159
  };
1122
1160
  Ok(self
1123
1161
  .df
1124
- .borrow()
1162
+ .borrow_mut()
1125
1163
  .transpose(keep_names_as.as_deref(), new_col_names)
1126
1164
  .map_err(RbPolarsErr::from)?
1127
1165
  .into())
@@ -1163,4 +1201,8 @@ impl RbDataFrame {
1163
1201
  let df = self.df.borrow().unnest(names).map_err(RbPolarsErr::from)?;
1164
1202
  Ok(df.into())
1165
1203
  }
1204
+
1205
+ pub fn clear(&self) -> Self {
1206
+ self.df.borrow().clear().into()
1207
+ }
1166
1208
  }
@@ -1,3 +1,5 @@
1
+ use polars::prelude::*;
2
+
1
3
  use crate::RbExpr;
2
4
 
3
5
  impl RbExpr {
@@ -12,4 +14,80 @@ impl RbExpr {
12
14
  pub fn array_sum(&self) -> Self {
13
15
  self.inner.clone().arr().sum().into()
14
16
  }
17
+
18
+ pub fn arr_unique(&self, maintain_order: bool) -> Self {
19
+ if maintain_order {
20
+ self.inner.clone().arr().unique_stable().into()
21
+ } else {
22
+ self.inner.clone().arr().unique().into()
23
+ }
24
+ }
25
+
26
+ pub fn arr_to_list(&self) -> Self {
27
+ self.inner.clone().arr().to_list().into()
28
+ }
29
+
30
+ pub fn arr_all(&self) -> Self {
31
+ self.inner.clone().arr().all().into()
32
+ }
33
+
34
+ pub fn arr_any(&self) -> Self {
35
+ self.inner.clone().arr().any().into()
36
+ }
37
+
38
+ pub fn arr_sort(&self, descending: bool, nulls_last: bool) -> Self {
39
+ self.inner
40
+ .clone()
41
+ .arr()
42
+ .sort(SortOptions {
43
+ descending,
44
+ nulls_last,
45
+ ..Default::default()
46
+ })
47
+ .into()
48
+ }
49
+
50
+ pub fn arr_reverse(&self) -> Self {
51
+ self.inner.clone().arr().reverse().into()
52
+ }
53
+
54
+ pub fn arr_arg_min(&self) -> Self {
55
+ self.inner.clone().arr().arg_min().into()
56
+ }
57
+
58
+ pub fn arr_arg_max(&self) -> Self {
59
+ self.inner.clone().arr().arg_max().into()
60
+ }
61
+
62
+ pub fn arr_get(&self, index: &RbExpr, null_on_oob: bool) -> Self {
63
+ self.inner
64
+ .clone()
65
+ .arr()
66
+ .get(index.inner.clone(), null_on_oob)
67
+ .into()
68
+ }
69
+
70
+ pub fn arr_join(&self, separator: &RbExpr, ignore_nulls: bool) -> Self {
71
+ self.inner
72
+ .clone()
73
+ .arr()
74
+ .join(separator.inner.clone(), ignore_nulls)
75
+ .into()
76
+ }
77
+
78
+ pub fn arr_contains(&self, other: &RbExpr) -> Self {
79
+ self.inner
80
+ .clone()
81
+ .arr()
82
+ .contains(other.inner.clone())
83
+ .into()
84
+ }
85
+
86
+ pub fn arr_count_matches(&self, expr: &RbExpr) -> Self {
87
+ self.inner
88
+ .clone()
89
+ .arr()
90
+ .count_matches(expr.inner.clone())
91
+ .into()
92
+ }
15
93
  }
@@ -37,11 +37,16 @@ impl RbExpr {
37
37
  self.inner.clone().dt().cast_time_unit(tu.0).into()
38
38
  }
39
39
 
40
- pub fn dt_replace_time_zone(&self, time_zone: Option<String>, ambiguous: &Self) -> Self {
40
+ pub fn dt_replace_time_zone(
41
+ &self,
42
+ time_zone: Option<String>,
43
+ ambiguous: &Self,
44
+ non_existent: Wrap<NonExistent>,
45
+ ) -> Self {
41
46
  self.inner
42
47
  .clone()
43
48
  .dt()
44
- .replace_time_zone(time_zone, ambiguous.inner.clone())
49
+ .replace_time_zone(time_zone, ambiguous.inner.clone(), non_existent.0)
45
50
  .into()
46
51
  }
47
52
 
@@ -61,6 +66,14 @@ impl RbExpr {
61
66
  self.inner.clone().dt().month_end().into()
62
67
  }
63
68
 
69
+ pub fn dt_base_utc_offset(&self) -> Self {
70
+ self.inner.clone().dt().base_utc_offset().into()
71
+ }
72
+
73
+ pub fn dt_dst_offset(&self) -> Self {
74
+ self.inner.clone().dt().dst_offset().into()
75
+ }
76
+
64
77
  pub fn dt_round(&self, every: String, offset: String) -> Self {
65
78
  self.inner.clone().dt().round(&every, &offset).into()
66
79
  }
@@ -149,73 +162,31 @@ impl RbExpr {
149
162
  self.inner.clone().dt().timestamp(tu.0).into()
150
163
  }
151
164
 
152
- pub fn duration_days(&self) -> Self {
153
- self.inner
154
- .clone()
155
- .map(
156
- |s| Ok(Some(s.duration()?.days().into_series())),
157
- GetOutput::from_type(DataType::Int64),
158
- )
159
- .into()
165
+ pub fn dt_total_days(&self) -> Self {
166
+ self.inner.clone().dt().total_days().into()
160
167
  }
161
168
 
162
- pub fn duration_hours(&self) -> Self {
163
- self.inner
164
- .clone()
165
- .map(
166
- |s| Ok(Some(s.duration()?.hours().into_series())),
167
- GetOutput::from_type(DataType::Int64),
168
- )
169
- .into()
169
+ pub fn dt_total_hours(&self) -> Self {
170
+ self.inner.clone().dt().total_hours().into()
170
171
  }
171
172
 
172
- pub fn duration_minutes(&self) -> Self {
173
- self.inner
174
- .clone()
175
- .map(
176
- |s| Ok(Some(s.duration()?.minutes().into_series())),
177
- GetOutput::from_type(DataType::Int64),
178
- )
179
- .into()
173
+ pub fn dt_total_minutes(&self) -> Self {
174
+ self.inner.clone().dt().total_minutes().into()
180
175
  }
181
176
 
182
- pub fn duration_seconds(&self) -> Self {
183
- self.inner
184
- .clone()
185
- .map(
186
- |s| Ok(Some(s.duration()?.seconds().into_series())),
187
- GetOutput::from_type(DataType::Int64),
188
- )
189
- .into()
177
+ pub fn dt_total_seconds(&self) -> Self {
178
+ self.inner.clone().dt().total_seconds().into()
190
179
  }
191
180
 
192
- pub fn duration_milliseconds(&self) -> Self {
193
- self.inner
194
- .clone()
195
- .map(
196
- |s| Ok(Some(s.duration()?.milliseconds().into_series())),
197
- GetOutput::from_type(DataType::Int64),
198
- )
199
- .into()
181
+ pub fn dt_total_milliseconds(&self) -> Self {
182
+ self.inner.clone().dt().total_milliseconds().into()
200
183
  }
201
184
 
202
- pub fn duration_microseconds(&self) -> Self {
203
- self.inner
204
- .clone()
205
- .map(
206
- |s| Ok(Some(s.duration()?.microseconds().into_series())),
207
- GetOutput::from_type(DataType::Int64),
208
- )
209
- .into()
185
+ pub fn dt_total_microseconds(&self) -> Self {
186
+ self.inner.clone().dt().total_microseconds().into()
210
187
  }
211
188
 
212
- pub fn duration_nanoseconds(&self) -> Self {
213
- self.inner
214
- .clone()
215
- .map(
216
- |s| Ok(Some(s.duration()?.nanoseconds().into_series())),
217
- GetOutput::from_type(DataType::Int64),
218
- )
219
- .into()
189
+ pub fn dt_total_nanoseconds(&self) -> Self {
190
+ self.inner.clone().dt().total_nanoseconds().into()
220
191
  }
221
192
  }