polars-df 0.21.0-arm64-darwin → 0.22.0-arm64-darwin

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Cargo.lock +55 -48
  4. data/Cargo.toml +3 -0
  5. data/LICENSE-THIRD-PARTY.txt +23 -49
  6. data/README.md +12 -0
  7. data/lib/polars/3.2/polars.bundle +0 -0
  8. data/lib/polars/3.3/polars.bundle +0 -0
  9. data/lib/polars/3.4/polars.bundle +0 -0
  10. data/lib/polars/array_expr.rb +382 -3
  11. data/lib/polars/array_name_space.rb +281 -0
  12. data/lib/polars/binary_expr.rb +67 -0
  13. data/lib/polars/binary_name_space.rb +43 -0
  14. data/lib/polars/cat_expr.rb +224 -0
  15. data/lib/polars/cat_name_space.rb +138 -0
  16. data/lib/polars/config.rb +2 -2
  17. data/lib/polars/convert.rb +6 -6
  18. data/lib/polars/data_frame.rb +794 -27
  19. data/lib/polars/data_type_expr.rb +52 -0
  20. data/lib/polars/data_types.rb +26 -5
  21. data/lib/polars/date_time_expr.rb +252 -1
  22. data/lib/polars/date_time_name_space.rb +299 -0
  23. data/lib/polars/expr.rb +1248 -206
  24. data/lib/polars/functions/business.rb +95 -0
  25. data/lib/polars/functions/datatype.rb +21 -0
  26. data/lib/polars/functions/lazy.rb +14 -1
  27. data/lib/polars/io/csv.rb +1 -1
  28. data/lib/polars/io/iceberg.rb +27 -0
  29. data/lib/polars/io/json.rb +4 -4
  30. data/lib/polars/io/ndjson.rb +4 -4
  31. data/lib/polars/io/parquet.rb +32 -7
  32. data/lib/polars/io/scan_options.rb +4 -1
  33. data/lib/polars/lazy_frame.rb +1028 -28
  34. data/lib/polars/list_expr.rb +217 -17
  35. data/lib/polars/list_name_space.rb +231 -22
  36. data/lib/polars/meta_expr.rb +89 -0
  37. data/lib/polars/name_expr.rb +36 -0
  38. data/lib/polars/query_opt_flags.rb +50 -0
  39. data/lib/polars/scan_cast_options.rb +20 -1
  40. data/lib/polars/schema.rb +79 -3
  41. data/lib/polars/selector.rb +72 -0
  42. data/lib/polars/selectors.rb +3 -3
  43. data/lib/polars/series.rb +1053 -54
  44. data/lib/polars/string_expr.rb +436 -32
  45. data/lib/polars/string_name_space.rb +736 -50
  46. data/lib/polars/struct_expr.rb +103 -0
  47. data/lib/polars/struct_name_space.rb +19 -1
  48. data/lib/polars/utils/serde.rb +17 -0
  49. data/lib/polars/utils/various.rb +22 -1
  50. data/lib/polars/utils.rb +5 -1
  51. data/lib/polars/version.rb +1 -1
  52. data/lib/polars.rb +6 -0
  53. metadata +8 -2
@@ -80,10 +80,10 @@ module Polars
80
80
  # # │ 2 │
81
81
  # # │ 1 │
82
82
  # # └─────┘
83
- def lengths
83
+ def len
84
84
  Utils.wrap_expr(_rbexpr.list_len)
85
85
  end
86
- alias_method :len, :lengths
86
+ alias_method :lengths, :len
87
87
 
88
88
  # Drop all null values in the list.
89
89
  #
@@ -243,6 +243,79 @@ module Polars
243
243
  Utils.wrap_expr(_rbexpr.list_mean)
244
244
  end
245
245
 
