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
@@ -12,6 +12,13 @@ module Polars
12
12
 
13
13
  # Evaluate whether all boolean values in a list are true.
14
14
  #
15
+ # @param ignore_nulls [Boolean]
16
+ # * If set to `true` (default), null values are ignored. If there
17
+ # are no non-null values, the output is `true`.
18
+ # * If set to `false`, [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic) is used to deal with nulls:
19
+ # if the column contains any null values and no `false` values,
20
+ # the output is null.
21
+ #
15
22
  # @return [Series]
16
23
  #
17
24
  # @example
@@ -31,12 +38,19 @@ module Polars
31
38
  # # true
32
39
  # # null
33
40
  # # ]
34
- def all
41
+ def all(ignore_nulls: true)
35
42
  super
36
43
  end
37
44
 
38
45
  # Evaluate whether any boolean value in a list is true.
39
46
  #
47
+ # @param ignore_nulls [Boolean]
48
+ # * If set to `true` (default), null values are ignored. If there
49
+ # are no non-null values, the output is `false`.
50
+ # * If set to `false`, [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic) is used to deal with nulls:
51
+ # if the column contains any null values and no `true` values,
52
+ # the output is null.
53
+ #
40
54
  # @return [Series]
41
55
  #
42
56
  # @example
@@ -56,7 +70,7 @@ module Polars
56
70
  # # false
57
71
  # # null
58
72
  # # ]
59
- def any
73
+ def any(ignore_nulls: true)
60
74
  super
61
75
  end
62
76
 
@@ -66,7 +80,7 @@ module Polars
66
80
  #
67
81
  # @example
68
82
  # s = Polars::Series.new([[1, 2, 3], [5]])
69
- # s.list.lengths
83
+ # s.list.len
70
84
  # # =>
71
85
  # # shape: (2,)
72
86
  # # Series: '' [u32]
@@ -74,7 +88,7 @@ module Polars
74
88
  # # 3
75
89
  # # 1
76
90
  # # ]
77
- def lengths
91
+ def len
78
92
  super
79
93
  end
80
94
 
@@ -123,7 +137,7 @@ module Polars
123
137
  # # shape: (2,)
124
138
  # # Series: 'values' [list[i64]]
125
139
  # # [
126
- # # [2, 1]
140
+ # # [2, 3]
127
141
  # # [5]
128
142
  # # ]
129
143
  def sample(n: nil, fraction: nil, with_replacement: false, shuffle: false, seed: nil)
@@ -202,8 +216,67 @@ module Polars
202
216
  super
203
217
  end
204
218
 
219
+ # Compute the median value of the arrays in the list.
220
+ #
221
+ # @return [Series]
222
+ #
223
+ # @example
224
+ # s = Polars::Series.new("values", [[-1, 0, 1], [1, 10]])
225
+ # s.list.median
226
+ # # =>
227
+ # # shape: (2,)
228
+ # # Series: 'values' [f64]
229
+ # # [
230
+ # # 0.0
231
+ # # 5.5
232
+ # # ]
233
+ def median
234
+ super
235
+ end
236
+
237
+ # Compute the std value of the arrays in the list.
238
+ #
239
+ # @return [Series]
240
+ #
241
+ # @example
242
+ # s = Polars::Series.new("values", [[-1, 0, 1], [1, 10]])
243
+ # s.list.std
244
+ # # =>
245
+ # # shape: (2,)
246
+ # # Series: 'values' [f64]
247
+ # # [
248
+ # # 1.0
249
+ # # 6.363961
250
+ # # ]
251
+ def std(ddof: 1)
252
+ super
253
+ end
254
+
255
+ # Compute the var value of the arrays in the list.
256
+ #
257
+ # @return [Series]
258
+ #
259
+ # @example
260
+ # s = Polars::Series.new("values", [[-1, 0, 1], [1, 10]])
261
+ # s.list.var
262
+ # # =>
263
+ # # shape: (2,)
264
+ # # Series: 'values' [f64]
265
+ # # [
266
+ # # 1.0
267
+ # # 40.5
268
+ # # ]
269
+ def var(ddof: 1)
270
+ super
271
+ end
272
+
205
273
  # Sort the arrays in the list.
