polars-df 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/Cargo.lock +595 -709
  4. data/Cargo.toml +1 -0
  5. data/README.md +11 -9
  6. data/ext/polars/Cargo.toml +18 -10
  7. data/ext/polars/src/batched_csv.rs +26 -26
  8. data/ext/polars/src/conversion.rs +272 -136
  9. data/ext/polars/src/dataframe.rs +135 -94
  10. data/ext/polars/src/error.rs +8 -5
  11. data/ext/polars/src/expr/array.rs +15 -0
  12. data/ext/polars/src/expr/binary.rs +18 -6
  13. data/ext/polars/src/expr/datetime.rs +10 -12
  14. data/ext/polars/src/expr/general.rs +78 -264
  15. data/ext/polars/src/expr/list.rs +41 -28
  16. data/ext/polars/src/{expr.rs → expr/mod.rs} +5 -2
  17. data/ext/polars/src/expr/name.rs +44 -0
  18. data/ext/polars/src/expr/rolling.rs +196 -0
  19. data/ext/polars/src/expr/string.rs +94 -66
  20. data/ext/polars/src/file.rs +3 -3
  21. data/ext/polars/src/functions/aggregation.rs +35 -0
  22. data/ext/polars/src/functions/eager.rs +7 -31
  23. data/ext/polars/src/functions/io.rs +10 -10
  24. data/ext/polars/src/functions/lazy.rs +119 -54
  25. data/ext/polars/src/functions/meta.rs +30 -0
  26. data/ext/polars/src/functions/misc.rs +8 -0
  27. data/ext/polars/src/functions/mod.rs +5 -0
  28. data/ext/polars/src/functions/random.rs +6 -0
  29. data/ext/polars/src/functions/range.rs +46 -0
  30. data/ext/polars/src/functions/string_cache.rs +11 -0
  31. data/ext/polars/src/functions/whenthen.rs +7 -7
  32. data/ext/polars/src/lazyframe.rs +61 -44
  33. data/ext/polars/src/lib.rs +173 -84
  34. data/ext/polars/src/{apply → map}/dataframe.rs +28 -33
  35. data/ext/polars/src/{apply → map}/mod.rs +10 -6
  36. data/ext/polars/src/{apply → map}/series.rs +12 -16
  37. data/ext/polars/src/object.rs +2 -2
  38. data/ext/polars/src/rb_modules.rs +25 -6
  39. data/ext/polars/src/series/construction.rs +32 -6
  40. data/ext/polars/src/series/export.rs +2 -2
  41. data/ext/polars/src/series/set_at_idx.rs +33 -17
  42. data/ext/polars/src/series.rs +62 -42
  43. data/ext/polars/src/sql.rs +46 -0
  44. data/lib/polars/array_expr.rb +84 -0
  45. data/lib/polars/array_name_space.rb +77 -0
  46. data/lib/polars/batched_csv_reader.rb +1 -1
  47. data/lib/polars/config.rb +530 -0
  48. data/lib/polars/data_frame.rb +206 -131
  49. data/lib/polars/data_types.rb +163 -29
  50. data/lib/polars/date_time_expr.rb +13 -18
  51. data/lib/polars/date_time_name_space.rb +22 -28
  52. data/lib/polars/dynamic_group_by.rb +2 -2
  53. data/lib/polars/expr.rb +241 -151
  54. data/lib/polars/functions.rb +29 -38
  55. data/lib/polars/group_by.rb +38 -76
  56. data/lib/polars/io.rb +37 -2
  57. data/lib/polars/lazy_frame.rb +174 -95
  58. data/lib/polars/lazy_functions.rb +87 -63
  59. data/lib/polars/lazy_group_by.rb +7 -8
  60. data/lib/polars/list_expr.rb +40 -36
  61. data/lib/polars/list_name_space.rb +15 -15
  62. data/lib/polars/name_expr.rb +198 -0
  63. data/lib/polars/rolling_group_by.rb +6 -4
  64. data/lib/polars/series.rb +95 -28
  65. data/lib/polars/sql_context.rb +194 -0
  66. data/lib/polars/string_expr.rb +249 -69
  67. data/lib/polars/string_name_space.rb +155 -25
  68. data/lib/polars/utils.rb +119 -57
  69. data/lib/polars/version.rb +1 -1
  70. data/lib/polars.rb +6 -0
  71. metadata +21 -7
  72. /data/ext/polars/src/{apply → map}/lazy.rs +0 -0