246
+ # Compute the median value of the lists in the array.
247
+ #
248
+ # @return [Expr]
249
+ #
250
+ # @example
251
+ # df = Polars::DataFrame.new({"values" => [[-1, 0, 1], [1, 10]]})
252
+ # df.with_columns(Polars.col("values").list.median.alias("median"))
253
+ # # =>
254
+ # # shape: (2, 2)
255
+ # # ┌────────────┬────────┐
256
+ # # │ values ┆ median │
257
+ # # │ --- ┆ --- │
258
+ # # │ list[i64] ┆ f64 │
259
+ # # ╞════════════╪════════╡
260
+ # # │ [-1, 0, 1] ┆ 0.0 │
261
+ # # │ [1, 10] ┆ 5.5 │
262
+ # # └────────────┴────────┘
263
+ def median
264
+ Utils.wrap_expr(_rbexpr.list_median)
265
+ end
266
+
267
+ # Compute the std value of the lists in the array.
268
+ #
269
+ # @param ddof [Integer]
270
+ # “Delta Degrees of Freedom”: the divisor used in the calculation is N - ddof,
271
+ # where N represents the number of elements.
272
+ # By default ddof is 1.
273
+ #
274
+ # @return [Expr]
275
+ #
276
+ # @example
277
+ # df = Polars::DataFrame.new({"values" => [[-1, 0, 1], [1, 10]]})
278
+ # df.with_columns(Polars.col("values").list.std.alias("std"))
279
+ # # =>
280
+ # # shape: (2, 2)
281
+ # # ┌────────────┬──────────┐
282
+ # # │ values ┆ std │
283
+ # # │ --- ┆ --- │
284
+ # # │ list[i64] ┆ f64 │
285
+ # # ╞════════════╪══════════╡
286
+ # # │ [-1, 0, 1] ┆ 1.0 │
287
+ # # │ [1, 10] ┆ 6.363961 │
288
+ # # └────────────┴──────────┘
289
+ def std(ddof: 1)
290
+ Utils.wrap_expr(_rbexpr.list_std(ddof))
291
+ end
292
+
293
+ # Compute the var value of the lists in the array.
294
+ #
295
+ # @param ddof [Integer]
296
+ # “Delta Degrees of Freedom”: the divisor used in the calculation is N - ddof,
297
+ # where N represents the number of elements.
298
+ # By default ddof is 1.
299
+ #
300
+ # @return [Expr]
301
+ #
302
+ # @example
303
+ # df = Polars::DataFrame.new({"values" => [[-1, 0, 1], [1, 10]]})
304
+ # df.with_columns(Polars.col("values").list.var.alias("var"))
305
+ # # =>
306
+ # # shape: (2, 2)
307
+ # # ┌────────────┬──────┐
308
+ # # │ values ┆ var │
309
+ # # │ --- ┆ --- │
310
+ # # │ list[i64] ┆ f64 │
311
+ # # ╞════════════╪══════╡
312
+ # # │ [-1, 0, 1] ┆ 1.0 │
313
+ # # │ [1, 10] ┆ 40.5 │
314
+ # # └────────────┴──────┘
315
+ def var(ddof: 1)
316
+ Utils.wrap_expr(_rbexpr.list_var(ddof))
317
+ end
318
+
246
319
  # Sort the arrays in the list.
247
320
  #
248
321
  # @param reverse [Boolean]
@@ -322,6 +395,31 @@ module Polars
322
395
  Utils.wrap_expr(_rbexpr.list_unique(maintain_order))
323
396
  end
324
397
 
398
+ # Count the number of unique values in every sub-lists.
399
+ #
400
+ # @return [Expr]
401
+ #
402
+ # @example
403
+ # df = Polars::DataFrame.new(
404
+ # {
405
+ # "a" => [[1, 1, 2], [2, 3, 4]]
406
+ # }
407
+ # )
408
+ # df.with_columns(n_unique: Polars.col("a").list.n_unique)
409
+ # # =>
410
+ # # shape: (2, 2)
411
+ # # ┌───────────┬──────────┐
412
+ # # │ a ┆ n_unique │
413
+ # # │ --- ┆ --- │
414
+ # # │ list[i64] ┆ u32 │
415
+ # # ╞═══════════╪══════════╡
416
+ # # │ [1, 1, 2] ┆ 2 │
417
+ # # │ [2, 3, 4] ┆ 3 │
418
+ # # └───────────┴──────────┘
419
+ def n_unique
420
+ Utils.wrap_expr(_rbexpr.list_n_unique)
421
+ end
422
+
325
423
  # Concat the arrays in a Series dtype List in linear time.
326
424
  #
327
425
  # @param other [Object]
@@ -366,7 +464,7 @@ module Polars
366
464
  #
367
465
  # So index `0` would return the first item of every sublist
368
466
  # and index `-1` would return the last item of every sublist
369
- # if an index is out of bounds, it will return a `None`.
467
+ # if an index is out of bounds, it will return a `nil`.
370
468
  #
371
469
  # @param index [Integer]
372
470
  # Index to return per sublist
