polars-df 0.15.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +274 -0
  3. data/Cargo.lock +1465 -867
  4. data/Cargo.toml +3 -0
  5. data/LICENSE.txt +2 -2
  6. data/README.md +87 -37
  7. data/ext/polars/Cargo.toml +47 -16
  8. data/ext/polars/src/c_api/allocator.rs +7 -0
  9. data/ext/polars/src/c_api/mod.rs +1 -0
  10. data/ext/polars/src/catalog/mod.rs +1 -0
  11. data/ext/polars/src/catalog/unity.rs +470 -0
  12. data/ext/polars/src/conversion/any_value.rs +99 -84
  13. data/ext/polars/src/conversion/categorical.rs +30 -0
  14. data/ext/polars/src/conversion/chunked_array.rs +71 -62
  15. data/ext/polars/src/conversion/datetime.rs +63 -0
  16. data/ext/polars/src/conversion/mod.rs +796 -312
  17. data/ext/polars/src/dataframe/construction.rs +6 -18
  18. data/ext/polars/src/dataframe/export.rs +30 -39
  19. data/ext/polars/src/dataframe/general.rs +294 -362
  20. data/ext/polars/src/dataframe/io.rs +33 -150
  21. data/ext/polars/src/dataframe/map.rs +175 -0
  22. data/ext/polars/src/dataframe/mod.rs +37 -5
  23. data/ext/polars/src/dataframe/serde.rs +23 -8
  24. data/ext/polars/src/error.rs +44 -7
  25. data/ext/polars/src/exceptions.rs +21 -8
  26. data/ext/polars/src/expr/array.rs +86 -22
  27. data/ext/polars/src/expr/binary.rs +50 -1
  28. data/ext/polars/src/expr/bitwise.rs +39 -0
  29. data/ext/polars/src/expr/categorical.rs +20 -0
  30. data/ext/polars/src/expr/datatype.rs +51 -0
  31. data/ext/polars/src/expr/datetime.rs +99 -41
  32. data/ext/polars/src/expr/extension.rs +12 -0
  33. data/ext/polars/src/expr/general.rs +252 -128
  34. data/ext/polars/src/expr/list.rs +56 -60
  35. data/ext/polars/src/expr/meta.rs +30 -35
  36. data/ext/polars/src/expr/mod.rs +28 -6
  37. data/ext/polars/src/expr/name.rs +29 -14
  38. data/ext/polars/src/expr/rolling.rs +111 -3
  39. data/ext/polars/src/expr/selector.rs +219 -0
  40. data/ext/polars/src/expr/serde.rs +28 -0
  41. data/ext/polars/src/expr/string.rs +118 -20
  42. data/ext/polars/src/expr/struct.rs +14 -1
  43. data/ext/polars/src/file.rs +194 -86
  44. data/ext/polars/src/functions/aggregation.rs +13 -12
  45. data/ext/polars/src/functions/business.rs +2 -3
  46. data/ext/polars/src/functions/eager.rs +3 -2
  47. data/ext/polars/src/functions/io.rs +90 -18
  48. data/ext/polars/src/functions/lazy.rs +267 -118
  49. data/ext/polars/src/functions/meta.rs +8 -7
  50. data/ext/polars/src/functions/misc.rs +1 -1
  51. data/ext/polars/src/functions/mod.rs +2 -1
  52. data/ext/polars/src/functions/range.rs +88 -31
  53. data/ext/polars/src/functions/strings.rs +6 -0
  54. data/ext/polars/src/functions/utils.rs +8 -0
  55. data/ext/polars/src/interop/arrow/mod.rs +52 -1
  56. data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +37 -7
  57. data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
  58. data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
  59. data/ext/polars/src/interop/numo/to_numo_series.rs +72 -50
  60. data/ext/polars/src/io/cloud_options.rs +107 -0
  61. data/ext/polars/src/io/mod.rs +4 -0
  62. data/ext/polars/src/io/scan_options.rs +113 -0
  63. data/ext/polars/src/io/sink_options.rs +46 -0
  64. data/ext/polars/src/io/sink_output.rs +21 -0
  65. data/ext/polars/src/lazyframe/exitable.rs +39 -0
  66. data/ext/polars/src/lazyframe/general.rs +846 -368
  67. data/ext/polars/src/lazyframe/mod.rs +58 -5
  68. data/ext/polars/src/lazyframe/optflags.rs +59 -0
  69. data/ext/polars/src/lazyframe/serde.rs +36 -4
  70. data/ext/polars/src/lazyframe/sink.rs +46 -0
  71. data/ext/polars/src/lazygroupby.rs +38 -9
  72. data/ext/polars/src/lib.rs +574 -165
  73. data/ext/polars/src/map/lazy.rs +44 -74
  74. data/ext/polars/src/map/mod.rs +18 -254
  75. data/ext/polars/src/map/series.rs +241 -1087
  76. data/ext/polars/src/on_startup.rs +192 -9
  77. data/ext/polars/src/prelude.rs +1 -0
  78. data/ext/polars/src/rb_modules.rs +10 -57
  79. data/ext/polars/src/ruby/exceptions.rs +26 -0
  80. data/ext/polars/src/ruby/gvl.rs +104 -0
  81. data/ext/polars/src/ruby/lazy.rs +46 -0
  82. data/ext/polars/src/ruby/mod.rs +11 -0
  83. data/ext/polars/src/ruby/numo.rs +52 -0
  84. data/ext/polars/src/ruby/plan_callback.rs +198 -0
  85. data/ext/polars/src/ruby/rb_modules.rs +16 -0
  86. data/ext/polars/src/ruby/ruby_convert_registry.rs +51 -0
  87. data/ext/polars/src/ruby/ruby_function.rs +11 -0
  88. data/ext/polars/src/ruby/ruby_udf.rs +164 -0
  89. data/ext/polars/src/ruby/thread.rs +65 -0
  90. data/ext/polars/src/ruby/utils.rs +39 -0
  91. data/ext/polars/src/series/aggregation.rs +116 -91
  92. data/ext/polars/src/series/arithmetic.rs +16 -22
  93. data/ext/polars/src/series/comparison.rs +101 -222
  94. data/ext/polars/src/series/construction.rs +80 -70
  95. data/ext/polars/src/series/export.rs +98 -56
  96. data/ext/polars/src/series/general.rs +323 -440
  97. data/ext/polars/src/series/import.rs +22 -5
  98. data/ext/polars/src/series/map.rs +103 -0
  99. data/ext/polars/src/series/mod.rs +57 -15
  100. data/ext/polars/src/series/scatter.rs +139 -82
  101. data/ext/polars/src/sql.rs +16 -9
  102. data/ext/polars/src/testing/frame.rs +31 -0
  103. data/ext/polars/src/testing/mod.rs +5 -0
  104. data/ext/polars/src/testing/series.rs +31 -0
  105. data/ext/polars/src/timeout.rs +105 -0
  106. data/ext/polars/src/utils.rs +105 -4
  107. data/lib/polars/array_expr.rb +500 -22
  108. data/lib/polars/array_name_space.rb +384 -10
  109. data/lib/polars/batched_csv_reader.rb +48 -66
  110. data/lib/polars/binary_expr.rb +217 -0
  111. data/lib/polars/binary_name_space.rb +155 -1
  112. data/lib/polars/cat_expr.rb +224 -0
  113. data/lib/polars/cat_name_space.rb +132 -32
  114. data/lib/polars/catalog/unity/catalog_info.rb +20 -0
  115. data/lib/polars/catalog/unity/column_info.rb +31 -0
  116. data/lib/polars/catalog/unity/namespace_info.rb +21 -0
  117. data/lib/polars/catalog/unity/table_info.rb +50 -0
  118. data/lib/polars/catalog.rb +448 -0
  119. data/lib/polars/collect_batches.rb +22 -0
  120. data/lib/polars/config.rb +3 -3
  121. data/lib/polars/convert.rb +201 -36
  122. data/lib/polars/data_frame.rb +2851 -1017
  123. data/lib/polars/data_frame_plot.rb +173 -0
  124. data/lib/polars/data_type_expr.rb +52 -0
  125. data/lib/polars/data_type_group.rb +6 -0
  126. data/lib/polars/data_types.rb +118 -18
  127. data/lib/polars/date_time_expr.rb +426 -84
  128. data/lib/polars/date_time_name_space.rb +384 -111
  129. data/lib/polars/dynamic_group_by.rb +102 -10
  130. data/lib/polars/exceptions.rb +50 -5
  131. data/lib/polars/expr.rb +2159 -915
  132. data/lib/polars/extension_expr.rb +39 -0
  133. data/lib/polars/extension_name_space.rb +39 -0
  134. data/lib/polars/functions/aggregation/horizontal.rb +11 -6
  135. data/lib/polars/functions/aggregation/vertical.rb +2 -3
  136. data/lib/polars/functions/as_datatype.rb +290 -8
  137. data/lib/polars/functions/business.rb +95 -0
  138. data/lib/polars/functions/col.rb +6 -5
  139. data/lib/polars/functions/datatype.rb +62 -0
  140. data/lib/polars/functions/eager.rb +426 -24
  141. data/lib/polars/functions/escape_regex.rb +21 -0
  142. data/lib/polars/functions/lazy.rb +813 -195
  143. data/lib/polars/functions/lit.rb +21 -10
  144. data/lib/polars/functions/range/int_range.rb +74 -2
  145. data/lib/polars/functions/range/linear_space.rb +195 -0
  146. data/lib/polars/functions/range/time_range.rb +1 -1
  147. data/lib/polars/functions/repeat.rb +7 -12
  148. data/lib/polars/functions/whenthen.rb +2 -2
  149. data/lib/polars/group_by.rb +188 -58
  150. data/lib/polars/iceberg_dataset.rb +108 -0
  151. data/lib/polars/in_process_query.rb +37 -0
  152. data/lib/polars/io/cloud.rb +18 -0
  153. data/lib/polars/io/csv.rb +336 -128
  154. data/lib/polars/io/database.rb +19 -4
  155. data/lib/polars/io/delta.rb +134 -0
  156. data/lib/polars/io/iceberg.rb +34 -0
  157. data/lib/polars/io/ipc.rb +63 -63
  158. data/lib/polars/io/json.rb +16 -0
  159. data/lib/polars/io/lines.rb +172 -0
  160. data/lib/polars/io/ndjson.rb +176 -20
  161. data/lib/polars/io/parquet.rb +173 -95
  162. data/lib/polars/io/scan_options.rb +55 -0
  163. data/lib/polars/io/sink_options.rb +27 -0
  164. data/lib/polars/io/utils.rb +17 -0
  165. data/lib/polars/lazy_frame.rb +3017 -622
  166. data/lib/polars/lazy_group_by.rb +436 -2
  167. data/lib/polars/list_expr.rb +551 -59
  168. data/lib/polars/list_name_space.rb +465 -51
  169. data/lib/polars/meta_expr.rb +146 -24
  170. data/lib/polars/name_expr.rb +87 -2
  171. data/lib/polars/query_opt_flags.rb +264 -0
  172. data/lib/polars/rolling_group_by.rb +90 -5
  173. data/lib/polars/scan_cast_options.rb +86 -0
  174. data/lib/polars/schema.rb +128 -0
  175. data/lib/polars/selector.rb +245 -0
  176. data/lib/polars/selectors.rb +1048 -201
  177. data/lib/polars/series.rb +2522 -774
  178. data/lib/polars/series_plot.rb +72 -0
  179. data/lib/polars/slice.rb +1 -1
  180. data/lib/polars/sql_context.rb +13 -6
  181. data/lib/polars/string_cache.rb +19 -72
  182. data/lib/polars/string_expr.rb +561 -107
  183. data/lib/polars/string_name_space.rb +781 -109
  184. data/lib/polars/struct_expr.rb +139 -18
  185. data/lib/polars/struct_name_space.rb +19 -1
  186. data/lib/polars/testing.rb +24 -273
  187. data/lib/polars/utils/constants.rb +2 -0
  188. data/lib/polars/utils/construction/data_frame.rb +410 -0
  189. data/lib/polars/utils/construction/series.rb +350 -0
  190. data/lib/polars/utils/construction/utils.rb +9 -0
  191. data/lib/polars/utils/convert.rb +18 -8
  192. data/lib/polars/utils/deprecation.rb +11 -0
  193. data/lib/polars/utils/parse.rb +62 -9
  194. data/lib/polars/utils/reduce_balanced.rb +43 -0
  195. data/lib/polars/utils/serde.rb +22 -0
  196. data/lib/polars/utils/unstable.rb +19 -0
  197. data/lib/polars/utils/various.rb +86 -1
  198. data/lib/polars/utils.rb +63 -48
  199. data/lib/polars/version.rb +1 -1
  200. data/lib/polars.rb +85 -2
  201. metadata +80 -28
  202. data/ext/polars/src/allocator.rs +0 -13
  203. data/ext/polars/src/batched_csv.rs +0 -138
  204. data/ext/polars/src/functions/string_cache.rs +0 -25
  205. data/ext/polars/src/map/dataframe.rs +0 -338
  206. data/lib/polars/plot.rb +0 -109
