polars-df 0.10.0 → 0.12.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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Cargo.lock +392 -351
  4. data/README.md +6 -6
  5. data/ext/polars/Cargo.toml +12 -7
  6. data/ext/polars/src/batched_csv.rs +53 -52
  7. data/ext/polars/src/conversion/any_value.rs +261 -0
  8. data/ext/polars/src/conversion/chunked_array.rs +4 -4
  9. data/ext/polars/src/conversion/mod.rs +60 -66
  10. data/ext/polars/src/dataframe/construction.rs +184 -0
  11. data/ext/polars/src/dataframe/export.rs +48 -0
  12. data/ext/polars/src/dataframe/general.rs +597 -0
  13. data/ext/polars/src/dataframe/io.rs +473 -0
  14. data/ext/polars/src/dataframe/mod.rs +26 -0
  15. data/ext/polars/src/error.rs +26 -4
  16. data/ext/polars/src/expr/categorical.rs +0 -10
  17. data/ext/polars/src/expr/datetime.rs +4 -8
  18. data/ext/polars/src/expr/general.rs +129 -94
  19. data/ext/polars/src/expr/mod.rs +2 -2
  20. data/ext/polars/src/expr/rolling.rs +201 -77
  21. data/ext/polars/src/expr/string.rs +11 -36
  22. data/ext/polars/src/functions/eager.rs +10 -10
  23. data/ext/polars/src/functions/lazy.rs +23 -21
  24. data/ext/polars/src/functions/range.rs +69 -1
  25. data/ext/polars/src/interop/mod.rs +1 -0
  26. data/ext/polars/src/interop/numo/mod.rs +2 -0
  27. data/ext/polars/src/interop/numo/to_numo_df.rs +23 -0
  28. data/ext/polars/src/interop/numo/to_numo_series.rs +61 -0
  29. data/ext/polars/src/lazyframe/mod.rs +135 -136
  30. data/ext/polars/src/lib.rs +94 -59
  31. data/ext/polars/src/map/dataframe.rs +2 -2
  32. data/ext/polars/src/map/lazy.rs +5 -25
  33. data/ext/polars/src/map/series.rs +7 -1
  34. data/ext/polars/src/rb_modules.rs +25 -1
  35. data/ext/polars/src/series/aggregation.rs +49 -30
  36. data/ext/polars/src/series/arithmetic.rs +21 -11
  37. data/ext/polars/src/series/construction.rs +56 -38
  38. data/ext/polars/src/series/export.rs +131 -49
  39. data/ext/polars/src/series/mod.rs +32 -141
  40. data/ext/polars/src/sql.rs +3 -1
  41. data/lib/polars/array_expr.rb +4 -4
  42. data/lib/polars/batched_csv_reader.rb +11 -5
  43. data/lib/polars/cat_expr.rb +0 -36
  44. data/lib/polars/cat_name_space.rb +0 -37
  45. data/lib/polars/convert.rb +6 -1
  46. data/lib/polars/data_frame.rb +176 -403
  47. data/lib/polars/data_types.rb +1 -1
  48. data/lib/polars/date_time_expr.rb +525 -572
  49. data/lib/polars/date_time_name_space.rb +263 -460
  50. data/lib/polars/dynamic_group_by.rb +5 -5
  51. data/lib/polars/exceptions.rb +7 -0
  52. data/lib/polars/expr.rb +1394 -243
  53. data/lib/polars/expr_dispatch.rb +1 -1
  54. data/lib/polars/functions/aggregation/horizontal.rb +8 -8
  55. data/lib/polars/functions/as_datatype.rb +63 -40
  56. data/lib/polars/functions/lazy.rb +63 -14
  57. data/lib/polars/functions/lit.rb +1 -1
  58. data/lib/polars/functions/range/date_range.rb +90 -57
  59. data/lib/polars/functions/range/datetime_range.rb +149 -0
  60. data/lib/polars/functions/range/int_range.rb +2 -2
  61. data/lib/polars/functions/range/time_range.rb +141 -0
  62. data/lib/polars/functions/repeat.rb +1 -1
  63. data/lib/polars/functions/whenthen.rb +1 -1
  64. data/lib/polars/group_by.rb +88 -23
  65. data/lib/polars/io/avro.rb +24 -0
  66. data/lib/polars/{io.rb → io/csv.rb} +299 -493
  67. data/lib/polars/io/database.rb +73 -0
  68. data/lib/polars/io/ipc.rb +247 -0
  69. data/lib/polars/io/json.rb +29 -0
  70. data/lib/polars/io/ndjson.rb +80 -0
  71. data/lib/polars/io/parquet.rb +227 -0
  72. data/lib/polars/lazy_frame.rb +143 -272
  73. data/lib/polars/lazy_group_by.rb +100 -3
  74. data/lib/polars/list_expr.rb +11 -11
  75. data/lib/polars/list_name_space.rb +5 -1
  76. data/lib/polars/rolling_group_by.rb +7 -9
  77. data/lib/polars/series.rb +103 -187
  78. data/lib/polars/string_expr.rb +78 -102
  79. data/lib/polars/string_name_space.rb +5 -4
  80. data/lib/polars/testing.rb +2 -2
  81. data/lib/polars/utils/constants.rb +9 -0
  82. data/lib/polars/utils/convert.rb +97 -0
  83. data/lib/polars/utils/parse.rb +89 -0
  84. data/lib/polars/utils/various.rb +76 -0
  85. data/lib/polars/utils/wrap.rb +19 -0
  86. data/lib/polars/utils.rb +8 -300
  87. data/lib/polars/version.rb +1 -1
  88. data/lib/polars/whenthen.rb +6 -6
  89. data/lib/polars.rb +20 -1
  90. metadata +28 -7
  91. data/ext/polars/src/conversion/anyvalue.rs +0 -186
  92. data/ext/polars/src/dataframe.rs +0 -1208
@@ -5,6 +5,7 @@ mod error;
5
5
  mod expr;
6
6
  mod file;
7
7
  mod functions;
