polars-df 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/Cargo.lock +337 -381
  4. data/README.md +4 -3
  5. data/ext/polars/Cargo.toml +5 -4
  6. data/ext/polars/src/apply/mod.rs +7 -3
  7. data/ext/polars/src/conversion.rs +171 -63
  8. data/ext/polars/src/dataframe.rs +19 -23
  9. data/ext/polars/src/error.rs +8 -0
  10. data/ext/polars/src/expr/array.rs +15 -0
  11. data/ext/polars/src/expr/general.rs +39 -9
  12. data/ext/polars/src/expr/list.rs +27 -22
  13. data/ext/polars/src/expr/string.rs +10 -9
  14. data/ext/polars/src/expr.rs +1 -0
  15. data/ext/polars/src/functions/lazy.rs +61 -21
  16. data/ext/polars/src/lazyframe.rs +14 -2
  17. data/ext/polars/src/lib.rs +25 -20
  18. data/ext/polars/src/object.rs +1 -1
  19. data/ext/polars/src/rb_modules.rs +4 -0
  20. data/ext/polars/src/series/construction.rs +28 -2
  21. data/ext/polars/src/series.rs +57 -17
  22. data/lib/polars/array_expr.rb +84 -0
  23. data/lib/polars/array_name_space.rb +77 -0
  24. data/lib/polars/batched_csv_reader.rb +1 -1
  25. data/lib/polars/data_frame.rb +91 -49
  26. data/lib/polars/data_types.rb +163 -29
  27. data/lib/polars/date_time_name_space.rb +17 -3
  28. data/lib/polars/expr.rb +76 -69
  29. data/lib/polars/functions.rb +0 -1
  30. data/lib/polars/group_by.rb +1 -22
  31. data/lib/polars/lazy_frame.rb +82 -30
  32. data/lib/polars/lazy_functions.rb +67 -31
  33. data/lib/polars/list_expr.rb +28 -28
  34. data/lib/polars/list_name_space.rb +13 -13
  35. data/lib/polars/rolling_group_by.rb +4 -2
  36. data/lib/polars/series.rb +70 -16
  37. data/lib/polars/string_expr.rb +137 -11
  38. data/lib/polars/string_name_space.rb +137 -22
  39. data/lib/polars/utils.rb +107 -57
  40. data/lib/polars/version.rb +1 -1
  41. data/lib/polars.rb +3 -0
  42. metadata +5 -2
@@ -2,6 +2,8 @@ use magnus::{block::Proc, IntoValue, RArray, Value};
2
2
  use polars::lazy::dsl;
3
3
  use polars::prelude::*;
4
4
  use polars::series::ops::NullBehavior;
5
+ use polars_core::series::IsSorted;
6
+ use std::any::Any;
5
7
 
6
8
  use crate::apply::lazy::map_single;
7
9
  use crate::conversion::{parse_fill_null_strategy, Wrap};
@@ -201,6 +203,7 @@ impl RbExpr {
201
203
  descending,
202
204
  nulls_last,
203
205
  multithreaded: true,
206
+ maintain_order: false,
204
207
  })
205
208
  .into()
206
209
  }
@@ -212,6 +215,7 @@ impl RbExpr {
212
215
  descending: reverse,
213
216
  nulls_last,
214
217
  multithreaded: true,
218
+ maintain_order: false,
215
219
  })
216
220
  .into()
217
221
  }
@@ -588,6 +592,7 @@ impl RbExpr {
588
592
  center,
589
593
  by,
590
594
  closed_window: closed.map(|c| c.0),
595
+ ..Default::default()
591
596
  };
592
597
  self.inner.clone().rolling_sum(options).into()
593
598
  }
@@ -608,6 +613,7 @@ impl RbExpr {
608
613
  center,
609
614
  by,
610
615
  closed_window: closed.map(|c| c.0),
616
+ ..Default::default()
611
617
  };
612
618
  self.inner.clone().rolling_min(options).into()
613
619
  }