@@ -1,4 +1,4 @@
1
- use magnus::{prelude::*, value::Opaque, Ruby, Value};
1
+ use magnus::{RArray, prelude::*};
2
2
  use polars::lazy::dsl::lit;
3
3
  use polars::prelude::*;
4
4
  use polars::series::ops::NullBehavior;
@@ -7,14 +7,6 @@ use crate::conversion::Wrap;
7
7
  use crate::{RbExpr, RbResult};
8
8
 
9
9
  impl RbExpr {
10
- pub fn list_all(&self) -> Self {
11
- self.inner.clone().list().all().into()
12
- }
13
-
14
- pub fn list_any(&self) -> Self {
15
- self.inner.clone().list().any().into()
16
- }
17
-
18
10
  pub fn list_arg_max(&self) -> Self {
19
11
  self.inner.clone().list().arg_max().into()
20
12
  }
@@ -23,11 +15,11 @@ impl RbExpr {
23
15
  self.inner.clone().list().arg_min().into()
24
16
  }
25
17
 
26
- pub fn list_contains(&self, other: &RbExpr) -> Self {
18
+ pub fn list_contains(&self, other: &RbExpr, nulls_equal: bool) -> Self {
27
19
  self.inner
28
20
  .clone()
29
21
  .list()
30
- .contains(other.inner.clone())
22
+ .contains(other.inner.clone(), nulls_equal)
31
23
  .into()
32
24
  }
33
25
 
@@ -43,11 +35,19 @@ impl RbExpr {
43
35
  Ok(self.inner.clone().list().diff(n, null_behavior.0).into())
44
36
  }
45
37
 
46
- pub fn list_eval(&self, expr: &RbExpr, parallel: bool) -> Self {
38
+ pub fn list_eval(&self, expr: &RbExpr) -> Self {
39
+ self.inner.clone().list().eval(expr.inner.clone()).into()
40
+ }
41
+
42
+ pub fn list_agg(&self, expr: &RbExpr) -> Self {
43
+ self.inner.clone().list().agg(expr.inner.clone()).into()
44
+ }
45
+
46
+ pub fn list_filter(&self, predicate: &RbExpr) -> Self {
47
47
  self.inner
48
48
  .clone()
49
49
  .list()
50
- .eval(expr.inner.clone(), parallel)
50
+ .eval(Expr::Column(PlSmallStr::EMPTY).filter(predicate.inner.clone()))
51
51
  .into()
52
52
  }
53
53
 
@@ -76,20 +76,23 @@ impl RbExpr {
76
76
  }
77
77
 
78
78
  pub fn list_mean(&self) -> Self {
79
- self.inner
80
- .clone()
81
- .list()
82
- .mean()
83
- .with_fmt("list.mean")
84
- .into()
79
+ self.inner.clone().list().mean().into()
85
80
  }
86
81
 
87
- pub fn list_min(&self) -> Self {
88
- self.inner.clone().list().min().into()
82
+ pub fn list_median(&self) -> Self {
83
+ self.inner.clone().list().median().into()
89
84
  }
90
85
 
91
- pub fn list_reverse(&self) -> Self {
92
- self.inner.clone().list().reverse().into()
86
+ pub fn list_std(&self, ddof: u8) -> Self {
87
+ self.inner.clone().list().std(ddof).into()
88
+ }
89
+
90
+ pub fn list_var(&self, ddof: u8) -> Self {
91
+ self.inner.clone().list().var(ddof).into()
92
+ }
93
+
94
+ pub fn list_min(&self) -> Self {
95
+ self.inner.clone().list().min().into()
93
96
  }
94
97
 
95
98
  pub fn list_shift(&self, periods: &RbExpr) -> Self {
@@ -116,20 +119,20 @@ impl RbExpr {
116
119
  self.inner.clone().list().tail(n.inner.clone()).into()
117
120
  }
118
121
 
119
- pub fn list_sort(&self, reverse: bool) -> Self {
122
+ pub fn list_sort(&self, descending: bool, nulls_last: bool) -> Self {
120
123
  self.inner
121
124
  .clone()
122
125
  .list()
123
- .sort(SortOptions {
124
- descending: reverse,
125
- ..Default::default()
126
- })
127
- .with_fmt("list.sort")
126
+ .sort(
127
+ SortOptions::default()
128
+ .with_order_descending(descending)
129
+ .with_nulls_last(nulls_last),
130
+ )
128
131
  .into()
129
132
  }
130
133
 
131
134
  pub fn list_sum(&self) -> Self {
132
- self.inner.clone().list().sum().with_fmt("list.sum").into()
135
+ self.inner.clone().list().sum().into()
133
136
  }
134
137
 
135
138
  pub fn list_drop_nulls(&self) -> Self {
@@ -172,47 +175,40 @@ impl RbExpr {
172
175
  .into()
173
176
  }
174
177
 
178
+ pub fn list_gather_every(&self, n: &RbExpr, offset: &RbExpr) -> Self {
179
+ self.inner
180
+ .clone()
181
+ .list()
182
+ .gather_every(n.inner.clone(), offset.inner.clone())
183
+ .into()
184
+ }
185
+
175
186
  pub fn list_to_array(&self, width: usize) -> Self {
176
187
  self.inner.clone().list().to_array(width).into()
177
188
  }
178
189
 
179
- pub fn list_to_struct(
180
- &self,
181
- width_strat: Wrap<ListToStructWidthStrategy>,
182
- name_gen: Option<Value>,
183
- upper_bound: usize,
184
- ) -> RbResult<Self> {
185
- let name_gen = name_gen.map(|lambda| {
186
- let lambda = Opaque::from(lambda);
187
- Arc::new(move |idx: usize| {
188
- let lambda = Ruby::get().unwrap().get_inner(lambda);
189
- let out: String = lambda.funcall("call", (idx,)).unwrap();
190
- PlSmallStr::from_string(out)
191
- });
192
-
193
- // non-Ruby thread
194
- todo!();
195
- });
196
-
190
+ pub fn list_to_struct(&self, names: RArray) -> RbResult<Self> {
197
191
  Ok(self
198
192
  .inner
199
193
  .clone()
200
194
  .list()
201
- .to_struct(ListToStructArgs::InferWidth {
202
- infer_field_strategy: width_strat.0,
203
- get_index_name: name_gen,
204
- max_fields: upper_bound,
205
- })
195
+ .to_struct(
196
+ names
197
+ .into_iter()
198
+ .map(|x| Ok(Wrap::<PlSmallStr>::try_convert(x)?.0))
199
+ .collect::<RbResult<Arc<[_]>>>()?,
200
+ )
206
201
  .into())
207
202
  }
208
203
 
209
- pub fn list_unique(&self, maintain_order: bool) -> Self {
210
- let e = self.inner.clone();
211
-
212
- if maintain_order {
213
- e.list().unique_stable().into()
214
- } else {
215
- e.list().unique().into()
204
+ pub fn list_set_operation(&self, other: &RbExpr, operation: Wrap<SetOperation>) -> Self {
205
+ let e = self.inner.clone().list();
206
+ match operation.0 {
207
+ SetOperation::Intersection => e.set_intersection(other.inner.clone()),
208
+ SetOperation::Difference => e.set_difference(other.inner.clone()),
209
+ SetOperation::Union => e.union(other.inner.clone()),
210
+ SetOperation::SymmetricDifference => e.set_symmetric_difference(other.inner.clone()),
216
211
  }
212
+ .into()
217
213
  }
218
214
  }
@@ -1,17 +1,23 @@
1
- use magnus::RArray;
1
+ use magnus::{RArray, Ruby};
2
+ use polars::prelude::Schema;
2
3
 
3
- use crate::{RbExpr, RbPolarsErr, RbResult};
4
+ use crate::expr::ToRbExprs;
5
+ use crate::{RbExpr, RbPolarsErr, RbResult, Wrap};
4
6
 
5
7
  impl RbExpr {
6
8
  pub fn meta_eq(&self, other: &RbExpr) -> bool {
7
9
  self.inner == other.inner
8
10
  }
9
11
 
10
- pub fn meta_pop(&self) -> RbResult<RArray> {
11
- let exprs = self.inner.clone().meta().pop().map_err(RbPolarsErr::from)?;
12
- Ok(RArray::from_iter(
13
- exprs.iter().map(|e| RbExpr::from(e.clone())),
14
- ))
12
+ pub fn meta_pop(ruby: &Ruby, self_: &Self, schema: Option<Wrap<Schema>>) -> RbResult<RArray> {
13
+ let schema = schema.as_ref().map(|s| &s.0);
14
+ let exprs = self_
15
+ .inner
16
+ .clone()
17
+ .meta()
18
+ .pop(schema)
19
+ .map_err(RbPolarsErr::from)?;
20
+ Ok(exprs.to_rbexprs(ruby))
15
21
  }
16
22
 
17
23
  pub fn meta_root_names(&self) -> Vec<String> {
@@ -50,47 +56,36 @@ impl RbExpr {
50
56
  self.inner.clone().meta().is_regex_projection()
51
57
  }
52
58
 
53
- pub fn _meta_selector_add(&self, other: &RbExpr) -> RbResult<RbExpr> {
54
- let out = self
55
- .inner
59
+ pub fn meta_is_column_selection(&self, allow_aliasing: bool) -> bool {
60
+ self.inner
56
61
  .clone()
57
62
  .meta()
58
- ._selector_add(other.inner.clone())
59
- .map_err(RbPolarsErr::from)?;
60
- Ok(out.into())
63
+ .is_column_selection(allow_aliasing)
61
64
  }
62
65
 
63
- pub fn _meta_selector_sub(&self, other: &RbExpr) -> RbResult<RbExpr> {
64
- let out = self
65
- .inner
66
- .clone()
67
- .meta()
68
- ._selector_sub(other.inner.clone())
69
- .map_err(RbPolarsErr::from)?;
70
- Ok(out.into())
66
+ pub fn meta_is_literal(&self, allow_aliasing: bool) -> bool {
67
+ self.inner.clone().meta().is_literal(allow_aliasing)
71
68
  }
72
69
 
73
- pub fn _meta_selector_and(&self, other: &RbExpr) -> RbResult<RbExpr> {
74
- let out = self
70
+ fn compute_tree_format(
71
+ &self,
72
+ display_as_dot: bool,
73
+ schema: Option<Wrap<Schema>>,
74
+ ) -> RbResult<String> {
75
+ let e = self
75
76
  .inner
76
77
  .clone()
77
78
  .meta()
78
- ._selector_and(other.inner.clone())
79
+ .into_tree_formatter(display_as_dot, schema.as_ref().map(|s| &s.0))
79
80
  .map_err(RbPolarsErr::from)?;
80
- Ok(out.into())
81
+ Ok(format!("{e}"))
81
82
  }
82
83
 
83
- pub fn _meta_as_selector(&self) -> RbExpr {
84
- self.inner.clone().meta()._into_selector().into()
84
+ pub fn meta_tree_format(&self, schema: Option<Wrap<Schema>>) -> RbResult<String> {
85
+ self.compute_tree_format(false, schema)
85
86
  }
86
87
 
87
- pub fn meta_tree_format(&self) -> RbResult<String> {
88
- let e = self
89
- .inner
90
- .clone()
91
- .meta()
92
- .into_tree_formatter()
93
- .map_err(RbPolarsErr::from)?;
94
- Ok(format!("{e}"))
88
+ pub fn meta_show_graph(&self, schema: Option<Wrap<Schema>>) -> RbResult<String> {
89
+ self.compute_tree_format(true, schema)
95
90
  }
96
91
  }
@@ -1,16 +1,22 @@
1
1
  mod array;
2
2
  mod binary;
3
+ mod bitwise;
3
4
  mod categorical;
5
+ pub mod datatype;
4
6
  mod datetime;
7
+ mod extension;
5
8
  mod general;
6
9
  mod list;
7
10
  mod meta;
8
11
  mod name;
9
12
  mod rolling;
13
+ pub mod selector;
14
+ #[cfg(feature = "serialize_binary")]
15
+ mod serde;
10
16
  mod string;
11
17
  mod r#struct;
12
18
 
13
- use magnus::{prelude::*, RArray};
19
+ use magnus::{RArray, Ruby, prelude::*};
14
20
  use polars::lazy::dsl::Expr;
15
21
 
16
22
  use crate::RbResult;
@@ -27,10 +33,26 @@ impl From<Expr> for RbExpr {
27
33
  }
28
34
  }
29
35
 
30
- pub fn rb_exprs_to_exprs(rb_exprs: RArray) -> RbResult<Vec<Expr>> {
31
- let mut exprs = Vec::new();
32
- for item in rb_exprs.into_iter() {
33
- exprs.push(<&RbExpr>::try_convert(item)?.inner.clone());
36
+ pub(crate) trait ToExprs {
37
+ fn to_exprs(self) -> RbResult<Vec<Expr>>;
38
+ }
39
+
40
+ impl ToExprs for RArray {
41
+ fn to_exprs(self) -> RbResult<Vec<Expr>> {
42
+ let mut exprs = Vec::new();
43
+ for item in self.into_iter() {
44
+ exprs.push(<&RbExpr>::try_convert(item)?.inner.clone());
45
+ }
46
+ Ok(exprs)
47
+ }
48
+ }
49
+
50
+ pub(crate) trait ToRbExprs {
51
+ fn to_rbexprs(self, rb: &Ruby) -> RArray;
52
+ }
53
+
54
+ impl ToRbExprs for Vec<Expr> {
55
+ fn to_rbexprs(self, rb: &Ruby) -> RArray {
56
+ rb.ary_from_iter(self.iter().map(|e| RbExpr::from(e.clone())))
34
57
  }
35
- Ok(exprs)
36
58
  }
@@ -1,29 +1,20 @@
1
- use magnus::{block::Proc, value::Opaque, Ruby};
1
+ use magnus::Value;
2
2
  use polars::prelude::*;
3
- use polars_utils::format_pl_smallstr;
4
3
 
5
4
  use crate::RbExpr;
5
+ use crate::ruby::plan_callback::PlanCallbackExt;
6
+ use crate::ruby::ruby_function::RubyObject;
6
7
 
7
8
  impl RbExpr {
8
9
  pub fn name_keep(&self) -> Self {
9
10
  self.inner.clone().name().keep().into()
10
11
  }
11
12
 
12
- pub fn name_map(&self, lambda: Proc) -> Self {
13
- let lambda = Opaque::from(lambda);
13
+ pub fn name_map(&self, lambda: Value) -> Self {
14
14
  self.inner
15
15
  .clone()
16
16
  .name()
17
- .map(move |name| {
18
- let lambda = Ruby::get().unwrap().get_inner(lambda);
19
- let out = lambda.call::<_, String>((name.as_str(),));
20
- match out {
21
- Ok(out) => Ok(format_pl_smallstr!("{}", out)),
22
- Err(e) => Err(PolarsError::ComputeError(
23
- format!("Ruby function in 'name.map' produced an error: {}.", e).into(),
24
- )),
25
- }
26
- })
17
+ .map(PlanCallback::new_ruby(RubyObject::from(lambda)))
27
18
  .into()
28
19
  }
29
20
 
@@ -42,4 +33,28 @@ impl RbExpr {
42
33
  pub fn name_to_uppercase(&self) -> Self {
43
34
  self.inner.clone().name().to_uppercase().into()
44
35
  }
36
+
37
+ pub fn name_replace(&self, pattern: String, value: String, literal: bool) -> Self {
38
+ self.inner
39
+ .clone()
40
+ .name()
41
+ .replace(&pattern, &value, literal)
42
+ .into()
43
+ }
44
+
45
+ pub fn name_map_fields(&self, name_mapper: Value) -> Self {
46
+ self.inner
47
+ .clone()
48
+ .name()
49
+ .map_fields(PlanCallback::new_ruby(RubyObject::from(name_mapper)))
50
+ .into()
51
+ }
52
+
53
+ pub fn name_prefix_fields(&self, prefix: String) -> Self {
54
+ self.inner.clone().name().prefix_fields(&prefix).into()
55
+ }
56
+
57
+ pub fn name_suffix_fields(&self, suffix: String) -> Self {
58
+ self.inner.clone().name().suffix_fields(&suffix).into()
59
+ }
45
60
  }
@@ -1,7 +1,10 @@
1
+ use magnus::Value;
1
2
  use polars::prelude::*;
2
3
 
3
4
  use crate::conversion::Wrap;
4
- use crate::RbExpr;
5
+ use crate::ruby::plan_callback::PlanCallbackExt;
6
+ use crate::ruby::ruby_function::RubyObject;
7
+ use crate::{RbExpr, RbPolarsErr, RbResult};
5
8
 
6
9
  impl RbExpr {
7
10
  pub fn rolling_sum(
@@ -319,7 +322,112 @@ impl RbExpr {
319
322
  .into()
320
323
  }
321
324
 
322
- pub fn rolling_skew(&self, window_size: usize, bias: bool) -> Self {
323
- self.inner.clone().rolling_skew(window_size, bias).into()
325
+ pub fn rolling_rank(
326
+ &self,
327
+ window_size: usize,
328
+ method: Wrap<RollingRankMethod>,
329
+ seed: Option<u64>,
330
+ min_samples: Option<usize>,
331
+ center: bool,
332
+ ) -> Self {
333
+ let min_samples = min_samples.unwrap_or(window_size);
334
+ let options = RollingOptionsFixedWindow {
335
+ window_size,
336
+ min_periods: min_samples,
337
+ weights: None,
338
+ center,
339
+ fn_params: Some(RollingFnParams::Rank {
340
+ method: method.0,
341
+ seed,
342
+ }),
343
+ };
344
+
345
+ self.inner.clone().rolling_rank(options).into()
346
+ }
347
+
348
+ pub fn rolling_rank_by(
349
+ &self,
350
+ by: &RbExpr,
351
+ window_size: String,
352
+ method: Wrap<RollingRankMethod>,
353
+ seed: Option<u64>,
354
+ min_samples: usize,
355
+ closed: Wrap<ClosedWindow>,
356
+ ) -> RbResult<Self> {
357
+ let options = RollingOptionsDynamicWindow {
358
+ window_size: Duration::try_parse(&window_size).map_err(RbPolarsErr::from)?,
359
+ min_periods: min_samples,
360
+ closed_window: closed.0,
361
+ fn_params: Some(RollingFnParams::Rank {
362
+ method: method.0,
363
+ seed,
364
+ }),
365
+ };
366
+
367
+ Ok(self
368
+ .inner
369
+ .clone()
370
+ .rolling_rank_by(by.inner.clone(), options)
371
+ .into())
372
+ }
373
+
374
+ pub fn rolling_skew(
375
+ &self,
376
+ window_size: usize,
377
+ bias: bool,
378
+ min_periods: Option<usize>,
379
+ center: bool,
380
+ ) -> Self {
381
+ let min_periods = min_periods.unwrap_or(window_size);
382
+ let options = RollingOptionsFixedWindow {
383
+ window_size,
384
+ weights: None,
385
+ min_periods,
386
+ center,
387
+ fn_params: Some(RollingFnParams::Skew { bias }),
388
+ };
389
+
390
+ self.inner.clone().rolling_skew(options).into()
391
+ }
392
+
393
+ pub fn rolling_kurtosis(
394
+ &self,
395
+ window_size: usize,
396
+ fisher: bool,
397
+ bias: bool,
398
+ min_periods: Option<usize>,
399
+ center: bool,
400
+ ) -> Self {
401
+ let min_periods = min_periods.unwrap_or(window_size);
402
+ let options = RollingOptionsFixedWindow {
403
+ window_size,
404
+ weights: None,
405
+ min_periods,
406
+ center,
407
+ fn_params: Some(RollingFnParams::Kurtosis { fisher, bias }),
408
+ };
409
+
410
+ self.inner.clone().rolling_kurtosis(options).into()
411
+ }
412
+
413
+ pub fn rolling_map(
414
+ &self,
415
+ lambda: Value,
416
+ window_size: usize,
417
+ weights: Option<Vec<f64>>,
418
+ min_periods: Option<usize>,
419
+ center: bool,
420
+ ) -> Self {
421
+ let min_periods = min_periods.unwrap_or(window_size);
422
+ let options = RollingOptionsFixedWindow {
423
+ window_size,
424
+ weights,
425
+ min_periods,
426
+ center,
427
+ ..Default::default()
428
+ };
429
+ let function = PlanCallback::new_ruby(RubyObject::from(lambda));
430
+
431
+ self.inner.clone().rolling_map(function, options).into()
324
432
  }
325
433
  }