8
+ mod interop;
8
9
  mod lazyframe;
9
10
  mod lazygroupby;
10
11
  mod map;
@@ -59,18 +60,26 @@ fn init(ruby: &Ruby) -> RbResult<()> {
59
60
  class.define_singleton_method("read_csv", function!(RbDataFrame::read_csv, -1))?;
60
61
  class.define_singleton_method("read_parquet", function!(RbDataFrame::read_parquet, 9))?;
61
62
  class.define_singleton_method("read_ipc", function!(RbDataFrame::read_ipc, 6))?;
63
+ class.define_singleton_method(
64
+ "read_ipc_stream",
65
+ function!(RbDataFrame::read_ipc_stream, 6),
66
+ )?;
62
67
  class.define_singleton_method("read_avro", function!(RbDataFrame::read_avro, 4))?;
63
- class.define_singleton_method("read_rows", function!(RbDataFrame::read_rows, 3))?;
64
- class.define_singleton_method("read_hashes", function!(RbDataFrame::read_hashes, 4))?;
65
- class.define_singleton_method("read_hash", function!(RbDataFrame::read_hash, 1))?;
66
- class.define_singleton_method("read_json", function!(RbDataFrame::read_json, 1))?;
67
- class.define_singleton_method("read_ndjson", function!(RbDataFrame::read_ndjson, 1))?;
68
+ class.define_singleton_method("from_rows", function!(RbDataFrame::from_rows, 3))?;
69
+ class.define_singleton_method("from_hashes", function!(RbDataFrame::from_hashes, 5))?;
70
+ class.define_singleton_method("read_json", function!(RbDataFrame::read_json, 4))?;
71
+ class.define_singleton_method("read_ndjson", function!(RbDataFrame::read_ndjson, 4))?;
68
72
  class.define_method("estimated_size", method!(RbDataFrame::estimated_size, 0))?;
73
+ class.define_method("dtype_strings", method!(RbDataFrame::dtype_strings, 0))?;
69
74
  class.define_method("write_avro", method!(RbDataFrame::write_avro, 2))?;
70
75
  class.define_method("write_json", method!(RbDataFrame::write_json, 3))?;
71
76
  class.define_method("write_ndjson", method!(RbDataFrame::write_ndjson, 1))?;
72
77
  class.define_method("write_csv", method!(RbDataFrame::write_csv, 10))?;
73
78
  class.define_method("write_ipc", method!(RbDataFrame::write_ipc, 2))?;
79
+ class.define_method(
80
+ "write_ipc_stream",
81
+ method!(RbDataFrame::write_ipc_stream, 2),
82
+ )?;
74
83
  class.define_method("row_tuple", method!(RbDataFrame::row_tuple, 1))?;
75
84
  class.define_method("row_tuples", method!(RbDataFrame::row_tuples, 0))?;
76
85
  class.define_method("to_numo", method!(RbDataFrame::to_numo, 0))?;
@@ -88,7 +97,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
88
97
  class.define_method("sample_n", method!(RbDataFrame::sample_n, 4))?;
89
98
  class.define_method("sample_frac", method!(RbDataFrame::sample_frac, 4))?;
90
99
  class.define_method("rechunk", method!(RbDataFrame::rechunk, 0))?;
91
- class.define_method("to_s", method!(RbDataFrame::to_s, 0))?;
100
+ class.define_method("to_s", method!(RbDataFrame::as_str, 0))?;
92
101
  class.define_method("get_columns", method!(RbDataFrame::get_columns, 0))?;
93
102
  class.define_method("columns", method!(RbDataFrame::columns, 0))?;
94
103
  class.define_method(
@@ -106,8 +115,6 @@ fn init(ruby: &Ruby) -> RbResult<()> {
106
115
  class.define_method("vstack_mut", method!(RbDataFrame::vstack_mut, 1))?;
107
116
  class.define_method("vstack", method!(RbDataFrame::vstack, 1))?;
108
117
  class.define_method("drop_in_place", method!(RbDataFrame::drop_in_place, 1))?;
109
- class.define_method("drop_nulls", method!(RbDataFrame::drop_nulls, 1))?;
110
- class.define_method("drop", method!(RbDataFrame::drop, 1))?;
111
118
  class.define_method("select_at_idx", method!(RbDataFrame::select_at_idx, 1))?;
112
119
  class.define_method(
113
120
  "get_column_index",
@@ -115,7 +122,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
115
122
  )?;
116
123
  class.define_method("get_column", method!(RbDataFrame::get_column, 1))?;
117
124
  class.define_method("select", method!(RbDataFrame::select, 1))?;
118
- class.define_method("take", method!(RbDataFrame::take, 1))?;
125
+ class.define_method("take", method!(RbDataFrame::gather, 1))?;
119
126
  class.define_method(
120
127
  "take_with_series",
121
128
  method!(RbDataFrame::take_with_series, 1),
@@ -131,10 +138,9 @@ fn init(ruby: &Ruby) -> RbResult<()> {
131
138
  class.define_method("equals", method!(RbDataFrame::equals, 2))?;
132
139
  class.define_method("with_row_index", method!(RbDataFrame::with_row_index, 2))?;
133
140
  class.define_method("_clone", method!(RbDataFrame::clone, 0))?;
134
- class.define_method("melt", method!(RbDataFrame::melt, 4))?;
141
+ class.define_method("unpivot", method!(RbDataFrame::unpivot, 4))?;
135
142
  class.define_method("pivot_expr", method!(RbDataFrame::pivot_expr, 7))?;
136
143
  class.define_method("partition_by", method!(RbDataFrame::partition_by, 3))?;
137
- class.define_method("shift", method!(RbDataFrame::shift, 1))?;
138
144
  class.define_method("lazy", method!(RbDataFrame::lazy, 0))?;
139
145
  class.define_method("mean_horizontal", method!(RbDataFrame::mean_horizontal, 1))?;
140
146
  class.define_method("max_horizontal", method!(RbDataFrame::max_horizontal, 0))?;
@@ -142,11 +148,11 @@ fn init(ruby: &Ruby) -> RbResult<()> {
142
148
  class.define_method("sum_horizontal", method!(RbDataFrame::sum_horizontal, 1))?;
143
149
  class.define_method("to_dummies", method!(RbDataFrame::to_dummies, 3))?;
144
150
  class.define_method("null_count", method!(RbDataFrame::null_count, 0))?;
145
- class.define_method("apply", method!(RbDataFrame::apply, 3))?;
151
+ class.define_method("map_rows", method!(RbDataFrame::map_rows, 3))?;
146
152
  class.define_method("shrink_to_fit", method!(RbDataFrame::shrink_to_fit, 0))?;
147
153
  class.define_method("hash_rows", method!(RbDataFrame::hash_rows, 4))?;
148
154
  class.define_method("transpose", method!(RbDataFrame::transpose, 2))?;
149
- class.define_method("upsample", method!(RbDataFrame::upsample, 5))?;
155
+ class.define_method("upsample", method!(RbDataFrame::upsample, 4))?;
150
156
  class.define_method("to_struct", method!(RbDataFrame::to_struct, 1))?;
151
157
  class.define_method("unnest", method!(RbDataFrame::unnest, 1))?;
152
158
  class.define_method("clear", method!(RbDataFrame::clear, 0))?;
@@ -199,20 +205,23 @@ fn init(ruby: &Ruby) -> RbResult<()> {
199
205
  class.define_method("agg_groups", method!(RbExpr::agg_groups, 0))?;
200
206
  class.define_method("count", method!(RbExpr::count, 0))?;
201
207
  class.define_method("len", method!(RbExpr::len, 0))?;
202
- class.define_method("value_counts", method!(RbExpr::value_counts, 2))?;
208
+ class.define_method("value_counts", method!(RbExpr::value_counts, 4))?;
203
209
  class.define_method("unique_counts", method!(RbExpr::unique_counts, 0))?;
204
210
  class.define_method("null_count", method!(RbExpr::null_count, 0))?;
205
211
  class.define_method("cast", method!(RbExpr::cast, 2))?;
206
212
  class.define_method("sort_with", method!(RbExpr::sort_with, 2))?;
207
213
  class.define_method("arg_sort", method!(RbExpr::arg_sort, 2))?;
208
214
  class.define_method("top_k", method!(RbExpr::top_k, 1))?;
215
+ class.define_method("top_k_by", method!(RbExpr::top_k_by, 3))?;
209
216
  class.define_method("bottom_k", method!(RbExpr::bottom_k, 1))?;
217
+ class.define_method("bottom_k_by", method!(RbExpr::bottom_k_by, 3))?;
210
218
  class.define_method("peak_min", method!(RbExpr::peak_min, 0))?;
211
219
  class.define_method("peak_max", method!(RbExpr::peak_max, 0))?;
212
220
  class.define_method("arg_max", method!(RbExpr::arg_max, 0))?;
213
221
  class.define_method("arg_min", method!(RbExpr::arg_min, 0))?;
214
222
  class.define_method("search_sorted", method!(RbExpr::search_sorted, 2))?;
215
223
  class.define_method("gather", method!(RbExpr::gather, 1))?;
224
+ class.define_method("get", method!(RbExpr::get, 1))?;
216
225
  class.define_method("sort_by", method!(RbExpr::sort_by, 5))?;
217
226
  class.define_method("backward_fill", method!(RbExpr::backward_fill, 1))?;
218
227
  class.define_method("forward_fill", method!(RbExpr::forward_fill, 1))?;
@@ -230,6 +239,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
230
239
  class.define_method("std", method!(RbExpr::std, 1))?;
231
240
  class.define_method("var", method!(RbExpr::var, 1))?;
232
241
  class.define_method("is_unique", method!(RbExpr::is_unique, 0))?;
242
+ class.define_method("is_between", method!(RbExpr::is_between, 3))?;
233
243
  class.define_method("approx_n_unique", method!(RbExpr::approx_n_unique, 0))?;
234
244
  class.define_method("is_first_distinct", method!(RbExpr::is_first_distinct, 0))?;
235
245
  class.define_method("is_last_distinct", method!(RbExpr::is_last_distinct, 0))?;
@@ -287,7 +297,6 @@ fn init(ruby: &Ruby) -> RbResult<()> {
287
297
  class.define_method("str_strip_prefix", method!(RbExpr::str_strip_prefix, 1))?;
288
298
  class.define_method("str_strip_suffix", method!(RbExpr::str_strip_suffix, 1))?;
289
299
  class.define_method("str_slice", method!(RbExpr::str_slice, 2))?;
290
- class.define_method("str_explode", method!(RbExpr::str_explode, 0))?;
291
300
  class.define_method("str_to_uppercase", method!(RbExpr::str_to_uppercase, 0))?;
292
301
  class.define_method("str_to_lowercase", method!(RbExpr::str_to_lowercase, 0))?;
293
302
  class.define_method("str_len_bytes", method!(RbExpr::str_len_bytes, 0))?;
@@ -361,24 +370,24 @@ fn init(ruby: &Ruby) -> RbResult<()> {
361
370
  class.define_method("list_len", method!(RbExpr::list_len, 0))?;
362
371
  class.define_method("list_contains", method!(RbExpr::list_contains, 1))?;
363
372
  class.define_method("list_count_matches", method!(RbExpr::list_count_matches, 1))?;
364
- class.define_method("year", method!(RbExpr::dt_year, 0))?;
373
+ class.define_method("dt_year", method!(RbExpr::dt_year, 0))?;
365
374
  class.define_method("dt_is_leap_year", method!(RbExpr::dt_is_leap_year, 0))?;
366
- class.define_method("iso_year", method!(RbExpr::dt_iso_year, 0))?;
367
- class.define_method("quarter", method!(RbExpr::dt_quarter, 0))?;
368
- class.define_method("month", method!(RbExpr::dt_month, 0))?;
369
- class.define_method("week", method!(RbExpr::dt_week, 0))?;
370
- class.define_method("weekday", method!(RbExpr::dt_weekday, 0))?;
371
- class.define_method("day", method!(RbExpr::dt_day, 0))?;
372
- class.define_method("ordinal_day", method!(RbExpr::dt_ordinal_day, 0))?;
375
+ class.define_method("dt_iso_year", method!(RbExpr::dt_iso_year, 0))?;
376
+ class.define_method("dt_quarter", method!(RbExpr::dt_quarter, 0))?;
377
+ class.define_method("dt_month", method!(RbExpr::dt_month, 0))?;
378
+ class.define_method("dt_week", method!(RbExpr::dt_week, 0))?;
379
+ class.define_method("dt_weekday", method!(RbExpr::dt_weekday, 0))?;
380
+ class.define_method("dt_day", method!(RbExpr::dt_day, 0))?;
381
+ class.define_method("dt_ordinal_day", method!(RbExpr::dt_ordinal_day, 0))?;
373
382
  class.define_method("dt_time", method!(RbExpr::dt_time, 0))?;
374
383
  class.define_method("dt_date", method!(RbExpr::dt_date, 0))?;
375
384
  class.define_method("dt_datetime", method!(RbExpr::dt_datetime, 0))?;
376
- class.define_method("hour", method!(RbExpr::dt_hour, 0))?;
377
- class.define_method("minute", method!(RbExpr::dt_minute, 0))?;
378
- class.define_method("second", method!(RbExpr::dt_second, 0))?;
379
- class.define_method("millisecond", method!(RbExpr::dt_millisecond, 0))?;
380
- class.define_method("microsecond", method!(RbExpr::dt_microsecond, 0))?;
381
- class.define_method("nanosecond", method!(RbExpr::dt_nanosecond, 0))?;
385
+ class.define_method("dt_hour", method!(RbExpr::dt_hour, 0))?;
386
+ class.define_method("dt_minute", method!(RbExpr::dt_minute, 0))?;
387
+ class.define_method("dt_second", method!(RbExpr::dt_second, 0))?;
388
+ class.define_method("dt_millisecond", method!(RbExpr::dt_millisecond, 0))?;
389
+ class.define_method("dt_microsecond", method!(RbExpr::dt_microsecond, 0))?;
390
+ class.define_method("dt_nanosecond", method!(RbExpr::dt_nanosecond, 0))?;
382
391
  class.define_method("dt_total_days", method!(RbExpr::dt_total_days, 0))?;
383
392
  class.define_method("dt_total_hours", method!(RbExpr::dt_total_hours, 0))?;
384
393
  class.define_method("dt_total_minutes", method!(RbExpr::dt_total_minutes, 0))?;
@@ -395,7 +404,8 @@ fn init(ruby: &Ruby) -> RbResult<()> {
395
404
  "dt_total_milliseconds",
396
405
  method!(RbExpr::dt_total_milliseconds, 0),
397
406
  )?;
398
- class.define_method("timestamp", method!(RbExpr::dt_timestamp, 1))?;
407
+ class.define_method("dt_timestamp", method!(RbExpr::dt_timestamp, 1))?;
408
+ class.define_method("dt_to_string", method!(RbExpr::dt_to_string, 1))?;
399
409
  class.define_method("dt_offset_by", method!(RbExpr::dt_offset_by, 1))?;
400
410
  class.define_method("dt_epoch_seconds", method!(RbExpr::dt_epoch_seconds, 0))?;
401
411
  class.define_method("dt_with_time_unit", method!(RbExpr::dt_with_time_unit, 1))?;
@@ -408,27 +418,38 @@ fn init(ruby: &Ruby) -> RbResult<()> {
408
418
  "dt_replace_time_zone",
409
419
  method!(RbExpr::dt_replace_time_zone, 3),
410
420
  )?;
411
- class.define_method("dt_truncate", method!(RbExpr::dt_truncate, 2))?;
421
+ class.define_method("dt_truncate", method!(RbExpr::dt_truncate, 1))?;
412
422
  class.define_method("dt_month_start", method!(RbExpr::dt_month_start, 0))?;
413
423
  class.define_method("dt_month_end", method!(RbExpr::dt_month_end, 0))?;
414
424
  class.define_method("dt_base_utc_offset", method!(RbExpr::dt_base_utc_offset, 0))?;
415
425
  class.define_method("dt_dst_offset", method!(RbExpr::dt_dst_offset, 0))?;
416
- class.define_method("dt_round", method!(RbExpr::dt_round, 2))?;
426
+ class.define_method("dt_round", method!(RbExpr::dt_round, 1))?;
417
427
  class.define_method("dt_combine", method!(RbExpr::dt_combine, 2))?;
418
- class.define_method("map", method!(RbExpr::map, 3))?;
428
+ class.define_method("map_batches", method!(RbExpr::map_batches, 4))?;
419
429
  class.define_method("dot", method!(RbExpr::dot, 1))?;
420
430
  class.define_method("reinterpret", method!(RbExpr::reinterpret, 1))?;
421
431
  class.define_method("mode", method!(RbExpr::mode, 0))?;
422
432
  class.define_method("exclude", method!(RbExpr::exclude, 1))?;
423
433
  class.define_method("interpolate", method!(RbExpr::interpolate, 1))?;
424
- class.define_method("rolling_sum", method!(RbExpr::rolling_sum, 6))?;
425
- class.define_method("rolling_min", method!(RbExpr::rolling_min, 6))?;
426
- class.define_method("rolling_max", method!(RbExpr::rolling_max, 6))?;
427
- class.define_method("rolling_mean", method!(RbExpr::rolling_mean, 6))?;
428
- class.define_method("rolling_std", method!(RbExpr::rolling_std, 8))?;
429
- class.define_method("rolling_var", method!(RbExpr::rolling_var, 8))?;
430
- class.define_method("rolling_median", method!(RbExpr::rolling_median, 7))?;
431
- class.define_method("rolling_quantile", method!(RbExpr::rolling_quantile, 9))?;
434
+ class.define_method("rolling_sum", method!(RbExpr::rolling_sum, 4))?;
435
+ class.define_method("rolling_sum_by", method!(RbExpr::rolling_sum_by, 4))?;
436
+ class.define_method("rolling_min", method!(RbExpr::rolling_min, 4))?;
437
+ class.define_method("rolling_min_by", method!(RbExpr::rolling_min_by, 4))?;
438
+ class.define_method("rolling_max", method!(RbExpr::rolling_max, 4))?;
439
+ class.define_method("rolling_max_by", method!(RbExpr::rolling_max_by, 4))?;
440
+ class.define_method("rolling_mean", method!(RbExpr::rolling_mean, 4))?;
441
+ class.define_method("rolling_mean_by", method!(RbExpr::rolling_mean_by, 4))?;
442
+ class.define_method("rolling_std", method!(RbExpr::rolling_std, 5))?;
443
+ class.define_method("rolling_std_by", method!(RbExpr::rolling_std_by, 5))?;
444
+ class.define_method("rolling_var", method!(RbExpr::rolling_var, 5))?;
445
+ class.define_method("rolling_var_by", method!(RbExpr::rolling_var_by, 5))?;
446
+ class.define_method("rolling_median", method!(RbExpr::rolling_median, 4))?;
447
+ class.define_method("rolling_median_by", method!(RbExpr::rolling_median_by, 4))?;
448
+ class.define_method("rolling_quantile", method!(RbExpr::rolling_quantile, 6))?;
449
+ class.define_method(
450
+ "rolling_quantile_by",
451
+ method!(RbExpr::rolling_quantile_by, 6),
452
+ )?;
432
453
  class.define_method("rolling_skew", method!(RbExpr::rolling_skew, 2))?;
433
454
  class.define_method("lower_bound", method!(RbExpr::lower_bound, 0))?;
434
455
  class.define_method("upper_bound", method!(RbExpr::upper_bound, 0))?;
@@ -465,8 +486,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
465
486
  class.define_method("pct_change", method!(RbExpr::pct_change, 1))?;
466
487
  class.define_method("skew", method!(RbExpr::skew, 1))?;
467
488
  class.define_method("kurtosis", method!(RbExpr::kurtosis, 2))?;
468
- class.define_method("str_concat", method!(RbExpr::str_concat, 2))?;
469
- class.define_method("cat_set_ordering", method!(RbExpr::cat_set_ordering, 1))?;
489
+ class.define_method("str_join", method!(RbExpr::str_join, 2))?;
470
490
  class.define_method("cat_get_categories", method!(RbExpr::cat_get_categories, 0))?;
471
491
  class.define_method("reshape", method!(RbExpr::reshape, 1))?;
472
492
  class.define_method("cum_count", method!(RbExpr::cum_count, 1))?;
@@ -498,7 +518,8 @@ fn init(ruby: &Ruby) -> RbResult<()> {
498
518
  class.define_method("entropy", method!(RbExpr::entropy, 2))?;
499
519
  class.define_method("_hash", method!(RbExpr::hash, 4))?;
500
520
  class.define_method("set_sorted_flag", method!(RbExpr::set_sorted_flag, 1))?;
501
- class.define_method("replace", method!(RbExpr::replace, 4))?;
521
+ class.define_method("replace", method!(RbExpr::replace, 2))?;
522
+ class.define_method("replace_strict", method!(RbExpr::replace_strict, 4))?;
502
523
 
503
524
  // meta
504
525
  class.define_method("meta_pop", method!(RbExpr::meta_pop, 0))?;
@@ -531,7 +552,8 @@ fn init(ruby: &Ruby) -> RbResult<()> {
531
552
 
532
553
  // maybe add to different class
533
554
  let class = module.define_module("Plr")?;
534
- class.define_singleton_method("dtype_cols", function!(functions::lazy::dtype_cols2, 1))?;
555
+ class.define_singleton_method("dtype_cols", function!(functions::lazy::dtype_cols, 1))?;
556
+ class.define_singleton_method("index_cols", function!(functions::lazy::index_cols, 1))?;
535
557
  class.define_singleton_method("col", function!(functions::lazy::col, 1))?;
536
558
  class.define_singleton_method("len", function!(functions::lazy::len, 0))?;
537
559
  class.define_singleton_method("first", function!(functions::lazy::first, 0))?;
@@ -610,7 +632,18 @@ fn init(ruby: &Ruby) -> RbResult<()> {
610
632
  function!(functions::io::read_parquet_schema, 1),
611
633
  )?;
612
634
  class.define_singleton_method("collect_all", function!(functions::lazy::collect_all, 1))?;
613
- class.define_singleton_method("date_range", function!(functions::range::date_range, 6))?;
635
+ class.define_singleton_method("date_range", function!(functions::range::date_range, 4))?;
636
+ class.define_singleton_method("date_ranges", function!(functions::range::date_ranges, 4))?;
637
+ class.define_singleton_method(
638
+ "datetime_range",
639
+ function!(functions::range::datetime_range, 6),
640
+ )?;
641
+ class.define_singleton_method(
642
+ "datetime_ranges",
643
+ function!(functions::range::datetime_ranges, 6),
644
+ )?;
645
+ class.define_singleton_method("time_range", function!(functions::range::time_range, 4))?;
646
+ class.define_singleton_method("time_ranges", function!(functions::range::time_ranges, 4))?;
614
647
  class.define_singleton_method(
615
648
  "dtype_str_repr",
616
649
  function!(functions::misc::dtype_str_repr, 1),
@@ -689,7 +722,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
689
722
  class.define_singleton_method("new_from_csv", function!(RbLazyFrame::new_from_csv, -1))?;
690
723
  class.define_singleton_method(
691
724
  "new_from_parquet",
692
- function!(RbLazyFrame::new_from_parquet, 11),
725
+ function!(RbLazyFrame::new_from_parquet, 13),
693
726
  )?;
694
727
  class.define_singleton_method("new_from_ipc", function!(RbLazyFrame::new_from_ipc, 6))?;
695
728
  class.define_method("write_json", method!(RbLazyFrame::write_json, 1))?;
@@ -708,17 +741,17 @@ fn init(ruby: &Ruby) -> RbResult<()> {
708
741
  class.define_method("collect", method!(RbLazyFrame::collect, 0))?;
709
742
  class.define_method("sink_parquet", method!(RbLazyFrame::sink_parquet, 7))?;
710
743
  class.define_method("sink_ipc", method!(RbLazyFrame::sink_ipc, 3))?;
711
- class.define_method("sink_csv", method!(RbLazyFrame::sink_csv, 14))?;
744
+ class.define_method("sink_csv", method!(RbLazyFrame::sink_csv, 15))?;
712
745
  class.define_method("sink_json", method!(RbLazyFrame::sink_json, 2))?;
713
746
  class.define_method("fetch", method!(RbLazyFrame::fetch, 1))?;
714
747
  class.define_method("filter", method!(RbLazyFrame::filter, 1))?;
715
748
  class.define_method("select", method!(RbLazyFrame::select, 1))?;
716
749
  class.define_method("select_seq", method!(RbLazyFrame::select_seq, 1))?;
717
750
  class.define_method("group_by", method!(RbLazyFrame::group_by, 2))?;
718
- class.define_method("rolling", method!(RbLazyFrame::rolling, 6))?;
751
+ class.define_method("rolling", method!(RbLazyFrame::rolling, 5))?;
719
752
  class.define_method(
720
753
  "group_by_dynamic",
721
- method!(RbLazyFrame::group_by_dynamic, 10),
754
+ method!(RbLazyFrame::group_by_dynamic, 9),
722
755
  )?;
723
756
  class.define_method("with_context", method!(RbLazyFrame::with_context, 1))?;
724
757
  class.define_method("join_asof", method!(RbLazyFrame::join_asof, 11))?;
@@ -747,16 +780,13 @@ fn init(ruby: &Ruby) -> RbResult<()> {
747
780
  class.define_method("drop_nulls", method!(RbLazyFrame::drop_nulls, 1))?;
748
781
  class.define_method("slice", method!(RbLazyFrame::slice, 2))?;
749
782
  class.define_method("tail", method!(RbLazyFrame::tail, 1))?;
750
- class.define_method("melt", method!(RbLazyFrame::melt, 5))?;
783
+ class.define_method("unpivot", method!(RbLazyFrame::unpivot, 5))?;
751
784
  class.define_method("with_row_index", method!(RbLazyFrame::with_row_index, 2))?;
752
785
  class.define_method("drop", method!(RbLazyFrame::drop, 1))?;
753
786
  class.define_method("cast_all", method!(RbLazyFrame::cast_all, 2))?;
754
787
  class.define_method("_clone", method!(RbLazyFrame::clone, 0))?;
755
- class.define_method("columns", method!(RbLazyFrame::columns, 0))?;
756
- class.define_method("dtypes", method!(RbLazyFrame::dtypes, 0))?;
757
- class.define_method("schema", method!(RbLazyFrame::schema, 0))?;
788
+ class.define_method("collect_schema", method!(RbLazyFrame::collect_schema, 0))?;
758
789
  class.define_method("unnest", method!(RbLazyFrame::unnest, 1))?;
759
- class.define_method("width", method!(RbLazyFrame::width, 0))?;
760
790
  class.define_method("count", method!(RbLazyFrame::count, 0))?;
761
791
  class.define_method("merge_sorted", method!(RbLazyFrame::merge_sorted, 2))?;
762
792
 
@@ -778,8 +808,12 @@ fn init(ruby: &Ruby) -> RbResult<()> {
778
808
  class.define_singleton_method("new_opt_f32", function!(RbSeries::new_opt_f32, 3))?;
779
809
  class.define_singleton_method("new_opt_f64", function!(RbSeries::new_opt_f64, 3))?;
780
810
  class.define_singleton_method(
781
- "new_from_anyvalues",
782
- function!(RbSeries::new_from_anyvalues, 3),
811
+ "new_from_any_values",
812
+ function!(RbSeries::new_from_any_values, 3),
813
+ )?;
814
+ class.define_singleton_method(
815
+ "new_from_any_values_and_dtype",
816
+ function!(RbSeries::new_from_any_values_and_dtype, 4),
783
817
  )?;
784
818
  class.define_singleton_method("new_str", function!(RbSeries::new_str, 3))?;
785
819
  class.define_singleton_method("new_binary", function!(RbSeries::new_binary, 3))?;
@@ -836,7 +870,8 @@ fn init(ruby: &Ruby) -> RbResult<()> {
836
870
  class.define_method("div", method!(RbSeries::div, 1))?;
837
871
  class.define_method("rem", method!(RbSeries::rem, 1))?;
838
872
  class.define_method("sort", method!(RbSeries::sort, 3))?;
839
- class.define_method("value_counts", method!(RbSeries::value_counts, 1))?;
873
+ class.define_method("value_counts", method!(RbSeries::value_counts, 4))?;
874
+ class.define_method("slice", method!(RbSeries::slice, 2))?;
840
875
  class.define_method("any", method!(RbSeries::any, 1))?;
841
876
  class.define_method("all", method!(RbSeries::all, 1))?;
842
877
  class.define_method("arg_min", method!(RbSeries::arg_min, 0))?;
@@ -846,7 +881,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
846
881
  class.define_method("has_validity", method!(RbSeries::has_validity, 0))?;
847
882
  class.define_method("sample_n", method!(RbSeries::sample_n, 4))?;
848
883
  class.define_method("sample_frac", method!(RbSeries::sample_frac, 4))?;
849
- class.define_method("equals", method!(RbSeries::equals, 3))?;
884
+ class.define_method("equals", method!(RbSeries::equals, 4))?;
850
885
  class.define_method("eq", method!(RbSeries::eq, 1))?;
851
886
  class.define_method("neq", method!(RbSeries::neq, 1))?;
852
887
  class.define_method("gt", method!(RbSeries::gt, 1))?;
@@ -255,8 +255,8 @@ pub fn apply_lambda_with_rows_output<'a>(
255
255
  match RArray::try_convert(val).ok() {
256
256
  Some(tuple) => {
257
257
  row_buf.0.clear();
258
- for v in tuple.each() {
259
- let v = Wrap::<AnyValue>::try_convert(v.unwrap()).unwrap().0;
258
+ for v in tuple.into_iter() {
259
+ let v = Wrap::<AnyValue>::try_convert(v).unwrap().0;
260
260
  row_buf.0.push(v);
261
261
  }
262
262
  let ptr = &row_buf as *const Row;
@@ -8,31 +8,11 @@ pub fn binary_lambda(_lambda: Value, _a: Series, _b: Series) -> PolarsResult<Opt
8
8
  }
9
9
 
10
10
  pub fn map_single(
11
- rbexpr: &RbExpr,
11
+ _rbexpr: &RbExpr,
12
12
  _lambda: Value,
13
- output_type: Option<Wrap<DataType>>,
14
- agg_list: bool,
13
+ _output_type: Option<Wrap<DataType>>,
14
+ _agg_list: bool,
15
+ _is_elementwise: bool,
15
16
  ) -> RbExpr {
16
- let output_type = output_type.map(|wrap| wrap.0);
17
-
18
- let output_type2 = output_type.clone();
19
- let function = move |_s: Series| {
20
- let _output_type = output_type2.clone().unwrap_or(DataType::Unknown);
21
-
22
- todo!();
23
- };
24
-
25
- let output_map = GetOutput::map_field(move |fld| match output_type {
26
- Some(ref dt) => Field::new(fld.name(), dt.clone()),
27
- None => {
28
- let mut fld = fld.clone();
29
- fld.coerce(DataType::Unknown);
30
- fld
31
- }
32
- });
33
- if agg_list {
34
- rbexpr.clone().inner.map_list(function, output_map).into()
35
- } else {
36
- rbexpr.clone().inner.map(function, output_map).into()
37
- }
17
+ todo!();
38
18
  }
@@ -33,7 +33,12 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
33
33
  .apply_lambda_with_utf8_out_type(lambda, null_count, Some(first_value.as_str()))
34
34
  .map(|ca| ca.into_series().into())
35
35
  } else if out.respond_to("_s", true)? {
36
- todo!()
36
+ let rb_rbseries: &RbSeries = out.funcall("_s", ()).unwrap();
37
+ let series = rb_rbseries.series.borrow();
38
+ let dt = series.dtype();
39
+ applyer
40
+ .apply_lambda_with_list_out_type(lambda, null_count, &series, dt)
41
+ .map(|ca| ca.into_series().into())
37
42
  } else if out.is_kind_of(class::array()) {
38
43
  todo!()
39
44
  } else if out.is_kind_of(class::hash()) {
@@ -66,6 +71,7 @@ pub trait ApplyLambda<'a> {
66
71
  fn apply_lambda_unknown(&'a self, _lambda: Value) -> RbResult<RbSeries>;
67
72
 
68
73
  /// Apply a lambda that doesn't change output types
74
+ #[allow(dead_code)]
69
75
  fn apply_lambda(&'a self, _lambda: Value) -> RbResult<RbSeries>;
70
76
 
71
77
  // Used to store a struct type
@@ -1,4 +1,4 @@
1
- use magnus::{value::Lazy, Module, RClass, RModule, Ruby};
1
+ use magnus::{value::Lazy, ExceptionClass, Module, RClass, RModule, Ruby};
2
2
 
3
3
  static POLARS: Lazy<RModule> = Lazy::new(|ruby| ruby.class_object().const_get("Polars").unwrap());
4
4
 
@@ -38,3 +38,27 @@ static DATETIME: Lazy<RClass> =
38
38
  pub(crate) fn datetime() -> RClass {
39
39
  Ruby::get().unwrap().get_inner(&DATETIME)
40
40
  }
41
+
42
+ static ERROR: Lazy<ExceptionClass> =
43
+ Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Error").unwrap());
44
+
45
+ pub(crate) fn error() -> ExceptionClass {
46
+ Ruby::get().unwrap().get_inner(&ERROR)
47
+ }
48
+
49
+ static COMPUTE_ERROR: Lazy<ExceptionClass> =
50
+ Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("ComputeError").unwrap());
51
+
52
+ pub(crate) fn compute_error() -> ExceptionClass {
53
+ Ruby::get().unwrap().get_inner(&COMPUTE_ERROR)
54
+ }
55
+
56
+ static INVALID_OPERATION_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
57
+ ruby.get_inner(&POLARS)
58
+ .const_get("InvalidOperationError")
59
+ .unwrap()
60
+ });
61
+
62
+ pub(crate) fn invalid_operation_error() -> ExceptionClass {
63
+ Ruby::get().unwrap().get_inner(&INVALID_OPERATION_ERROR)
64
+ }
@@ -1,6 +1,6 @@
1
1
  use crate::error::RbPolarsErr;
2
2
  use crate::prelude::*;
3
- use crate::{RbResult, RbSeries, RbValueError};
3
+ use crate::{RbResult, RbSeries};
4
4
  use magnus::{IntoValue, Value};
5
5
 
6
6
  impl RbSeries {
@@ -36,31 +36,54 @@ impl RbSeries {
36
36
  Ok(Wrap(
37
37
  self.series
38
38
  .borrow()
39
- .max_as_series()
39
+ .max_reduce()
40
40
  .map_err(RbPolarsErr::from)?
41
- .get(0)
42
- .map_err(RbPolarsErr::from)?,
41
+ .as_any_value(),
43
42
  )
44
43
  .into_value())
45
44
  }
46
45
 
47
- pub fn mean(&self) -> Option<f64> {
46
+ pub fn mean(&self) -> RbResult<Value> {
48
47
  match self.series.borrow().dtype() {
49
- DataType::Boolean => {
50
- let s = self.series.borrow().cast(&DataType::UInt8).unwrap();
51
- s.mean()
48
+ DataType::Boolean => Ok(Wrap(
49
+ self.series
50
+ .borrow()
51
+ .cast(&DataType::UInt8)
52
+ .unwrap()
53
+ .mean_reduce()
54
+ .as_any_value(),
55
+ )
56
+ .into_value()),
57
+ // For non-numeric output types we require mean_reduce.
58
+ dt if dt.is_temporal() => {
59
+ Ok(Wrap(self.series.borrow().mean_reduce().as_any_value()).into_value())
52
60
  }
53
- _ => self.series.borrow().mean(),
61
+ _ => Ok(self.series.borrow().mean().into_value()),
54
62
  }
55
63
  }
56
64
 
57
- pub fn median(&self) -> Option<f64> {
65
+ pub fn median(&self) -> RbResult<Value> {
58
66
  match self.series.borrow().dtype() {
59
- DataType::Boolean => {
60
- let s = self.series.borrow().cast(&DataType::UInt8).unwrap();
61
- s.median()
62
- }
63
- _ => self.series.borrow().median(),
67
+ DataType::Boolean => Ok(Wrap(
68
+ self.series
69
+ .borrow()
70
+ .cast(&DataType::UInt8)
71
+ .unwrap()
72
+ .median_reduce()
73
+ .map_err(RbPolarsErr::from)?
74
+ .as_any_value(),
75
+ )
76
+ .into_value()),
77
+ // For non-numeric output types we require median_reduce.
78
+ dt if dt.is_temporal() => Ok(Wrap(
79
+ self.series
80
+ .borrow()
81
+ .median_reduce()
82
+ .map_err(RbPolarsErr::from)?
83
+ .as_any_value(),
84
+ )
85
+ .into_value()),
86
+ _ => Ok(self.series.borrow().median().into_value()),
64
87
  }
65
88
  }
66
89
 
@@ -68,10 +91,9 @@ impl RbSeries {
68
91
  Ok(Wrap(
69
92
  self.series
70
93
  .borrow()
71
- .min_as_series()
94
+ .min_reduce()
72
95
  .map_err(RbPolarsErr::from)?
73
- .get(0)
74
- .map_err(RbPolarsErr::from)?,
96
+ .as_any_value(),
75
97
  )
76
98
  .into_value())
77
99
  }
@@ -81,25 +103,22 @@ impl RbSeries {
81
103
  quantile: f64,
82
104
  interpolation: Wrap<QuantileInterpolOptions>,
83
105
  ) -> RbResult<Value> {
84
- Ok(Wrap(
85
- self.series
86
- .borrow()
87
- .quantile_as_series(quantile, interpolation.0)
88
- .map_err(|_| RbValueError::new_err("invalid quantile".into()))?
89
- .get(0)
90
- .unwrap_or(AnyValue::Null),
91
- )
92
- .into_value())
106
+ let bind = self
107
+ .series
108
+ .borrow()
109
+ .quantile_reduce(quantile, interpolation.0);
110
+ let sc = bind.map_err(RbPolarsErr::from)?;
111
+
112
+ Ok(Wrap(sc.as_any_value()).into_value())
93
113
  }
94
114
 
95
115
  pub fn sum(&self) -> RbResult<Value> {
96
116
  Ok(Wrap(
97
117
  self.series
98
118
  .borrow()
99
- .sum_as_series()
119
+ .sum_reduce()
100
120
  .map_err(RbPolarsErr::from)?
101
- .get(0)
102
- .map_err(RbPolarsErr::from)?,
121
+ .as_any_value(),
103
122
  )
104
123
  .into_value())
105
124
  }
@@ -1,24 +1,34 @@
1
- use crate::{RbResult, RbSeries};
1
+ use crate::{RbPolarsErr, RbResult, RbSeries};
2
2
 
3
3
  impl RbSeries {
4
- pub fn add(&self, other: &RbSeries) -> Self {
5
- (&*self.series.borrow() + &*other.series.borrow()).into()
4
+ pub fn add(&self, other: &RbSeries) -> RbResult<Self> {
5
+ (&*self.series.borrow() + &*other.series.borrow())
6
+ .map(Into::into)
7
+ .map_err(RbPolarsErr::from)
6
8
  }
7
9
 
8
- pub fn sub(&self, other: &RbSeries) -> Self {
9
- (&*self.series.borrow() - &*other.series.borrow()).into()
10
+ pub fn sub(&self, other: &RbSeries) -> RbResult<Self> {
11
+ (&*self.series.borrow() - &*other.series.borrow())
12
+ .map(Into::into)
13
+ .map_err(RbPolarsErr::from)
10
14
  }
11
15
 
12
- pub fn mul(&self, other: &RbSeries) -> Self {
13
- (&*self.series.borrow() * &*other.series.borrow()).into()
16
+ pub fn mul(&self, other: &RbSeries) -> RbResult<Self> {
17
+ (&*self.series.borrow() * &*other.series.borrow())
18
+ .map(Into::into)
19
+ .map_err(RbPolarsErr::from)
14
20
  }
15
21
 
16
- pub fn div(&self, other: &RbSeries) -> Self {
17
- (&*self.series.borrow() / &*other.series.borrow()).into()
22
+ pub fn div(&self, other: &RbSeries) -> RbResult<Self> {
23
+ (&*self.series.borrow() / &*other.series.borrow())
24
+ .map(Into::into)
25
+ .map_err(RbPolarsErr::from)
18
26
  }
19
27
 
20
- pub fn rem(&self, other: &RbSeries) -> Self {
21
- (&*self.series.borrow() % &*other.series.borrow()).into()
28
+ pub fn rem(&self, other: &RbSeries) -> RbResult<Self> {
29
+ (&*self.series.borrow() % &*other.series.borrow())
30
+ .map(Into::into)
31
+ .map_err(RbPolarsErr::from)
22
32
  }
23
33
  }
24
34