@@ -438,6 +536,48 @@ module Polars
438
536
  end
439
537
  alias_method :take, :gather
440
538
 
539
+ # Take every n-th value start from offset in sublists.
540
+ #
541
+ # @param n [Integer]
542
+ # Gather every n-th element.
543
+ # @param offset [Integer]
544
+ # Starting index.
545
+ #
546
+ # @return [Expr]
547
+ #
548
+ # @example
549
+ # df = Polars::DataFrame.new(
550
+ # {
551
+ # "a" => [[1, 2, 3, 4, 5], [6, 7, 8], [9, 10, 11, 12]],
552
+ # "n" => [2, 1, 3],
553
+ # "offset" => [0, 1, 0]
554
+ # }
555
+ # )
556
+ # df.with_columns(
557
+ # gather_every: Polars.col("a").list.gather_every(
558
+ # Polars.col("n"), Polars.col("offset")
559
+ # )
560
+ # )
561
+ # # =>
562
+ # # shape: (3, 4)
563
+ # # ┌───────────────┬─────┬────────┬──────────────┐
564
+ # # │ a ┆ n ┆ offset ┆ gather_every │
565
+ # # │ --- ┆ --- ┆ --- ┆ --- │
566
+ # # │ list[i64] ┆ i64 ┆ i64 ┆ list[i64] │
567
+ # # ╞═══════════════╪═════╪════════╪══════════════╡
568
+ # # │ [1, 2, … 5] ┆ 2 ┆ 0 ┆ [1, 3, 5] │
569
+ # # │ [6, 7, 8] ┆ 1 ┆ 1 ┆ [7, 8] │
570
+ # # │ [9, 10, … 12] ┆ 3 ┆ 0 ┆ [9, 12] │
571
+ # # └───────────────┴─────┴────────┴──────────────┘
572
+ def gather_every(
573
+ n,
574
+ offset = 0
575
+ )
576
+ n = Utils.parse_into_expression(n)
577
+ offset = Utils.parse_into_expression(offset)
578
+ Utils.wrap_expr(_rbexpr.list_gather_every(n, offset))
579
+ end
580
+
441
581
  # Get the first value of the sublists.
442
582
  #
443
583
  # @return [Expr]
@@ -702,7 +842,32 @@ module Polars
702
842
  Utils.wrap_expr(_rbexpr.list_tail(n))
703
843
  end
704
844
 
705
- # Count how often the value produced by ``element`` occurs.
845
+ # Returns a column with a separate row for every list element.
846
+ #
847
+ # @return [Expr]
848
+ #
849
+ # @example
850
+ # df = Polars::DataFrame.new({"a" => [[1, 2, 3], [4, 5, 6]]})
851
+ # df.select(Polars.col("a").list.explode)
852
+ # # =>
853
+ # # shape: (6, 1)
854
+ # # ┌─────┐
855
+ # # │ a │
856
+ # # │ --- │
857
+ # # │ i64 │
858
+ # # ╞═════╡
859
+ # # │ 1 │
860
+ # # │ 2 │
861
+ # # │ 3 │
862
+ # # │ 4 │
863
+ # # │ 5 │
864
+ # # │ 6 │
865
+ # # └─────┘
866
+ def explode
867
+ Utils.wrap_expr(_rbexpr.explode)
868
+ end
869
+
870
+ # Count how often the value produced by `element` occurs.
706
871
  #
707
872
  # @param element [Expr]
708
873
  # An expression that produces a single value
@@ -730,10 +895,37 @@ module Polars
730
895
  end
731
896
  alias_method :count_match, :count_matches
732
897
 
898
+ # Convert a List column into an Array column with the same inner data type.
899
+ #
900
+ # @param width [Integer]
901
+ # Width of the resulting Array column.
902
+ #
903
+ # @return [Expr]
904
+ #
905
+ # @example
906
+ # df = Polars::DataFrame.new(
907
+ # {"a" => [[1, 2], [3, 4]]},
908
+ # schema: {"a" => Polars::List.new(Polars::Int8)}
909
+ # )
910
+ # df.with_columns(array: Polars.col("a").list.to_array(2))
911
+ # # =>
912
+ # # shape: (2, 2)
913
+ # # ┌──────────┬──────────────┐
914
+ # # │ a ┆ array │
915
+ # # │ --- ┆ --- │
916
+ # # │ list[i8] ┆ array[i8, 2] │
917
+ # # ╞══════════╪══════════════╡
918
+ # # │ [1, 2] ┆ [1, 2] │
919
+ # # │ [3, 4] ┆ [3, 4] │
920
+ # # └──────────┴──────────────┘
921
+ def to_array(width)
922
+ Utils.wrap_expr(_rbexpr.list_to_array(width))
923
+ end
924
+
733
925
  # Convert the series of type `List` to a series of type `Struct`.