206
274
  #
275
+ # @param descending [Boolean]
276
+ # Sort in descending order.
277
+ # @param nulls_last [Boolean]
278
+ # Place null values last.
279
+ #
207
280
  # @return [Series]
208
281
  #
209
282
  # @example
@@ -218,7 +291,7 @@ module Polars
218
291
  # # ]
219
292
  #
220
293
  # @example
221
- # s.list.sort(reverse: true)
294
+ # s.list.sort(descending: true)
222
295
  # # =>
223
296
  # # shape: (2,)
224
297
  # # Series: 'a' [list[i64]]
@@ -226,7 +299,7 @@ module Polars
226
299
  # # [3, 2, 1]
227
300
  # # [9, 2, 1]
228
301
  # # ]
229
- def sort(reverse: false)
302
+ def sort(descending: false, nulls_last: false)
230
303
  super
231
304
  end
232
305
 
@@ -250,11 +323,14 @@ module Polars
250
323
 
251
324
  # Get the unique/distinct values in the list.
252
325
  #
326
+ # @param maintain_order [Boolean]
327
+ # Maintain order of data. This requires more work.
328
+ #
253
329
  # @return [Series]
254
330
  #
255
331
  # @example
256
332
  # s = Polars::Series.new("a", [[1, 1, 2], [2, 3, 3]])
257
- # s.list.unique()
333
+ # s.list.unique
258
334
  # # =>
259
335
  # # shape: (2,)
260
336
  # # Series: 'a' [list[i64]]
@@ -262,7 +338,25 @@ module Polars
262
338
  # # [1, 2]
263
339
  # # [2, 3]
264
340
  # # ]
265
- def unique
341
+ def unique(maintain_order: false)
342
+ super
343
+ end
344
+
345
+ # Count the number of unique values in every sub-lists.
346
+ #
347
+ # @return [Series]
348
+ #
349
+ # @example
350
+ # s = Polars::Series.new("a", [[1, 1, 2], [2, 3, 4]])
351
+ # s.list.n_unique
352
+ # # =>
353
+ # # shape: (2,)
354
+ # # Series: 'a' [u32]
355
+ # # [
356
+ # # 2
357
+ # # 3
358
+ # # ]
359
+ def n_unique
266
360
  super
267
361
  end
268
362
 
@@ -292,7 +386,7 @@ module Polars
292
386
  #
293
387
  # So index `0` would return the first item of every sublist
294
388
  # and index `-1` would return the last item of every sublist
295
- # if an index is out of bounds, it will return a `None`.
389
+ # if an index is out of bounds, it will return a `nil`.
296
390
  #
297
391
  # @param index [Integer]
298
392
  # Index to return per sublist
@@ -318,6 +412,63 @@ module Polars
318
412
  super
319
413
  end
320
414
 
415
+ # Take sublists by multiple indices.
416
+ #
417
+ # The indices may be defined in a single column, or by sublists in another
418
+ # column of dtype `List`.
419
+ #
420
+ # @param indices [Object]
421
+ # Indices to return per sublist
422
+ # @param null_on_oob [Boolean]
423
+ # Behavior if an index is out of bounds:
424
+ # true -> set as null
425
+ # false -> raise an error
426
+ # Note that defaulting to raising an error is much cheaper
427
+ #
428
+ # @return [Series]
429
+ #
430
+ # @example
431
+ # s = Polars::Series.new("a", [[3, 2, 1], [], [1, 2]])
432
+ # s.list.gather([0, 2], null_on_oob: true)
433
+ # # =>
434
+ # # shape: (3,)
435
+ # # Series: 'a' [list[i64]]
436
+ # # [
437
+ # # [3, 1]
438
+ # # [null, null]
439
+ # # [1, null]
440
+ # # ]
441
+ def gather(
442
+ indices,
443
+ null_on_oob: false
444
+ )
445
+ super
446
+ end
447
+
448
+ # Take every n-th value start from offset in sublists.
449
+ #
450
+ # @param n [Integer]
451
+ # Gather every n-th element.
452
+ # @param offset [Integer]
453
+ # Starting index.
454
+ #
455
+ # @return [Series]
456
+ #
457
+ # @example
458
+ # s = Polars::Series.new("a", [[1, 2, 3], [], [6, 7, 8, 9]])
459
+ # s.list.gather_every(2, 1)
460
+ # # =>
461
+ # # shape: (3,)
462
+ # # Series: 'a' [list[i64]]
463
+ # # [
464
+ # # [2]
465
+ # # []
466
+ # # [7, 9]
467
+ # # ]
468
+ def gather_every(n, offset = 0)
469
+ super
470
+ end
471
+
321
472
  # Get the value by index in the sublists.