@@ -628,6 +634,7 @@ impl RbExpr {
628
634
  center,
629
635
  by,
630
636
  closed_window: closed.map(|c| c.0),
637
+ ..Default::default()
631
638
  };
632
639
  self.inner.clone().rolling_max(options).into()
633
640
  }
@@ -648,11 +655,13 @@ impl RbExpr {
648
655
  center,
649
656
  by,
650
657
  closed_window: closed.map(|c| c.0),
658
+ ..Default::default()
651
659
  };
652
660
 
653
661
  self.inner.clone().rolling_mean(options).into()
654
662
  }
655
663
 
664
+ #[allow(clippy::too_many_arguments)]
656
665
  pub fn rolling_std(
657
666
  &self,
658
667
  window_size: String,
@@ -661,6 +670,7 @@ impl RbExpr {
661
670
  center: bool,
662
671
  by: Option<String>,
663
672
  closed: Option<Wrap<ClosedWindow>>,
673
+ ddof: u8,
664
674
  ) -> Self {
665
675
  let options = RollingOptions {
666
676
  window_size: Duration::parse(&window_size),
@@ -669,11 +679,13 @@ impl RbExpr {
669
679
  center,
670
680
  by,
671
681
  closed_window: closed.map(|c| c.0),
682
+ fn_params: Some(Arc::new(RollingVarParams { ddof }) as Arc<dyn Any + Send + Sync>),
672
683
  };
673
684
 
674
685
  self.inner.clone().rolling_std(options).into()
675
686
  }
676
687
 
688
+ #[allow(clippy::too_many_arguments)]
677
689
  pub fn rolling_var(
678
690
  &self,
679
691
  window_size: String,
@@ -682,6 +694,7 @@ impl RbExpr {
682
694
  center: bool,
683
695
  by: Option<String>,
684
696
  closed: Option<Wrap<ClosedWindow>>,
697
+ ddof: u8,
685
698
  ) -> Self {
686
699
  let options = RollingOptions {
687
700
  window_size: Duration::parse(&window_size),
@@ -690,6 +703,7 @@ impl RbExpr {
690
703
  center,
691
704
  by,
692
705
  closed_window: closed.map(|c| c.0),
706
+ fn_params: Some(Arc::new(RollingVarParams { ddof }) as Arc<dyn Any + Send + Sync>),
693
707
  };
694
708
 
695
709
  self.inner.clone().rolling_var(options).into()
@@ -711,8 +725,12 @@ impl RbExpr {
711
725
  center,
712
726
  by,
713
727
  closed_window: closed.map(|c| c.0),
728
+ fn_params: Some(Arc::new(RollingQuantileParams {
729
+ prob: 0.5,
730
+ interpol: QuantileInterpolOptions::Linear,
731
+ }) as Arc<dyn Any + Send + Sync>),
714
732
  };
715
- self.inner.clone().rolling_median(options).into()
733
+ self.inner.clone().rolling_quantile(options).into()
716
734
  }
717
735
 
718
736
  #[allow(clippy::too_many_arguments)]
@@ -734,12 +752,13 @@ impl RbExpr {
734
752
  center,
735
753
  by,
736
754
  closed_window: closed.map(|c| c.0),
755
+ fn_params: Some(Arc::new(RollingQuantileParams {
756
+ prob: quantile,
757
+ interpol: interpolation.0,
758
+ }) as Arc<dyn Any + Send + Sync>),
737
759
  };
738
760
 
739
- self.inner
740
- .clone()
741
- .rolling_quantile(quantile, interpolation.0, options)
742
- .into()
761
+ self.inner.clone().rolling_quantile(options).into()
743
762
  }
744
763
 
745
764
  pub fn rolling_skew(&self, window_size: usize, bias: bool) -> Self {
@@ -809,8 +828,8 @@ impl RbExpr {
809
828
  .into()
810
829
  }
811
830
 
812
- pub fn shuffle(&self, seed: Option<u64>) -> Self {
813
- self.inner.clone().shuffle(seed).into()
831
+ pub fn shuffle(&self, seed: Option<u64>, fixed_seed: bool) -> Self {
832
+ self.inner.clone().shuffle(seed, fixed_seed).into()
814
833
  }
815
834
 
816
835
  pub fn sample_n(
@@ -819,10 +838,11 @@ impl RbExpr {
819
838
  with_replacement: bool,
820
839
  shuffle: bool,
821
840
  seed: Option<u64>,
841
+ fixed_seed: bool,
822
842
  ) -> Self {
823
843
  self.inner
824
844
  .clone()
825
- .sample_n(n, with_replacement, shuffle, seed)
845
+ .sample_n(n, with_replacement, shuffle, seed, fixed_seed)
826
846
  .into()
827
847
  }
828
848
 
@@ -832,10 +852,11 @@ impl RbExpr {
832
852
  with_replacement: bool,
833
853
  shuffle: bool,
834
854
  seed: Option<u64>,
855
+ fixed_seed: bool,
835
856
  ) -> Self {
836
857
  self.inner
837
858
  .clone()
838
- .sample_frac(frac, with_replacement, shuffle, seed)
859
+ .sample_frac(frac, with_replacement, shuffle, seed, fixed_seed)
839
860
  .into()
840
861
  }
841
862
 
@@ -930,4 +951,13 @@ impl RbExpr {
930
951
  pub fn hash(&self, seed: u64, seed_1: u64, seed_2: u64, seed_3: u64) -> Self {
931
952
  self.inner.clone().hash(seed, seed_1, seed_2, seed_3).into()
932
953
  }
954
+
955
+ pub fn set_sorted_flag(&self, descending: bool) -> Self {
956
+ let is_sorted = if descending {
957
+ IsSorted::Descending
958
+ } else {
959
+ IsSorted::Ascending
960
+ };
961
+ self.inner.clone().set_sorted_flag(is_sorted).into()
962
+ }
933
963
  }
@@ -8,17 +8,17 @@ use crate::{RbExpr, RbResult};
8
8
 
9
9
  impl RbExpr {
10
10
  pub fn list_arg_max(&self) -> Self {
11
- self.inner.clone().arr().arg_max().into()
11
+ self.inner.clone().list().arg_max().into()
12
12
  }
13
13
 
14
14
  pub fn list_arg_min(&self) -> Self {
15
- self.inner.clone().arr().arg_min().into()
15
+ self.inner.clone().list().arg_min().into()
16
16
  }
17
17
 
18
18
  pub fn list_contains(&self, other: &RbExpr) -> Self {
19
19
  self.inner
20
20
  .clone()
21
- .arr()
21
+ .list()
22
22
  .contains(other.inner.clone())
23
23
  .into()
24
24
  }
@@ -26,53 +26,58 @@ impl RbExpr {
26
26
  pub fn list_count_match(&self, expr: &RbExpr) -> Self {
27
27
  self.inner
28
28
  .clone()
29
- .arr()
29
+ .list()
30
30
  .count_match(expr.inner.clone())
31
31
  .into()
32
32
  }
33
33
 
34
34
  pub fn list_diff(&self, n: i64, null_behavior: Wrap<NullBehavior>) -> RbResult<Self> {
35
- Ok(self.inner.clone().arr().diff(n, null_behavior.0).into())
35
+ Ok(self.inner.clone().list().diff(n, null_behavior.0).into())
36
36
  }
37
37
 
38
38
  pub fn list_eval(&self, expr: &RbExpr, parallel: bool) -> Self {
39
39
  self.inner
40
40
  .clone()
41
- .arr()
41
+ .list()
42
42
  .eval(expr.inner.clone(), parallel)
43
43
  .into()
44
44
  }
45
45
 
46
46
  pub fn list_get(&self, index: &RbExpr) -> Self {
47
- self.inner.clone().arr().get(index.inner.clone()).into()
47
+ self.inner.clone().list().get(index.inner.clone()).into()
48
48
  }
49
49
 
50
50
  pub fn list_join(&self, separator: String) -> Self {
51
- self.inner.clone().arr().join(&separator).into()
51
+ self.inner.clone().list().join(&separator).into()
52
52
  }
53
53
 
54
54
  pub fn list_lengths(&self) -> Self {
55
- self.inner.clone().arr().lengths().into()
55
+ self.inner.clone().list().lengths().into()
56
56
  }
57
57
 
58
58
  pub fn list_max(&self) -> Self {
59
- self.inner.clone().arr().max().into()
59
+ self.inner.clone().list().max().into()
60
60
  }
61
61
 
62
62
  pub fn list_mean(&self) -> Self {
63
- self.inner.clone().arr().mean().with_fmt("arr.mean").into()
63
+ self.inner
64
+ .clone()
65
+ .list()
66
+ .mean()
67
+ .with_fmt("list.mean")
68
+ .into()
64
69
  }
65
70
 
66
71
  pub fn list_min(&self) -> Self {
67
- self.inner.clone().arr().min().into()
72
+ self.inner.clone().list().min().into()
68
73
  }
69
74
 
70
75
  pub fn list_reverse(&self) -> Self {
71
- self.inner.clone().arr().reverse().into()
76
+ self.inner.clone().list().reverse().into()
72
77
  }
73
78
 
74
79
  pub fn list_shift(&self, periods: i64) -> Self {
75
- self.inner.clone().arr().shift(periods).into()
80
+ self.inner.clone().list().shift(periods).into()
76
81
  }
77
82
 
78
83
  pub fn list_slice(&self, offset: &RbExpr, length: Option<&RbExpr>) -> Self {
@@ -82,7 +87,7 @@ impl RbExpr {
82
87
  };
83
88
  self.inner
84
89
  .clone()
85
- .arr()
90
+ .list()
86
91
  .slice(offset.inner.clone(), length)
87
92
  .into()
88
93
  }
@@ -90,23 +95,23 @@ impl RbExpr {
90
95
  pub fn list_sort(&self, reverse: bool) -> Self {
91
96
  self.inner
92
97
  .clone()
93
- .arr()
98
+ .list()
94
99
  .sort(SortOptions {
95
100
  descending: reverse,
96
101
  ..Default::default()
97
102
  })
98
- .with_fmt("arr.sort")
103
+ .with_fmt("list.sort")
99
104
  .into()
100
105
  }
101
106
 
102
107
  pub fn list_sum(&self) -> Self {
103
- self.inner.clone().arr().sum().with_fmt("arr.sum").into()
108
+ self.inner.clone().list().sum().with_fmt("list.sum").into()
104
109
  }
105
110
 
106
111
  pub fn list_take(&self, index: &RbExpr, null_on_oob: bool) -> Self {
107
112
  self.inner
108
113
  .clone()
109
- .arr()
114
+ .list()
110
115
  .take(index.inner.clone(), null_on_oob)
111
116
  .into()
112
117
  }
@@ -129,7 +134,7 @@ impl RbExpr {
129
134
  Ok(self
130
135
  .inner
131
136
  .clone()
132
- .arr()
137
+ .list()
133
138
  .to_struct(width_strat.0, name_gen, upper_bound)
134
139
  .into())
135
140
  }
@@ -138,9 +143,9 @@ impl RbExpr {
138
143
  let e = self.inner.clone();
139
144
 
140
145
  if maintain_order {
141
- e.arr().unique_stable().into()
146
+ e.list().unique_stable().into()
142
147
  } else {
143
- e.arr().unique().into()
148
+ e.list().unique().into()
144
149
  }
145
150
  }
146
151
  }
@@ -20,12 +20,10 @@ impl RbExpr {
20
20
  strict,
21
21
  exact,
22
22
  cache,
23
- ..Default::default()
24
23
  };
25
24
  self.inner.clone().str().to_date(options).into()
26
25
  }
27
26
 
28
- #[allow(clippy::too_many_arguments)]
29
27
  pub fn str_to_datetime(
30
28
  &self,
31
29
  format: Option<String>,
@@ -34,16 +32,12 @@ impl RbExpr {
34
32
  strict: bool,
35
33
  exact: bool,
36
34
  cache: bool,
37
- utc: bool,
38
- tz_aware: bool,
39
35
  ) -> Self {
40
36
  let options = StrptimeOptions {
41
37
  format,
42
38
  strict,
43
39
  exact,
44
40
  cache,
45
- tz_aware,
46
- utc,
47
41
  };
48
42
  self.inner
49
43
  .clone()
@@ -58,7 +52,6 @@ impl RbExpr {
58
52
  strict,
59
53
  cache,
60
54
  exact: true,
61
- ..Default::default()
62
55
  };
63
56
  self.inner.clone().str().to_time(options).into()
64
57
  }
@@ -87,6 +80,10 @@ impl RbExpr {
87
80
  .into()
88
81
  }
89
82
 
83
+ pub fn str_explode(&self) -> Self {
84
+ self.inner.clone().str().explode().into()
85
+ }
86
+
90
87
  pub fn str_to_uppercase(&self) -> Self {
91
88
  self.inner.clone().str().to_uppercase().into()
92
89
  }
@@ -233,7 +230,11 @@ impl RbExpr {
233
230
  .into()
234
231
  }
235
232
 
236
- pub fn str_json_extract(&self, dtype: Option<Wrap<DataType>>) -> Self {
233
+ pub fn str_json_extract(
234
+ &self,
235
+ dtype: Option<Wrap<DataType>>,
236
+ infer_schema_len: Option<usize>,
237
+ ) -> Self {
237
238
  let dtype = dtype.map(|wrap| wrap.0);
238
239
 
239
240
  let output_type = match dtype.clone() {
@@ -243,7 +244,7 @@ impl RbExpr {
243
244
 
244
245
  let function = move |s: Series| {
245
246
  let ca = s.utf8()?;
246
- match ca.json_extract(dtype.clone()) {
247
+ match ca.json_extract(dtype.clone(), infer_schema_len) {
247
248
  Ok(ca) => Ok(Some(ca.into_series())),
248
249
  Err(e) => Err(PolarsError::ComputeError(format!("{e:?}").into())),
249
250
  }
@@ -1,3 +1,4 @@
1
+ mod array;
1
2
  mod binary;
2
3
  mod categorical;
3
4
  mod datetime;
@@ -1,4 +1,5 @@
1
- use magnus::{class, RArray, RString, Value};
1
+ use magnus::encoding::{self, EncodingCapable};
2
+ use magnus::{class, Float, Integer, RArray, RString, Value};
2
3
  use polars::lazy::dsl;
3
4
  use polars::prelude::*;
4
5
 
@@ -6,7 +7,7 @@ use crate::apply::lazy::binary_lambda;
6
7
  use crate::conversion::{get_lf, get_rbseq, Wrap};
7
8
  use crate::prelude::vec_extract_wrapped;
8
9
  use crate::rb_exprs_to_exprs;
9
- use crate::{RbDataFrame, RbExpr, RbLazyFrame, RbPolarsErr, RbResult, RbSeries};
10
+ use crate::{RbDataFrame, RbExpr, RbLazyFrame, RbPolarsErr, RbResult, RbSeries, RbValueError};
10
11
 
11
12
  macro_rules! set_unwrapped_or_0 {
12
13
  ($($var:ident),+ $(,)?) => {
@@ -57,7 +58,12 @@ pub fn cols(names: Vec<String>) -> RbExpr {
57
58
  dsl::cols(names).into()
58
59
  }
59
60
 
60
- pub fn concat_lf(lfs: Value, rechunk: bool, parallel: bool) -> RbResult<RbLazyFrame> {
61
+ pub fn concat_lf(
62
+ lfs: Value,
63
+ rechunk: bool,
64
+ parallel: bool,
65
+ to_supertypes: bool,
66
+ ) -> RbResult<RbLazyFrame> {
61
67
  let (seq, len) = get_rbseq(lfs)?;
62
68
  let mut lfs = Vec::with_capacity(len);
63
69
 
@@ -67,7 +73,15 @@ pub fn concat_lf(lfs: Value, rechunk: bool, parallel: bool) -> RbResult<RbLazyFr
67
73
  lfs.push(lf);
68
74
  }
69
75
 
70
- let lf = polars::lazy::dsl::concat(lfs, rechunk, parallel).map_err(RbPolarsErr::from)?;
76
+ let lf = dsl::concat(
77
+ lfs,
78
+ UnionArgs {
79
+ rechunk,
80
+ parallel,
81
+ to_supertypes,
82
+ },
83
+ )
84
+ .map_err(RbPolarsErr::from)?;
71
85
  Ok(lf.into())
72
86
  }
73
87
 
@@ -135,16 +149,11 @@ pub fn cumfold(acc: &RbExpr, lambda: Value, exprs: RArray, include_init: bool) -
135
149
  Ok(polars::lazy::dsl::cumfold_exprs(acc.inner.clone(), func, exprs, include_init).into())
136
150
  }
137
151
 
138
- // TODO improve
139
- pub fn lit(value: Value) -> RbResult<RbExpr> {
140
- if value.is_nil() {
141
- Ok(dsl::lit(Null {}).into())
142
- } else if let Ok(series) = value.try_convert::<&RbSeries>() {
143
- Ok(dsl::lit(series.series.borrow().clone()).into())
144
- } else if let Some(v) = RString::from_value(value) {
145
- Ok(dsl::lit(v.try_convert::<String>()?).into())
146
- } else if value.is_kind_of(class::integer()) {
147
- match value.try_convert::<i64>() {
152
+ pub fn lit(value: Value, allow_object: bool) -> RbResult<RbExpr> {
153
+ if value.is_kind_of(class::true_class()) || value.is_kind_of(class::false_class()) {
154
+ Ok(dsl::lit(value.try_convert::<bool>()?).into())
155
+ } else if let Some(v) = Integer::from_value(value) {
156
+ match v.try_convert::<i64>() {
148
157
  Ok(val) => {
149
158
  if val > 0 && val < i32::MAX as i64 || val < 0 && val > i32::MIN as i64 {
150
159
  Ok(dsl::lit(val as i32).into())
@@ -157,17 +166,47 @@ pub fn lit(value: Value) -> RbResult<RbExpr> {
157
166
  Ok(dsl::lit(val).into())
158
167
  }
159
168
  }
169
+ } else if let Some(v) = Float::from_value(value) {
170
+ Ok(dsl::lit(v.try_convert::<f64>()?).into())
171
+ } else if let Some(v) = RString::from_value(value) {
172
+ if v.enc_get() == encoding::Index::utf8() {
173
+ Ok(dsl::lit(v.try_convert::<String>()?).into())
174
+ } else {
175
+ Ok(dsl::lit(unsafe { v.as_slice() }).into())
176
+ }
177
+ } else if let Ok(series) = value.try_convert::<&RbSeries>() {
178
+ Ok(dsl::lit(series.series.borrow().clone()).into())
179
+ } else if value.is_nil() {
180
+ Ok(dsl::lit(Null {}).into())
181
+ } else if allow_object {
182
+ todo!()
160
183
  } else {
161
- Ok(dsl::lit(value.try_convert::<f64>()?).into())
184
+ Err(RbValueError::new_err(format!(
185
+ "could not convert value {:?} as a Literal",
186
+ value.to_string()
187
+ )))
162
188
  }
163
189
  }
164
190
 
165
- pub fn repeat(value: Value, n_times: &RbExpr) -> RbResult<RbExpr> {
166
- if value.is_nil() {
167
- Ok(polars::lazy::dsl::repeat(Null {}, n_times.inner.clone()).into())
168
- } else {
169
- todo!();
191
+ pub fn repeat(value: &RbExpr, n: &RbExpr, dtype: Option<Wrap<DataType>>) -> RbResult<RbExpr> {
192
+ let mut value = value.inner.clone();
193
+ let n = n.inner.clone();
194
+
195
+ if let Some(dtype) = dtype {
196
+ value = value.cast(dtype.0);
197
+ }
198
+
199
+ if let Expr::Literal(lv) = &value {
200
+ let av = lv.to_anyvalue().unwrap();
201
+ // Integer inputs that fit in Int32 are parsed as such
202
+ if let DataType::Int64 = av.dtype() {
203
+ let int_value = av.try_extract::<i64>().unwrap();
204
+ if int_value >= i32::MIN as i64 && int_value <= i32::MAX as i64 {
205
+ value = value.cast(DataType::Int32);
206
+ }
207
+ }
170
208
  }
209
+ Ok(dsl::repeat(value, n).into())
171
210
  }
172
211
 
173
212
  pub fn pearson_corr(a: &RbExpr, b: &RbExpr, ddof: u8) -> RbExpr {
@@ -203,7 +242,8 @@ pub fn dtype_cols2(dtypes: RArray) -> RbResult<RbExpr> {
203
242
  Ok(crate::functions::lazy::dtype_cols(dtypes))
204
243
  }
205
244
 
245
+ // TODO rename to sum_horizontal
206
246
  pub fn sum_exprs(exprs: RArray) -> RbResult<RbExpr> {
207
247
  let exprs = rb_exprs_to_exprs(exprs)?;
208
- Ok(polars::lazy::dsl::sum_exprs(exprs).into())
248
+ Ok(polars::lazy::dsl::sum_horizontal(exprs).into())
209
249
  }
@@ -230,7 +230,13 @@ impl RbLazyFrame {
230
230
  ldf.into()
231
231
  }
232
232
 
233
- pub fn sort(&self, by_column: String, reverse: bool, nulls_last: bool) -> Self {
233
+ pub fn sort(
234
+ &self,
235
+ by_column: String,
236
+ reverse: bool,
237
+ nulls_last: bool,
238
+ maintain_order: bool,
239
+ ) -> Self {
234
240
  let ldf = self.ldf.clone();
235
241
  ldf.sort(
236
242
  &by_column,
@@ -238,6 +244,7 @@ impl RbLazyFrame {
238
244
  descending: reverse,
239
245
  nulls_last,
240
246
  multithreaded: true,
247
+ maintain_order,
241
248
  },
242
249
  )
243
250
  .into()
@@ -248,10 +255,13 @@ impl RbLazyFrame {
248
255
  by_column: RArray,
249
256
  reverse: Vec<bool>,
250
257
  nulls_last: bool,
258
+ maintain_order: bool,
251
259
  ) -> RbResult<Self> {
252
260
  let ldf = self.ldf.clone();
253
261
  let exprs = rb_exprs_to_exprs(by_column)?;
254
- Ok(ldf.sort_by_exprs(exprs, reverse, nulls_last).into())
262
+ Ok(ldf
263
+ .sort_by_exprs(exprs, reverse, nulls_last, maintain_order)
264
+ .into())
255
265
  }
256
266
 
257
267
  pub fn cache(&self) -> Self {
@@ -328,6 +338,7 @@ impl RbLazyFrame {
328
338
  offset: String,
329
339
  closed: Wrap<ClosedWindow>,
330
340
  by: RArray,
341
+ check_sorted: bool,
331
342
  ) -> RbResult<RbLazyGroupBy> {
332
343
  let closed_window = closed.0;
333
344
  let ldf = self.ldf.clone();
@@ -340,6 +351,7 @@ impl RbLazyFrame {
340
351
  period: Duration::parse(&period),
341
352
  offset: Duration::parse(&offset),
342
353
  closed_window,
354
+ check_sorted,
343
355
  },
344
356
  );
345
357