734
926
  #
735
927
  # @param n_field_strategy ["first_non_null", "max_width"]
736
- # Strategy to determine the number of fields of the struct.
928
+ # Deprecated and ignored.
737
929
  # @param fields pArray
738
930
  # If the name and number of the desired fields is known in advance
739
931
  # a list of field names can be given, which will be assigned by index.
@@ -753,20 +945,28 @@ module Polars
753
945
  # @return [Expr]
754
946
  #
755
947
  # @example
756
- # df = Polars::DataFrame.new({"a" => [[1, 2, 3], [1, 2]]})
757
- # df.select([Polars.col("a").list.to_struct])
948
+ # df = Polars::DataFrame.new({"n" => [[0, 1], [0, 1, 2]]})
949
+ # df.with_columns(struct: Polars.col("n").list.to_struct(upper_bound: 2))
758
950
  # # =>
759
- # # shape: (2, 1)
760
- # # ┌────────────┐
761
- # # │ a
762
- # # │ ---
763
- # # │ struct[3]
764
- # # ╞════════════╡
765
- # # │ {1,2,3}
766
- # # │ {1,2,null}
767
- # # └────────────┘
951
+ # # shape: (2, 2)
952
+ # # ┌───────────┬───────────┐
953
+ # # │ n ┆ struct
954
+ # # │ --- ┆ ---
955
+ # # │ list[i64] ┆ struct[2]
956
+ # # ╞═══════════╪═══════════╡
957
+ # # │ [0, 1] ┆ {0,1}
958
+ # # │ [0, 1, 2] ┆ {0,1}
959
+ # # └───────────┴───────────┘
768
960
  def to_struct(n_field_strategy: "first_non_null", fields: nil, upper_bound: nil)
769
- Utils.wrap_expr(_rbexpr.list_to_struct(n_field_strategy, fields, nil))
961
+ if !fields.is_a?(::Array)
962
+ if fields.nil?
963
+ fields = upper_bound.times.map { |i| "field_#{i}" }
964
+ else
965
+ fields = upper_bound.times.map { |i| fields.(i) }
966
+ end
967
+ end
968
+
969
+ Utils.wrap_expr(_rbexpr.list_to_struct(fields))
770
970
  end
771
971
 
772
972
  # Run any polars expression against the lists' elements.
@@ -66,7 +66,7 @@ module Polars
66
66
  #
67
67
  # @example
68
68
  # s = Polars::Series.new([[1, 2, 3], [5]])
69
- # s.list.lengths
69
+ # s.list.len
70
70
  # # =>
71
71
  # # shape: (2,)
72
72
  # # Series: '' [u32]
@@ -74,9 +74,10 @@ module Polars
74
74
  # # 3
75
75
  # # 1
76
76
  # # ]
77
- def lengths
77
+ def len
78
78
  super
79
79
  end
80
+ alias_method :lengths, :len
80
81
 
81
82
  # Drop all null values in the list.
82
83
  #
@@ -202,6 +203,60 @@ module Polars
202
203
  super
203
204
  end
204
205
 
206
+ # Compute the median value of the arrays in the list.
207
+ #
208
+ # @return [Series]
209
+ #
210
+ # @example
211
+ # s = Polars::Series.new("values", [[-1, 0, 1], [1, 10]])
212
+ # s.list.median
213
+ # # =>
214
+ # # shape: (2,)
215
+ # # Series: 'values' [f64]
216
+ # # [
217
+ # # 0.0
218
+ # # 5.5
219
+ # # ]
220
+ def median
221
+ super
222
+ end
223
+
224
+ # Compute the std value of the arrays in the list.
225
+ #
226
+ # @return [Series]
227
+ #
228
+ # @example
229
+ # s = Polars::Series.new("values", [[-1, 0, 1], [1, 10]])
230
+ # s.list.std
231
+ # # =>
232
+ # # shape: (2,)
233
+ # # Series: 'values' [f64]
234
+ # # [
235
+ # # 1.0
236
+ # # 6.363961
237
+ # # ]
238
+ def std(ddof: 1)
239
+ super
240
+ end
241
+
242
+ # Compute the var value of the arrays in the list.
243
+ #
244
+ # @return [Series]
245
+ #
246
+ # @example
247
+ # s = Polars::Series.new("values", [[-1, 0, 1], [1, 10]])
248
+ # s.list.var
249
+ # # =>
250
+ # # shape: (2,)
251
+ # # Series: 'values' [f64]
252
+ # # [
253
+ # # 1.0
254
+ # # 40.5
255
+ # # ]
256
+ def var(ddof: 1)
257
+ super
258
+ end
259
+
205
260
  # Sort the arrays in the list.