322
473
  #
323
474
  # @return [Series]
@@ -331,6 +482,11 @@ module Polars
331
482
  #
332
483
  # @param separator [String]
333
484
  # string to separate the items with
485
+ # @param ignore_nulls [Boolean]
486
+ # Ignore null values (default).
487
+ #
488
+ # If set to `false`, null values will be propagated.
489
+ # If the sub-list contains any null values, the output is `nil`.
334
490
  #
335
491
  # @return [Series]
336
492
  #
@@ -344,7 +500,7 @@ module Polars
344
500
  # # "foo-bar"
345
501
  # # "hello-world"
346
502
  # # ]
347
- def join(separator)
503
+ def join(separator, ignore_nulls: true)
348
504
  super
349
505
  end
350
506
 
@@ -386,10 +542,33 @@ module Polars
386
542
  super
387
543
  end
388
544
 
545
+ # Get the single value of the sublists.
546
+ #
547
+ # This errors if the sublist length is not exactly one.
548
+ #
549
+ # @return [Series]
550
+ #
551
+ # @example
552
+ # s = Polars::Series.new("a", [[1], [4], [6]])
553
+ # s.list.item
554
+ # # =>
555
+ # # shape: (3,)
556
+ # # Series: 'a' [i64]
557
+ # # [
558
+ # # 1
559
+ # # 4
560
+ # # 6
561
+ # # ]
562
+ def item
563
+ super
564
+ end
565
+
389
566
  # Check if sublists contain the given item.
390
567
  #
391
568
  # @param item [Object]
392
569
  # Item that will be checked for membership.
570
+ # @param nulls_equal [Boolean]
571
+ # If true, treat null as a distinct value. Null values will not propagate.
393
572
  #
394
573
  # @return [Series]
395
574
  #
@@ -404,7 +583,7 @@ module Polars
404
583
  # # false
405
584
  # # true
406
585
  # # ]
407
- def contains(item)
586
+ def contains(item, nulls_equal: true)
408
587
  super
409
588
  end
410
589
 
@@ -469,7 +648,7 @@ module Polars
469
648
 
470
649
  # Shift values by the given period.
471
650
  #
472
- # @param periods [Integer]
651
+ # @param n [Integer]
473
652
  # Number of places to shift (may be negative).
474
653
  #
475
654
  # @return [Series]
@@ -484,7 +663,7 @@ module Polars
484
663
  # # [null, 1, … 3]
485
664
  # # [null, 10, 2]
486
665
  # # ]
487
- def shift(periods = 1)
666
+ def shift(n = 1)
488
667
  super
489
668
  end
490
669
 
@@ -554,31 +733,124 @@ module Polars
554
733
  super
555
734
  end
556
735
 