@@ -1,4 +1,7 @@
1
- use magnus::{r_hash::ForEach, IntoValue, RArray, RHash, RString, Value};
1
+ use either::Either;
2
+ use magnus::{
3
+ prelude::*, r_hash::ForEach, typed_data::Obj, IntoValue, RArray, RHash, RString, Value,
4
+ };
2
5
  use polars::frame::row::{rows_to_schema_supertypes, Row};
3
6
  use polars::frame::NullStrategy;
4
7
  use polars::io::avro::AvroCompression;
@@ -11,12 +14,12 @@ use std::cell::RefCell;
11
14
  use std::io::{BufWriter, Cursor};
12
15
  use std::ops::Deref;
13
16
 
14
- use crate::apply::dataframe::{
17
+ use crate::conversion::*;
18
+ use crate::file::{get_file_like, get_mmap_bytes_reader};
19
+ use crate::map::dataframe::{
15
20
  apply_lambda_unknown, apply_lambda_with_bool_out_type, apply_lambda_with_primitive_out_type,
16
21
  apply_lambda_with_utf8_out_type,
17
22
  };
18
- use crate::conversion::*;
19
- use crate::file::{get_file_like, get_mmap_bytes_reader};
20
23
  use crate::rb_modules;
21
24
  use crate::series::{to_rbseries_collection, to_series_collection};
22
25
  use crate::{RbExpr, RbLazyFrame, RbPolarsErr, RbResult, RbSeries};
@@ -53,7 +56,7 @@ impl RbDataFrame {
53
56
  // replace inferred nulls with boolean
54
57
  let fields = schema.iter_fields().map(|mut fld| match fld.data_type() {
55
58
  DataType::Null => {
56
- fld.coerce(DataType::Boolean);
59
+ // fld.coerce(DataType::Boolean);
57
60
  fld
58
61
  }
59
62
  DataType::Decimal(_, _) => {
@@ -86,7 +89,7 @@ impl RbDataFrame {
86
89
  pub fn init(columns: RArray) -> RbResult<Self> {
87
90
  let mut cols = Vec::new();
88
91
  for i in columns.each() {
89
- cols.push(i?.try_convert::<&RbSeries>()?.series.borrow().clone());
92
+ cols.push(<&RbSeries>::try_convert(i?)?.series.borrow().clone());
90
93
  }
91
94
  let df = DataFrame::new(cols).map_err(RbPolarsErr::from)?;
92
95
  Ok(RbDataFrame::new(df))
@@ -99,32 +102,32 @@ impl RbDataFrame {
99
102
  pub fn read_csv(arguments: &[Value]) -> RbResult<Self> {
100
103
  // start arguments
101
104
  // this pattern is needed for more than 16
102
- let rb_f: Value = arguments[0].try_convert()?;
103
- let infer_schema_length: Option<usize> = arguments[1].try_convert()?;
104
- let chunk_size: usize = arguments[2].try_convert()?;
105
- let has_header: bool = arguments[3].try_convert()?;
106
- let ignore_errors: bool = arguments[4].try_convert()?;
107
- let n_rows: Option<usize> = arguments[5].try_convert()?;
108
- let skip_rows: usize = arguments[6].try_convert()?;
109
- let projection: Option<Vec<usize>> = arguments[7].try_convert()?;
110
- let sep: String = arguments[8].try_convert()?;
111
- let rechunk: bool = arguments[9].try_convert()?;
112
- let columns: Option<Vec<String>> = arguments[10].try_convert()?;
113
- let encoding: Wrap<CsvEncoding> = arguments[11].try_convert()?;
114
- let n_threads: Option<usize> = arguments[12].try_convert()?;
115
- let path: Option<String> = arguments[13].try_convert()?;
116
- let overwrite_dtype: Option<Vec<(String, Wrap<DataType>)>> = arguments[14].try_convert()?;
105
+ let rb_f = arguments[0];
106
+ let infer_schema_length = Option::<usize>::try_convert(arguments[1])?;
107
+ let chunk_size = usize::try_convert(arguments[2])?;
108
+ let has_header = bool::try_convert(arguments[3])?;
109
+ let ignore_errors = bool::try_convert(arguments[4])?;
110
+ let n_rows = Option::<usize>::try_convert(arguments[5])?;
111
+ let skip_rows = usize::try_convert(arguments[6])?;
112
+ let projection = Option::<Vec<usize>>::try_convert(arguments[7])?;
113
+ let separator = String::try_convert(arguments[8])?;
114
+ let rechunk = bool::try_convert(arguments[9])?;
115
+ let columns = Option::<Vec<String>>::try_convert(arguments[10])?;
116
+ let encoding = Wrap::<CsvEncoding>::try_convert(arguments[11])?;
117
+ let n_threads = Option::<usize>::try_convert(arguments[12])?;
118
+ let path = Option::<String>::try_convert(arguments[13])?;
119
+ let overwrite_dtype = Option::<Vec<(String, Wrap<DataType>)>>::try_convert(arguments[14])?;
117
120
  // TODO fix
118
- let overwrite_dtype_slice: Option<Vec<Wrap<DataType>>> = None; // arguments[15].try_convert()?;
119
- let low_memory: bool = arguments[16].try_convert()?;
120
- let comment_char: Option<String> = arguments[17].try_convert()?;
121
- let quote_char: Option<String> = arguments[18].try_convert()?;
122
- let null_values: Option<Wrap<NullValues>> = arguments[19].try_convert()?;
123
- let try_parse_dates: bool = arguments[20].try_convert()?;
124
- let skip_rows_after_header: usize = arguments[21].try_convert()?;
125
- let row_count: Option<(String, IdxSize)> = arguments[22].try_convert()?;
126
- let sample_size: usize = arguments[23].try_convert()?;
127
- let eol_char: String = arguments[24].try_convert()?;
121
+ let overwrite_dtype_slice = Option::<Vec<Wrap<DataType>>>::None; // Option::<Vec<Wrap<DataType>>>::try_convert(arguments[15])?;
122
+ let low_memory = bool::try_convert(arguments[16])?;
123
+ let comment_char = Option::<String>::try_convert(arguments[17])?;
124
+ let quote_char = Option::<String>::try_convert(arguments[18])?;
125
+ let null_values = Option::<Wrap<NullValues>>::try_convert(arguments[19])?;
126
+ let try_parse_dates = bool::try_convert(arguments[20])?;
127
+ let skip_rows_after_header = usize::try_convert(arguments[21])?;
128
+ let row_count = Option::<(String, IdxSize)>::try_convert(arguments[22])?;
129
+ let sample_size = usize::try_convert(arguments[23])?;
130
+ let eol_char = String::try_convert(arguments[24])?;
128
131
  // end arguments
129
132
 
130
133
  let null_values = null_values.map(|w| w.0);
@@ -165,7 +168,7 @@ impl RbDataFrame {
165
168
  .infer_schema(infer_schema_length)
166
169
  .has_header(has_header)
167
170
  .with_n_rows(n_rows)
168
- .with_delimiter(sep.as_bytes()[0])
171
+ .with_separator(separator.as_bytes()[0])
169
172
  .with_skip_rows(skip_rows)
170
173
  .with_ignore_errors(ignore_errors)
171
174
  .with_projection(projection)
@@ -265,7 +268,7 @@ impl RbDataFrame {
265
268
  ) -> RbResult<()> {
266
269
  use polars::io::avro::AvroWriter;
267
270
 
268
- if let Ok(s) = rb_f.try_convert::<String>() {
271
+ if let Ok(s) = String::try_convert(rb_f) {
269
272
  let f = std::fs::File::create(s).unwrap();
270
273
  AvroWriter::new(f)
271
274
  .with_compression(compression.0)
@@ -341,6 +344,27 @@ impl RbDataFrame {
341
344
  Ok(())
342
345
  }
343
346
 
347
+ pub fn read_rows(
348
+ rb_rows: RArray,
349
+ infer_schema_length: Option<usize>,
350
+ schema_overwrite: Option<Wrap<Schema>>,
351
+ ) -> RbResult<Self> {
352
+ let mut rows = Vec::with_capacity(rb_rows.len());
353
+ for v in rb_rows.each() {
354
+ let rb_row = RArray::try_convert(v?)?;
355
+ let mut row = Vec::with_capacity(rb_row.len());
356
+ for val in rb_row.each() {
357
+ row.push(Wrap::<AnyValue>::try_convert(val?)?.0);
358
+ }
359
+ rows.push(Row(row));
360
+ }
361
+ Self::finish_from_rows(
362
+ rows,
363
+ infer_schema_length,
364
+ schema_overwrite.map(|wrap| wrap.0),
365
+ )
366
+ }
367
+
344
368
  pub fn read_hashes(
345
369
  dicts: Value,
346
370
  infer_schema_length: Option<usize>,
@@ -395,9 +419,9 @@ impl RbDataFrame {
395
419
  pub fn write_csv(
396
420
  &self,
397
421
  rb_f: Value,
398
- has_header: bool,
399
- sep: u8,
400
- quote: u8,
422
+ include_header: bool,
423
+ separator: u8,
424
+ quote_char: u8,
401
425
  batch_size: usize,
402
426
  datetime_format: Option<String>,
403
427
  date_format: Option<String>,
@@ -407,13 +431,13 @@ impl RbDataFrame {
407
431
  ) -> RbResult<()> {
408
432
  let null = null_value.unwrap_or_default();
409
433
 
410
- if let Ok(s) = rb_f.try_convert::<String>() {
434
+ if let Ok(s) = String::try_convert(rb_f) {
411
435
  let f = std::fs::File::create(s).unwrap();
412
436
  // no need for a buffered writer, because the csv writer does internal buffering
413
437
  CsvWriter::new(f)
414
- .has_header(has_header)
415
- .with_delimiter(sep)
416
- .with_quoting_char(quote)
438
+ .include_header(include_header)
439
+ .with_separator(separator)
440
+ .with_quote_char(quote_char)
417
441
  .with_batch_size(batch_size)
418
442
  .with_datetime_format(datetime_format)
419
443
  .with_date_format(date_format)
@@ -425,9 +449,9 @@ impl RbDataFrame {
425
449
  } else {
426
450
  let mut buf = Cursor::new(Vec::new());
427
451
  CsvWriter::new(&mut buf)
428
- .has_header(has_header)
429
- .with_delimiter(sep)
430
- .with_quoting_char(quote)
452
+ .include_header(include_header)
453
+ .with_separator(separator)
454
+ .with_quote_char(quote_char)
431
455
  .with_batch_size(batch_size)
432
456
  .with_datetime_format(datetime_format)
433
457
  .with_date_format(date_format)
@@ -449,19 +473,21 @@ impl RbDataFrame {
449
473
  rb_f: Value,
450
474
  compression: Wrap<Option<IpcCompression>>,
451
475
  ) -> RbResult<()> {
452
- if let Ok(s) = rb_f.try_convert::<String>() {
476
+ if let Ok(s) = String::try_convert(rb_f) {
453
477
  let f = std::fs::File::create(s).unwrap();
454
478
  IpcWriter::new(f)
455
479
  .with_compression(compression.0)
456
480
  .finish(&mut self.df.borrow_mut())
457
481
  .map_err(RbPolarsErr::from)?;
458
482
  } else {
459
- let mut buf = get_file_like(rb_f, true)?;
460
-
483
+ let mut buf = Cursor::new(Vec::new());
461
484
  IpcWriter::new(&mut buf)
462
485
  .with_compression(compression.0)
463
486
  .finish(&mut self.df.borrow_mut())
464
487
  .map_err(RbPolarsErr::from)?;
488
+ // TODO less copying
489
+ let rb_str = RString::from_slice(&buf.into_inner());
490
+ rb_f.funcall::<_, _, Value>("write", (rb_str,))?;
465
491
  }
466
492
  Ok(())
467
493
  }
@@ -485,7 +511,7 @@ impl RbDataFrame {
485
511
  _ => Wrap(s.get(idx).unwrap()).into_value(),
486
512
  }),
487
513
  )
488
- .into()
514
+ .as_value()
489
515
  }
490
516
 
491
517
  pub fn row_tuples(&self) -> Value {
@@ -505,7 +531,7 @@ impl RbDataFrame {
505
531
  }),
506
532
  )
507
533
  }))
508
- .into()
534
+ .as_value()
509
535
  }
510
536
 
511
537
  pub fn to_numo(&self) -> Option<Value> {
@@ -535,7 +561,7 @@ impl RbDataFrame {
535
561
  ) -> RbResult<()> {
536
562
  let compression = parse_parquet_compression(&compression, compression_level)?;
537
563
 
538
- if let Ok(s) = rb_f.try_convert::<String>() {
564
+ if let Ok(s) = String::try_convert(rb_f) {
539
565
  let f = std::fs::File::create(s).unwrap();
540
566
  ParquetWriter::new(f)
541
567
  .with_compression(compression)
@@ -602,7 +628,7 @@ impl RbDataFrame {
602
628
 
603
629
  pub fn sample_n(
604
630
  &self,
605
- n: usize,
631
+ n: &RbSeries,
606
632
  with_replacement: bool,
607
633
  shuffle: bool,
608
634
  seed: Option<u64>,
@@ -610,14 +636,14 @@ impl RbDataFrame {
610
636
  let df = self
611
637
  .df
612
638
  .borrow()
613
- .sample_n(n, with_replacement, shuffle, seed)
639
+ .sample_n(&n.series.borrow(), with_replacement, shuffle, seed)
614
640
  .map_err(RbPolarsErr::from)?;
615
641
  Ok(df.into())
616
642
  }
617
643
 
618
644
  pub fn sample_frac(
619
645
  &self,
620
- frac: f64,
646
+ frac: &RbSeries,
621
647
  with_replacement: bool,
622
648
  shuffle: bool,
623
649
  seed: Option<u64>,
@@ -625,7 +651,7 @@ impl RbDataFrame {
625
651
  let df = self
626
652
  .df
627
653
  .borrow()
628
- .sample_frac(frac, with_replacement, shuffle, seed)
654
+ .sample_frac(&frac.series.borrow(), with_replacement, shuffle, seed)
629
655
  .map_err(RbPolarsErr::from)?;
630
656
  Ok(df.into())
631
657
  }
@@ -794,22 +820,6 @@ impl RbDataFrame {
794
820
  Ok(RbDataFrame::new(df))
795
821
  }
796
822
 
797
- pub fn sort(&self, by_column: String, reverse: bool, nulls_last: bool) -> RbResult<Self> {
798
- let df = self
799
- .df
800
- .borrow()
801
- .sort_with_options(
802
- &by_column,
803
- SortOptions {
804
- descending: reverse,
805
- nulls_last,
806
- multithreaded: true,
807
- },
808
- )
809
- .map_err(RbPolarsErr::from)?;
810
- Ok(RbDataFrame::new(df))
811
- }
812
-
813
823
  pub fn replace(&self, column: String, new_col: &RbSeries) -> RbResult<()> {
814
824
  self.df
815
825
  .borrow_mut()
@@ -933,11 +943,16 @@ impl RbDataFrame {
933
943
  Ok(RbDataFrame::new(df))
934
944
  }
935
945
 
936
- pub fn partition_by(&self, groups: Vec<String>, stable: bool) -> RbResult<RArray> {
937
- let out = if stable {
938
- self.df.borrow().partition_by_stable(groups)
946
+ pub fn partition_by(
947
+ &self,
948
+ by: Vec<String>,
949
+ maintain_order: bool,
950
+ include_key: bool,
951
+ ) -> RbResult<RArray> {
952
+ let out = if maintain_order {
953
+ self.df.borrow().partition_by_stable(by, include_key)
939
954
  } else {
940
- self.df.borrow().partition_by(groups)
955
+ self.df.borrow().partition_by(by, include_key)
941
956
  }
942
957
  .map_err(RbPolarsErr::from)?;
943
958
  Ok(RArray::from_iter(out.into_iter().map(RbDataFrame::new)))
@@ -979,30 +994,48 @@ impl RbDataFrame {
979
994
  self.df.borrow().median().into()
980
995
  }
981
996
 
982
- pub fn hmean(&self, null_strategy: Wrap<NullStrategy>) -> RbResult<Option<RbSeries>> {
997
+ pub fn max_horizontal(&self) -> RbResult<Option<RbSeries>> {
983
998
  let s = self
984
999
  .df
985
1000
  .borrow()
986
- .hmean(null_strategy.0)
1001
+ .max_horizontal()
987
1002
  .map_err(RbPolarsErr::from)?;
988
1003
  Ok(s.map(|s| s.into()))
989
1004
  }
990
1005
 
991
- pub fn hmax(&self) -> RbResult<Option<RbSeries>> {
992
- let s = self.df.borrow().hmax().map_err(RbPolarsErr::from)?;
1006
+ pub fn min_horizontal(&self) -> RbResult<Option<RbSeries>> {
1007
+ let s = self
1008
+ .df
1009
+ .borrow()
1010
+ .min_horizontal()
1011
+ .map_err(RbPolarsErr::from)?;
993
1012
  Ok(s.map(|s| s.into()))
994
1013
  }
995
1014
 
996
- pub fn hmin(&self) -> RbResult<Option<RbSeries>> {
997
- let s = self.df.borrow().hmin().map_err(RbPolarsErr::from)?;
1015
+ pub fn sum_horizontal(&self, ignore_nulls: bool) -> RbResult<Option<RbSeries>> {
1016
+ let null_strategy = if ignore_nulls {
1017
+ NullStrategy::Ignore
1018
+ } else {
1019
+ NullStrategy::Propagate
1020
+ };
1021
+ let s = self
1022
+ .df
1023
+ .borrow()
1024
+ .sum_horizontal(null_strategy)
1025
+ .map_err(RbPolarsErr::from)?;
998
1026
  Ok(s.map(|s| s.into()))
999
1027
  }
1000
1028
 
1001
- pub fn hsum(&self, null_strategy: Wrap<NullStrategy>) -> RbResult<Option<RbSeries>> {
1029
+ pub fn mean_horizontal(&self, ignore_nulls: bool) -> RbResult<Option<RbSeries>> {
1030
+ let null_strategy = if ignore_nulls {
1031
+ NullStrategy::Ignore
1032
+ } else {
1033
+ NullStrategy::Propagate
1034
+ };
1002
1035
  let s = self
1003
1036
  .df
1004
1037
  .borrow()
1005
- .hsum(null_strategy.0)
1038
+ .mean_horizontal(null_strategy)
1006
1039
  .map_err(RbPolarsErr::from)?;
1007
1040
  Ok(s.map(|s| s.into()))
1008
1041
  }
@@ -1024,13 +1057,18 @@ impl RbDataFrame {
1024
1057
  &self,
1025
1058
  columns: Option<Vec<String>>,
1026
1059
  separator: Option<String>,
1060
+ drop_first: bool,
1027
1061
  ) -> RbResult<Self> {
1028
1062
  let df = match columns {
1029
1063
  Some(cols) => self.df.borrow().columns_to_dummies(
1030
1064
  cols.iter().map(|x| x as &str).collect(),
1031
1065
  separator.as_deref(),
1066
+ drop_first,
1032
1067
  ),
1033
- None => self.df.borrow().to_dummies(separator.as_deref()),
1068
+ None => self
1069
+ .df
1070
+ .borrow()
1071
+ .to_dummies(separator.as_deref(), drop_first),
1034
1072
  }
1035
1073
  .map_err(RbPolarsErr::from)?;
1036
1074
  Ok(df.into())
@@ -1092,7 +1130,7 @@ impl RbDataFrame {
1092
1130
  _ => return apply_lambda_unknown(df, lambda, inference_size),
1093
1131
  };
1094
1132
 
1095
- Ok((RbSeries::from(out).into(), false))
1133
+ Ok((Obj::wrap(RbSeries::from(out)).as_value(), false))
1096
1134
  }
1097
1135
 
1098
1136
  pub fn shrink_to_fit(&self) {
@@ -1109,17 +1147,20 @@ impl RbDataFrame {
1109
1147
  Ok(hash.into_series().into())
1110
1148
  }
1111
1149
 
1112
- pub fn transpose(&self, include_header: bool, names: String) -> RbResult<Self> {
1113
- let mut df = self.df.borrow().transpose().map_err(RbPolarsErr::from)?;
1114
- if include_header {
1115
- let s = Utf8Chunked::from_iter_values(
1116
- &names,
1117
- self.df.borrow().get_columns().iter().map(|s| s.name()),
1118
- )
1119
- .into_series();
1120
- df.insert_at_idx(0, s).unwrap();
1121
- }
1122
- Ok(df.into())
1150
+ pub fn transpose(&self, keep_names_as: Option<String>, column_names: Value) -> RbResult<Self> {
1151
+ let new_col_names = if let Ok(name) = <Vec<String>>::try_convert(column_names) {
1152
+ Some(Either::Right(name))
1153
+ } else if let Ok(name) = String::try_convert(column_names) {
1154
+ Some(Either::Left(name))
1155
+ } else {
1156
+ None
1157
+ };
1158
+ Ok(self
1159
+ .df
1160
+ .borrow()
1161
+ .transpose(keep_names_as.as_deref(), new_col_names)
1162
+ .map_err(RbPolarsErr::from)?
1163
+ .into())
1123
1164
  }
1124
1165
 
1125
1166
  pub fn upsample(
@@ -1,6 +1,5 @@
1
1
  use magnus::exception;
2
2
  use magnus::Error;
3
- use polars::error::ArrowError;
4
3
  use polars::prelude::PolarsError;
5
4
 
6
5
  pub struct RbPolarsErr {}
@@ -11,10 +10,6 @@ impl RbPolarsErr {
11
10
  Error::new(exception::runtime_error(), e.to_string())
12
11
  }
13
12
 
14
- pub fn arrow(e: ArrowError) -> Error {
15
- Error::new(exception::runtime_error(), e.to_string())
16
- }
17
-
18
13
  pub fn io(e: std::io::Error) -> Error {
19
14
  Error::new(exception::runtime_error(), e.to_string())
20
15
  }
@@ -24,6 +19,14 @@ impl RbPolarsErr {
24
19
  }
25
20
  }
26
21
 
22
+ pub struct RbTypeError {}
23
+
24
+ impl RbTypeError {
25
+ pub fn new_err(message: String) -> Error {
26
+ Error::new(exception::type_error(), message)
27
+ }
28
+ }
29
+
27
30
  pub struct RbValueError {}
28
31
 
29
32
  impl RbValueError {
@@ -0,0 +1,15 @@
1
+ use crate::RbExpr;
2
+
3
+ impl RbExpr {
4
+ pub fn array_max(&self) -> Self {
5
+ self.inner.clone().arr().max().into()
6
+ }
7
+
8
+ pub fn array_min(&self) -> Self {
9
+ self.inner.clone().arr().min().into()
10
+ }
11
+
12
+ pub fn array_sum(&self) -> Self {
13
+ self.inner.clone().arr().sum().into()
14
+ }
15
+ }
@@ -3,16 +3,28 @@ use polars::prelude::*;
3
3
  use crate::RbExpr;
4
4
 
5
5
  impl RbExpr {
6
- pub fn bin_contains(&self, lit: Vec<u8>) -> Self {
7
- self.inner.clone().binary().contains_literal(lit).into()
6
+ pub fn bin_contains(&self, lit: &RbExpr) -> Self {
7
+ self.inner
8
+ .clone()
9
+ .binary()
10
+ .contains_literal(lit.inner.clone())
11
+ .into()
8
12
  }
9
13
 
10
- pub fn bin_ends_with(&self, sub: Vec<u8>) -> Self {
11
- self.inner.clone().binary().ends_with(sub).into()
14
+ pub fn bin_ends_with(&self, sub: &RbExpr) -> Self {
15
+ self.inner
16
+ .clone()
17
+ .binary()
18
+ .ends_with(sub.inner.clone())
19
+ .into()
12
20
  }
13
21
 
14
- pub fn bin_starts_with(&self, sub: Vec<u8>) -> Self {
15
- self.inner.clone().binary().starts_with(sub).into()
22
+ pub fn bin_starts_with(&self, sub: &RbExpr) -> Self {
23
+ self.inner
24
+ .clone()
25
+ .binary()
26
+ .starts_with(sub.inner.clone())
27
+ .into()
16
28
  }
17
29
 
18
30
  pub fn bin_hex_decode(&self, strict: bool) -> Self {
@@ -8,9 +8,8 @@ impl RbExpr {
8
8
  self.inner.clone().dt().to_string(&format).into()
9
9
  }
10
10
 
11
- pub fn dt_offset_by(&self, by: String) -> Self {
12
- let by = Duration::parse(&by);
13
- self.inner.clone().dt().offset_by(by).into()
11
+ pub fn dt_offset_by(&self, by: &RbExpr) -> Self {
12
+ self.inner.clone().dt().offset_by(by.inner.clone()).into()
14
13
  }
15
14
 
16
15
  pub fn dt_epoch_seconds(&self) -> Self {
@@ -38,21 +37,20 @@ impl RbExpr {
38
37
  self.inner.clone().dt().cast_time_unit(tu.0).into()
39
38
  }
40
39
 
41
- pub fn dt_replace_time_zone(&self, tz: Option<String>, use_earliest: Option<bool>) -> Self {
40
+ pub fn dt_replace_time_zone(&self, time_zone: Option<String>, ambiguous: &Self) -> Self {
42
41
  self.inner
43
42
  .clone()
44
43
  .dt()
45
- .replace_time_zone(tz, use_earliest)
44
+ .replace_time_zone(time_zone, ambiguous.inner.clone())
46
45
  .into()
47
46
  }
48
47
 
49
- #[allow(deprecated)]
50
- pub fn dt_tz_localize(&self, tz: String) -> Self {
51
- self.inner.clone().dt().tz_localize(tz).into()
52
- }
53
-
54
- pub fn dt_truncate(&self, every: String, offset: String) -> Self {
55
- self.inner.clone().dt().truncate(&every, &offset).into()
48
+ pub fn dt_truncate(&self, every: &Self, offset: String) -> Self {
49
+ self.inner
50
+ .clone()
51
+ .dt()
52
+ .truncate(every.inner.clone(), offset)
53
+ .into()
56
54
  }
57
55
 
58
56
  pub fn dt_month_start(&self) -> Self {