206
261
  #
207
262
  # @return [Series]
@@ -254,7 +309,7 @@ module Polars
254
309
  #
255
310
  # @example
256
311
  # s = Polars::Series.new("a", [[1, 1, 2], [2, 3, 3]])
257
- # s.list.unique()
312
+ # s.list.unique
258
313
  # # =>
259
314
  # # shape: (2,)
260
315
  # # Series: 'a' [list[i64]]
@@ -266,6 +321,24 @@ module Polars
266
321
  super
267
322
  end
268
323
 
324
+ # Count the number of unique values in every sub-lists.
325
+ #
326
+ # @return [Series]
327
+ #
328
+ # @example
329
+ # s = Polars::Series.new("a", [[1, 1, 2], [2, 3, 4]])
330
+ # s.list.n_unique
331
+ # # =>
332
+ # # shape: (2,)
333
+ # # Series: 'a' [u32]
334
+ # # [
335
+ # # 2
336
+ # # 3
337
+ # # ]
338
+ def n_unique
339
+ super
340
+ end
341
+
269
342
  # Concat the arrays in a Series dtype List in linear time.
270
343
  #
271
344
  # @param other [Object]
@@ -292,7 +365,7 @@ module Polars
292
365
  #
293
366
  # So index `0` would return the first item of every sublist
294
367
  # and index `-1` would return the last item of every sublist
295
- # if an index is out of bounds, it will return a `None`.
368
+ # if an index is out of bounds, it will return a `nil`.
296
369
  #
297
370
  # @param index [Integer]
298
371
  # Index to return per sublist
@@ -318,6 +391,63 @@ module Polars
318
391
  super
319
392
  end
320
393
 
394
+ # Take sublists by multiple indices.
395
+ #
396
+ # The indices may be defined in a single column, or by sublists in another
397
+ # column of dtype `List`.
398
+ #
399
+ # @param indices [Object]
400
+ # Indices to return per sublist
401
+ # @param null_on_oob [Boolean]
402
+ # Behavior if an index is out of bounds:
403
+ # True -> set as null
404
+ # False -> raise an error
405
+ # Note that defaulting to raising an error is much cheaper
406
+ #
407
+ # @return [Series]
408
+ #
409
+ # @example
410
+ # s = Polars::Series.new("a", [[3, 2, 1], [], [1, 2]])
411
+ # s.list.gather([0, 2], null_on_oob: true)
412
+ # # =>
413
+ # # shape: (3,)
414
+ # # Series: 'a' [list[i64]]
415
+ # # [
416
+ # # [3, 1]
417
+ # # [null, null]
418
+ # # [1, null]
419
+ # # ]
420
+ def gather(
421
+ indices,
422
+ null_on_oob: false
423
+ )
424
+ super
425
+ end
426
+
427
+ # Take every n-th value start from offset in sublists.
428
+ #
429
+ # @param n [Integer]
430
+ # Gather every n-th element.
431
+ # @param offset [Integer]
432
+ # Starting index.
433
+ #
434
+ # @return [Series]
435
+ #
436
+ # @example
437
+ # s = Polars::Series.new("a", [[1, 2, 3], [], [6, 7, 8, 9]])
438
+ # s.list.gather_every(2, 1)
439
+ # # =>
440
+ # # shape: (3,)
441
+ # # Series: 'a' [list[i64]]
442
+ # # [
443
+ # # [2]
444
+ # # []
445
+ # # [7, 9]
446
+ # # ]
447
+ def gather_every(n, offset = 0)
448
+ super
449
+ end
450
+
321
451
  # Get the value by index in the sublists.
322
452
  #
323
453
  # @return [Series]
@@ -554,33 +684,112 @@ module Polars
554
684
  super
555
685
  end