736
+ # Returns a column with a separate row for every list element.
737
+ #
738
+ # @param empty_as_null [Boolean]
739
+ # Explode an empty list into a `null`.
740
+ # @param keep_nulls [Boolean]
741
+ # Explode a `null` list into a `null`.
742
+ #
743
+ # @return [Series]
744
+ #
745
+ # @example
746
+ # s = Polars::Series.new("a", [[1, 2, 3], [4, 5, 6]])
747
+ # s.list.explode
748
+ # # =>
749
+ # # shape: (6,)
750
+ # # Series: 'a' [i64]
751
+ # # [
752
+ # # 1
753
+ # # 2
754
+ # # 3
755
+ # # 4
756
+ # # 5
757
+ # # 6
758
+ # # ]
759
+ def explode(empty_as_null: true, keep_nulls: true)
760
+ super
761
+ end
762
+
763
+ # Count how often the value produced by `element` occurs.
764
+ #
765
+ # @param element [Object]
766
+ # An expression that produces a single value
767
+ #
768
+ # @return [Series]
769
+ #
770
+ # @example
771
+ # s = Polars::Series.new("a", [[0], [1], [1, 2, 3, 2], [1, 2, 1], [4, 4]])
772
+ # s.list.count_matches(1)
773
+ # # =>
774
+ # # shape: (5,)
775
+ # # Series: 'a' [u32]
776
+ # # [
777
+ # # 0
778
+ # # 1
779
+ # # 1
780
+ # # 2
781
+ # # 0
782
+ # # ]
783
+ def count_matches(element)
784
+ super
785
+ end
786
+
787
+ # Convert a List column into an Array column with the same inner data type.
788
+ #
789
+ # @param width [Integer]
790
+ # Width of the resulting Array column.
791
+ #
792
+ # @return [Series]
793
+ #
794
+ # @example
795
+ # s = Polars::Series.new([[1, 2], [3, 4]], dtype: Polars::List.new(Polars::Int8))
796
+ # s.list.to_array(2)
797
+ # # =>
798
+ # # shape: (2,)
799
+ # # Series: '' [array[i8, 2]]
800
+ # # [
801
+ # # [1, 2]
802
+ # # [3, 4]
803
+ # # ]
804
+ def to_array(width)
805
+ super
806
+ end
807
+
557
808
  # Convert the series of type `List` to a series of type `Struct`.
558
809
  #
559
810
  # @param n_field_strategy ["first_non_null", "max_width"]
560
811
  # Strategy to determine the number of fields of the struct.
561
- # @param name_generator [Object]
562
- # A custom function that can be used to generate the field names.
563
- # Default field names are `field_0, field_1 .. field_n`
812
+ # @param fields [Object]
813
+ # If the name and number of the desired fields is known in advance
814
+ # a list of field names can be given, which will be assigned by index.
815
+ # Otherwise, to dynamically assign field names, a custom function can be
816
+ # used; if neither are set, fields will be `field_0, field_1 .. field_n`.
564
817
  #
565
818
  # @return [Series]
566
819
  #
567
- # @example
568
- # df = Polars::DataFrame.new({"a" => [[1, 2, 3], [1, 2]]})
569
- # df.select([Polars.col("a").list.to_struct])
820
+ # @example Convert list to struct with field name assignment by index from a list of names:
821
+ # s1 = Polars::Series.new("n", [[0, 1, 2], [0, 1]])
822
+ # s2 = s1.list.to_struct
823
+ # s2.struct.fields
824
+ # # => ["field_0", "field_1", "field_2"]
825
+ #
826
+ # @example Convert list to struct with field name assignment by function/index:
827
+ # s3 = s1.list.to_struct(fields: ->(idx) { "n%02d" % idx })
828
+ # s3.struct.fields
829
+ # # => ["n00", "n01", "n02"]
830
+ #
831
+ # @example Convert list to struct with field name assignment by index from a list of names:
832
+ # s1.list.to_struct(fields: ["one", "two", "three"]).struct.unnest
570
833
  # # =>
571
- # # shape: (2, 1)
572
- # # ┌────────────┐
573
- # # │ a
574
- # # │ ---
575
- # # │ struct[3]
576
- # # ╞════════════╡
577
- # # │ {1,2,3}
578
- # # │ {1,2,null}
579
- # # └────────────┘
580
- def to_struct(n_field_strategy: "first_non_null", name_generator: nil)
581
- super
834
+ # # shape: (2, 3)
835
+ # # ┌─────┬─────┬───────┐
836
+ # # │ one ┆ two ┆ three
837
+ # # │ --- ┆ --- ┆ ---
838
+ # # │ i64 ┆ i64 ┆ i64
839
+ # # ╞═════╪═════╪═══════╡
840
+ # # │ 0 ┆ 12
841
+ # # │ 0 ┆ 1null
842
+ # # └─────┴─────┴───────┘
843
+ def to_struct(n_field_strategy: "first_non_null", fields: nil)
844
+ if fields.is_a?(::Array)
845
+ s = Utils.wrap_s(_s)
846
+ return (
847
+ s.to_frame
848
+ .select_seq(F.col(s.name).list.to_struct(fields: fields))
849
+ .to_series
850
+ )
851
+ end
852
+
853
+ Utils.wrap_s(_s.list_to_struct(n_field_strategy, fields))
582
854
  end