556
686
 
557
- # Convert the series of type `List` to a series of type `Struct`.
687
+ # Returns a column with a separate row for every list element.
558
688
  #
559
- # @param n_field_strategy ["first_non_null", "max_width"]
560
- # 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`
689
+ # @return [Series]
690
+ #
691
+ # @example
692
+ # s = Polars::Series.new("a", [[1, 2, 3], [4, 5, 6]])
693
+ # s.list.explode
694
+ # # =>
695
+ # # shape: (6,)
696
+ # # Series: 'a' [i64]
697
+ # # [
698
+ # # 1
699
+ # # 2
700
+ # # 3
701
+ # # 4
702
+ # # 5
703
+ # # 6
704
+ # # ]
705
+ def explode
706
+ super
707
+ end
708
+
709
+ # Count how often the value produced by `element` occurs.
710
+ #
711
+ # @param element [Object]
712
+ # An expression that produces a single value
564
713
  #
565
714
  # @return [Series]
566
715
  #
567
716
  # @example
568
- # df = Polars::DataFrame.new({"a" => [[1, 2, 3], [1, 2]]})
569
- # df.select([Polars.col("a").list.to_struct])
717
+ # s = Polars::Series.new("a", [[0], [1], [1, 2, 3, 2], [1, 2, 1], [4, 4]])
718
+ # s.list.count_matches(1)
570
719
  # # =>
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)
720
+ # # shape: (5,)
721
+ # # Series: 'a' [u32]
722
+ # # [
723
+ # # 0
724
+ # # 1
725
+ # # 1
726
+ # # 2
727
+ # # 0
728
+ # # ]
729
+ def count_matches(element)
581
730
  super
582
731
  end
583
732
 
733
+ # Convert a List column into an Array column with the same inner data type.
734
+ #
735
+ # @param width [Integer]
736
+ # Width of the resulting Array column.
737
+ #
738
+ # @return [Series]
739
+ #
740
+ # @example
741
+ # s = Polars::Series.new([[1, 2], [3, 4]], dtype: Polars::List.new(Polars::Int8))
742
+ # s.list.to_array(2)
743
+ # # =>
744
+ # # shape: (2,)
745
+ # # Series: '' [array[i8, 2]]
746
+ # # [
747
+ # # [1, 2]
748
+ # # [3, 4]
749
+ # # ]
750
+ def to_array(width)
751
+ super
752
+ end
753
+
754
+ # Convert the series of type `List` to a series of type `Struct`.
755
+ #
756
+ # @param n_field_strategy ["first_non_null", "max_width"]
757
+ # Strategy to determine the number of fields of the struct.
758
+ # @param fields [Object]
759
+ # If the name and number of the desired fields is known in advance
760
+ # a list of field names can be given, which will be assigned by index.
761
+ # Otherwise, to dynamically assign field names, a custom function can be
762
+ # used; if neither are set, fields will be `field_0, field_1 .. field_n`.
763
+ #
764
+ # @return [Series]
765
+ #
766
+ # @example Convert list to struct with field name assignment by index from a list of names:
767
+ # s1 = Polars::Series.new("n", [[0, 1, 2], [0, 1]])
768
+ # s1.list.to_struct(fields: ["one", "two", "three"]).struct.unnest
769
+ # # =>
770
+ # # shape: (2, 3)
771
+ # # ┌─────┬─────┬───────┐
772
+ # # │ one ┆ two ┆ three │
773
+ # # │ --- ┆ --- ┆ --- │
774
+ # # │ i64 ┆ i64 ┆ i64 │
775
+ # # ╞═════╪═════╪═══════╡
776
+ # # │ 0 ┆ 1 ┆ 2 │
777
+ # # │ 0 ┆ 1 ┆ null │
778
+ # # └─────┴─────┴───────┘
779
+ def to_struct(n_field_strategy: "first_non_null", fields: nil)
780
+ if fields.is_a?(::Array)
781
+ s = Utils.wrap_s(_s)
782
+ return (
783
+ s.to_frame
784
+ .select_seq(F.col(s.name).list.to_struct(fields: fields))
785
+ .to_series
786
+ )
787
+ end
788
+
789
+ raise Todo
790
+ # Utils.wrap_s(_s.list_to_struct(n_field_strategy, fields))
791
+ end
792
+
584
793
  # Run any polars expression against the lists' elements.
585
794
  #
586
795
  # @param expr [Expr]