583
855
 
584
856
  # Run any polars expression against the lists' elements.
@@ -586,32 +858,174 @@ module Polars
586
858
  # @param expr [Expr]
587
859
  # Expression to run. Note that you can select an element with `Polars.first`, or
588
860
  # `Polars.col`
589
- # @param parallel [Boolean]
590
- # Run all expression parallel. Don't activate this blindly.
591
- # Parallelism is worth it if there is enough work to do per thread.
592
861
  #
593
- # This likely should not be use in the group by context, because we already
594
- # parallel execution per group
862
+ # @return [Series]
863
+ #
864
+ # @example
865
+ # s = Polars::Series.new("a", [[1, 4], [8, 5], [3, 2]])
866
+ # s.list.eval(Polars.element.rank)
867
+ # # =>
868
+ # # shape: (3,)
869
+ # # Series: 'a' [list[f64]]
870
+ # # [
871
+ # # [1.0, 2.0]
872
+ # # [2.0, 1.0]
873
+ # # [2.0, 1.0]
874
+ # # ]
875
+ def eval(expr)
876
+ s = Utils.wrap_s(_s)
877
+ s.to_frame.select(F.col(s.name).list.eval(expr)).to_series
878
+ end
879
+
880
+ # Run any polars aggregation expression against the list' elements.
881
+ #
882
+ # @param expr [Expr]
883
+ # Expression to run. Note that you can select an element with `Polars.element`.
595
884
  #
596
885
  # @return [Series]
597
886
  #
598
887
  # @example
599
- # df = Polars::DataFrame.new({"a" => [1, 8, 3], "b" => [4, 5, 2]})
600
- # df.with_column(
601
- # Polars.concat_list(["a", "b"]).list.eval(Polars.element.rank).alias("rank")
602
- # )
888
+ # s = Polars::Series.new("a", [[1, nil], [42, 13], [nil, nil]])
889
+ # s.list.agg(Polars.element.null_count)
890
+ # # =>
891
+ # # shape: (3,)
892
+ # # Series: 'a' [u32]
893
+ # # [
894
+ # # 1
895
+ # # 0
896
+ # # 2
897
+ # # ]
898
+ #
899
+ # @example
900
+ # s.list.agg(Polars.element.drop_nulls)
603
901
  # # =>
604
- # # shape: (3, 3)
605
- # # ┌─────┬─────┬────────────┐
606
- # # │ a ┆ b ┆ rank │
607
- # # │ --- ┆ --- ┆ --- │
608
- # # │ i64 ┆ i64 ┆ list[f64]
609
- # # ╞═════╪═════╪════════════╡
610
- # # │ 1 ┆ 4 ┆ [1.0, 2.0]
611
- # # │ 8 ┆ 5 ┆ [2.0, 1.0] │
612
- # # │ 3 ┆ 2 ┆ [2.0, 1.0] │
613
- # # └─────┴─────┴────────────┘
614
- def eval(expr, parallel: false)
902
+ # # shape: (3,)
903
+ # # Series: 'a' [list[i64]]
904
+ # # [
905
+ # # [1]
906
+ # # [42, 13]
907
+ # # []
908
+ # # ]
909
+ def agg(expr)
910
+ super
911
+ end
912
+
913
+ # Filter elements in each list by a boolean expression, returning a new Series of lists.
914
+ #
915
+ # @param predicate [Object]
916
+ # A boolean expression evaluated on each list element.
917
+ # Use `Polars.element` to refer to the current element.
918
+ #
919
+ # @return [Series]
920
+ #
921
+ # @example
922
+ # s = Polars::Series.new("a", [[1, 4], [8, 5], [3, 2]])
923
+ # s.list.filter(Polars.element % 2 == 0)
924
+ # # =>
925
+ # # shape: (3,)
926
+ # # Series: 'a' [list[i64]]
927
+ # # [
928
+ # # [4]
929
+ # # [8]
930
+ # # [2]
931
+ # # ]
932
+ def filter(predicate)
933
+ super
934
+ end
935
+
936
+ # Compute the SET UNION between the elements in this list and the elements of `other`.
937
+ #
938
+ # @param other [Object]
939
+ # Right hand side of the set operation.
940
+ #
941
+ # @return [Series]
942
+ #
943
+ # @example
944
+ # a = Polars::Series.new([[1, 2, 3], [], [nil, 3], [5, 6, 7]])
945
+ # b = Polars::Series.new([[2, 3, 4], [3], [3, 4, nil], [6, 8]])
946
+ # a.list.set_union(b)
947
+ # # =>
948
+ # # shape: (4,)
949
+ # # Series: '' [list[i64]]
950
+ # # [
951
+ # # [1, 2, … 4]
952
+ # # [3]
953
+ # # [null, 3, 4]
954
+ # # [5, 6, … 8]
955
+ # # ]
956
+ def set_union(other)
957
+ super
958
+ end
959
+
960
+ # Compute the SET DIFFERENCE between the elements in this list and the elements of `other`.
961
+ #
962
+ # @param other [Object]
963
+ # Right hand side of the set operation.
964
+ #
965
+ # @return [Series]
966
+ #
967
+ # @example
968
+ # a = Polars::Series.new([[1, 2, 3], [], [nil, 3], [5, 6, 7]])
969
+ # b = Polars::Series.new([[2, 3, 4], [3], [3, 4, nil], [6, 8]])
970
+ # a.list.set_difference(b)
971
+ # # =>
972
+ # # shape: (4,)
973
+ # # Series: '' [list[i64]]
974
+ # # [
975
+ # # [1]
976
+ # # []
977
+ # # []
978
+ # # [5, 7]
979
+ # # ]
980
+ def set_difference(other)
981
+ super
982
+ end
983
+
984
+ # Compute the SET INTERSECTION between the elements in this list and the elements of `other`.
985
+ #
986
+ # @param other [Object]
987
+ # Right hand side of the set operation.
988
+ #
989
+ # @return [Series]
990
+ #
991
+ # @example
992
+ # a = Polars::Series.new([[1, 2, 3], [], [nil, 3], [5, 6, 7]])
993
+ # b = Polars::Series.new([[2, 3, 4], [3], [3, 4, nil], [6, 8]])
994
+ # a.list.set_intersection(b)
995
+ # # =>
996
+ # # shape: (4,)
997
+ # # Series: '' [list[i64]]
998
+ # # [
999
+ # # [2, 3]
1000
+ # # []
1001
+ # # [null, 3]
1002
+ # # [6]
1003
+ # # ]
1004
+ def set_intersection(other)
1005
+ super
1006
+ end
1007
+
1008
+ # Compute the SET SYMMETRIC DIFFERENCE between the elements in this list and the elements of `other`.
1009
+ #
1010
+ # @param other [Object]
1011
+ # Right hand side of the set operation.
1012
+ #
1013
+ # @return [Series]
1014
+ #
1015
+ # @example
1016
+ # a = Polars::Series.new([[1, 2, 3], [], [nil, 3], [5, 6, 7]])
1017
+ # b = Polars::Series.new([[2, 3, 4], [3], [3, 4, nil], [6, 8]])
1018
+ # a.list.set_symmetric_difference(b)
1019
+ # # =>
1020
+ # # shape: (4,)
1021
+ # # Series: '' [list[i64]]
1022
+ # # [
1023
+ # # [1, 4]
1024
+ # # [3]
1025
+ # # [4]
1026
+ # # [5, 7, 8]
1027
+ # # ]
1028
+ def set_symmetric_difference(other)
615
1029
  super
616
1030
  end
617
1031
  end