polars-df 0.7.0-x86_64-darwin → 0.9.0-x86_64-darwin

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/Cargo.lock +353 -237
  4. data/Cargo.toml +0 -3
  5. data/LICENSE-THIRD-PARTY.txt +4014 -3495
  6. data/LICENSE.txt +1 -1
  7. data/README.md +2 -2
  8. data/lib/polars/3.1/polars.bundle +0 -0
  9. data/lib/polars/3.2/polars.bundle +0 -0
  10. data/lib/polars/{3.0 → 3.3}/polars.bundle +0 -0
  11. data/lib/polars/array_expr.rb +449 -0
  12. data/lib/polars/array_name_space.rb +346 -0
  13. data/lib/polars/cat_expr.rb +24 -0
  14. data/lib/polars/cat_name_space.rb +75 -0
  15. data/lib/polars/config.rb +2 -2
  16. data/lib/polars/data_frame.rb +248 -108
  17. data/lib/polars/data_types.rb +195 -29
  18. data/lib/polars/date_time_expr.rb +41 -24
  19. data/lib/polars/date_time_name_space.rb +12 -12
  20. data/lib/polars/exceptions.rb +12 -1
  21. data/lib/polars/expr.rb +1080 -195
  22. data/lib/polars/functions/aggregation/horizontal.rb +246 -0
  23. data/lib/polars/functions/aggregation/vertical.rb +282 -0
  24. data/lib/polars/functions/as_datatype.rb +248 -0
  25. data/lib/polars/functions/col.rb +47 -0
  26. data/lib/polars/functions/eager.rb +182 -0
  27. data/lib/polars/functions/lazy.rb +1280 -0
  28. data/lib/polars/functions/len.rb +49 -0
  29. data/lib/polars/functions/lit.rb +35 -0
  30. data/lib/polars/functions/random.rb +16 -0
  31. data/lib/polars/functions/range/date_range.rb +103 -0
  32. data/lib/polars/functions/range/int_range.rb +51 -0
  33. data/lib/polars/functions/repeat.rb +144 -0
  34. data/lib/polars/functions/whenthen.rb +27 -0
  35. data/lib/polars/functions.rb +29 -416
  36. data/lib/polars/group_by.rb +3 -3
  37. data/lib/polars/io.rb +21 -28
  38. data/lib/polars/lazy_frame.rb +390 -76
  39. data/lib/polars/list_expr.rb +152 -6
  40. data/lib/polars/list_name_space.rb +102 -0
  41. data/lib/polars/meta_expr.rb +175 -7
  42. data/lib/polars/series.rb +557 -59
  43. data/lib/polars/sql_context.rb +1 -1
  44. data/lib/polars/string_cache.rb +75 -0
  45. data/lib/polars/string_expr.rb +412 -96
  46. data/lib/polars/string_name_space.rb +4 -4
  47. data/lib/polars/struct_expr.rb +1 -1
  48. data/lib/polars/struct_name_space.rb +1 -1
  49. data/lib/polars/testing.rb +507 -0
  50. data/lib/polars/utils.rb +64 -20
  51. data/lib/polars/version.rb +1 -1
  52. data/lib/polars.rb +15 -2
  53. metadata +36 -7
  54. data/lib/polars/lazy_functions.rb +0 -1197
data/lib/polars/expr.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  module Polars
2
2
  # Expressions that can be used in various contexts.
3
3
  class Expr
4
+ # @private
5
+ NO_DEFAULT = Object.new
6
+
4
7
  # @private
5
8
  attr_accessor :_rbexpr
6
9
 
@@ -23,112 +26,106 @@ module Polars
23
26
  #
24
27
  # @return [Expr]
25
28
  def ^(other)
26
- wrap_expr(_rbexpr._xor(_to_rbexpr(other)))
29
+ _from_rbexpr(_rbexpr._xor(_to_rbexpr(other)))
27
30
  end
28
31
 
29
32
  # Bitwise AND.
30
33
  #
31
34
  # @return [Expr]
32
35
  def &(other)
33
- wrap_expr(_rbexpr._and(_to_rbexpr(other)))
36
+ _from_rbexpr(_rbexpr._and(_to_rbexpr(other)))
34
37
  end
35
38
 
36
39
  # Bitwise OR.
37
40
  #
38
41
  # @return [Expr]
39
42
  def |(other)
40
- wrap_expr(_rbexpr._or(_to_rbexpr(other)))
43
+ _from_rbexpr(_rbexpr._or(_to_rbexpr(other)))
41
44
  end
42
45
 
43
46
  # Performs addition.
44
47
  #
45
48
  # @return [Expr]
46
49
  def +(other)
47
- wrap_expr(_rbexpr + _to_rbexpr(other))
50
+ _from_rbexpr(_rbexpr + _to_rbexpr(other))
48
51
  end
49
52
 
50
53
  # Performs subtraction.
51
54
  #
52
55
  # @return [Expr]
53
56
  def -(other)
54
- wrap_expr(_rbexpr - _to_rbexpr(other))
57
+ _from_rbexpr(_rbexpr - _to_rbexpr(other))
55
58
  end
56
59
 
57
60
  # Performs multiplication.
58
61
  #
59
62
  # @return [Expr]
60
63
  def *(other)
61
- wrap_expr(_rbexpr * _to_rbexpr(other))
64
+ _from_rbexpr(_rbexpr * _to_rbexpr(other))
62
65
  end
63
66
 
64
67
  # Performs division.
65
68
  #
66
69
  # @return [Expr]
67
70
  def /(other)
68
- wrap_expr(_rbexpr / _to_rbexpr(other))
69
- end
70
-
71
- # Performs floor division.
72
- #
73
- # @return [Expr]
74
- def floordiv(other)
75
- wrap_expr(_rbexpr.floordiv(_to_rbexpr(other)))
71
+ _from_rbexpr(_rbexpr / _to_rbexpr(other))
76
72
  end
77
73
 
78
74
  # Returns the modulo.
79
75
  #
80
76
  # @return [Expr]
81
77
  def %(other)
82
- wrap_expr(_rbexpr % _to_rbexpr(other))
78
+ _from_rbexpr(_rbexpr % _to_rbexpr(other))
83
79
  end
84
80
 
85
81
  # Raises to the power of exponent.
86
82
  #
87
83
  # @return [Expr]
88
84
  def **(power)
89
- pow(power)
85
+ exponent = Utils.expr_to_lit_or_expr(power)
86
+ _from_rbexpr(_rbexpr.pow(exponent._rbexpr))
90
87
  end
91
88
 
92
89
  # Greater than or equal.
93
90
  #
94
91
  # @return [Expr]
95
92
  def >=(other)
96
- wrap_expr(_rbexpr.gt_eq(_to_expr(other)._rbexpr))
93
+ _from_rbexpr(_rbexpr.gt_eq(_to_expr(other)._rbexpr))
97
94
  end
98
95
 
99
96
  # Less than or equal.
100
97
  #
101
98
  # @return [Expr]
102
99
  def <=(other)
103
- wrap_expr(_rbexpr.lt_eq(_to_expr(other)._rbexpr))
100
+ _from_rbexpr(_rbexpr.lt_eq(_to_expr(other)._rbexpr))
104
101
  end
105
102
 
106
103
  # Equal.
107
104
  #
108
105
  # @return [Expr]
109
106
  def ==(other)
110
- wrap_expr(_rbexpr.eq(_to_expr(other)._rbexpr))
107
+ _from_rbexpr(_rbexpr.eq(_to_expr(other)._rbexpr))
111
108
  end
112
109
 
113
110
  # Not equal.
114
111
  #
115
112
  # @return [Expr]
116
113
  def !=(other)
117
- wrap_expr(_rbexpr.neq(_to_expr(other)._rbexpr))
114
+ _from_rbexpr(_rbexpr.neq(_to_expr(other)._rbexpr))
118
115
  end
119
116
 
120
117
  # Less than.
121
118
  #
122
119
  # @return [Expr]
123
120
  def <(other)
124
- wrap_expr(_rbexpr.lt(_to_expr(other)._rbexpr))
121
+ _from_rbexpr(_rbexpr.lt(_to_expr(other)._rbexpr))
125
122
  end
126
123
 
127
124
  # Greater than.
128
125
  #
129
126
  # @return [Expr]
130
127
  def >(other)
131
- wrap_expr(_rbexpr.gt(_to_expr(other)._rbexpr))
128
+ _from_rbexpr(_rbexpr.gt(_to_expr(other)._rbexpr))
132
129
  end
133
130
 
134
131
  # Performs boolean not.
@@ -142,7 +139,7 @@ module Polars
142
139
  #
143
140
  # @return [Expr]
144
141
  def -@
145
- Utils.lit(0) - self
142
+ _from_rbexpr(_rbexpr.neg)
146
143
  end
147
144
 
148
145
  # Cast to physical representation of the logical dtype.
@@ -179,7 +176,7 @@ module Polars
179
176
  # # │ a ┆ 0 │
180
177
  # # └──────┴───────────────┘
181
178
  def to_physical
182
- wrap_expr(_rbexpr.to_physical)
179
+ _from_rbexpr(_rbexpr.to_physical)
183
180
  end
184
181
 
185
182
  # Check if any boolean value in a Boolean column is `true`.
@@ -199,7 +196,7 @@ module Polars
199
196
  # # │ true ┆ false │
200
197
  # # └──────┴───────┘
201
198
  def any(drop_nulls: true)
202
- wrap_expr(_rbexpr.any(drop_nulls))
199
+ _from_rbexpr(_rbexpr.any(drop_nulls))
203
200
  end
204
201
 
205
202
  # Check if all boolean values in a Boolean column are `true`.
@@ -224,7 +221,7 @@ module Polars
224
221
  # # │ true ┆ false ┆ false │
225
222
  # # └──────┴───────┴───────┘
226
223
  def all(drop_nulls: true)
227
- wrap_expr(_rbexpr.all(drop_nulls))
224
+ _from_rbexpr(_rbexpr.all(drop_nulls))
228
225
  end
229
226
 
230
227
  # Compute the square root of the elements.
@@ -290,7 +287,7 @@ module Polars
290
287
  # # │ 54.59815 │
291
288
  # # └──────────┘
292
289
  def exp
293
- wrap_expr(_rbexpr.exp)
290
+ _from_rbexpr(_rbexpr.exp)
294
291
  end
295
292
 
296
293
  # Rename the output of an expression.
@@ -325,7 +322,7 @@ module Polars
325
322
  # # │ 3 ┆ null │
326
323
  # # └─────┴──────┘
327
324
  def alias(name)
328
- wrap_expr(_rbexpr._alias(name))
325
+ _from_rbexpr(_rbexpr._alias(name))
329
326
  end
330
327
 
331
328
  # TODO support symbols for exclude
@@ -366,22 +363,22 @@ module Polars
366
363
  # # │ 3 ┆ 1.5 │
367
364
  # # └─────┴──────┘
368
365
  def exclude(columns)
369
- if columns.is_a?(String)
366
+ if columns.is_a?(::String)
370
367
  columns = [columns]
371
- return wrap_expr(_rbexpr.exclude(columns))
368
+ return _from_rbexpr(_rbexpr.exclude(columns))
372
369
  elsif !columns.is_a?(::Array)
373
370
  columns = [columns]
374
- return wrap_expr(_rbexpr.exclude_dtype(columns))
371
+ return _from_rbexpr(_rbexpr.exclude_dtype(columns))
375
372
  end
376
373
 
377
- if !columns.all? { |a| a.is_a?(String) } || !columns.all? { |a| Utils.is_polars_dtype(a) }
374
+ if !columns.all? { |a| a.is_a?(::String) } || !columns.all? { |a| Utils.is_polars_dtype(a) }
378
375
  raise ArgumentError, "input should be all string or all DataType"
379
376
  end
380
377
 
381
- if columns[0].is_a?(String)
382
- wrap_expr(_rbexpr.exclude(columns))
378
+ if columns[0].is_a?(::String)
379
+ _from_rbexpr(_rbexpr.exclude(columns))
383
380
  else
384
- wrap_expr(_rbexpr.exclude_dtype(columns))
381
+ _from_rbexpr(_rbexpr.exclude_dtype(columns))
385
382
  end
386
383
  end
387
384
 
@@ -490,8 +487,9 @@ module Polars
490
487
  # # │ true │
491
488
  # # └───────┘
492
489
  def is_not
493
- wrap_expr(_rbexpr.is_not)
490
+ _from_rbexpr(_rbexpr.not_)
494
491
  end
492
+ alias_method :not_, :is_not
495
493
 
496
494
  # Returns a boolean Series indicating which values are null.
497
495
  #
@@ -519,7 +517,7 @@ module Polars
519
517
  # # │ 5 ┆ 5.0 ┆ false ┆ false │
520
518
  # # └──────┴─────┴──────────┴──────────┘
521
519
  def is_null
522
- wrap_expr(_rbexpr.is_null)
520
+ _from_rbexpr(_rbexpr.is_null)
523
521
  end
524
522
 
525
523
  # Returns a boolean Series indicating which values are not null.
@@ -548,7 +546,7 @@ module Polars
548
546
  # # │ 5 ┆ 5.0 ┆ true ┆ true │
549
547
  # # └──────┴─────┴────────────┴────────────┘
550
548
  def is_not_null
551
- wrap_expr(_rbexpr.is_not_null)
549
+ _from_rbexpr(_rbexpr.is_not_null)
552
550
  end
553
551
 
554
552
  # Returns a boolean Series indicating which values are finite.
@@ -574,7 +572,7 @@ module Polars
574
572
  # # │ true ┆ false │
575
573
  # # └──────┴───────┘
576
574
  def is_finite
577
- wrap_expr(_rbexpr.is_finite)
575
+ _from_rbexpr(_rbexpr.is_finite)
578
576
  end
579
577
 
580
578
  # Returns a boolean Series indicating which values are infinite.
@@ -600,7 +598,7 @@ module Polars
600
598
  # # │ false ┆ true │
601
599
  # # └───────┴───────┘
602
600
  def is_infinite
603
- wrap_expr(_rbexpr.is_infinite)
601
+ _from_rbexpr(_rbexpr.is_infinite)
604
602
  end
605
603
 
606
604
  # Returns a boolean Series indicating which values are NaN.
@@ -633,7 +631,7 @@ module Polars
633
631
  # # │ 5 ┆ 5.0 ┆ false │
634
632
  # # └──────┴─────┴─────────┘
635
633
  def is_nan
636
- wrap_expr(_rbexpr.is_nan)
634
+ _from_rbexpr(_rbexpr.is_nan)
637
635
  end
638
636
 
639
637
  # Returns a boolean Series indicating which values are not NaN.
@@ -666,7 +664,7 @@ module Polars
666
664
  # # │ 5 ┆ 5.0 ┆ true │
667
665
  # # └──────┴─────┴──────────────┘
668
666
  def is_not_nan
669
- wrap_expr(_rbexpr.is_not_nan)
667
+ _from_rbexpr(_rbexpr.is_not_nan)
670
668
  end
671
669
 
672
670
  # Get the group indexes of the group by operation.
@@ -701,7 +699,7 @@ module Polars
701
699
  # # │ two ┆ [3, 4, 5] │
702
700
  # # └───────┴───────────┘
703
701
  def agg_groups
704
- wrap_expr(_rbexpr.agg_groups)
702
+ _from_rbexpr(_rbexpr.agg_groups)
705
703
  end
706
704
 
707
705
  # Count the number of values in this expression.
@@ -718,16 +716,14 @@ module Polars
718
716
  # # │ --- ┆ --- │
719
717
  # # │ u32 ┆ u32 │
720
718
  # # ╞═════╪═════╡
721
- # # │ 3 ┆ 3
719
+ # # │ 3 ┆ 2
722
720
  # # └─────┴─────┘
723
721
  def count
724
- wrap_expr(_rbexpr.count)
722
+ _from_rbexpr(_rbexpr.count)
725
723
  end
726
724
 
727
725
  # Count the number of values in this expression.
728
726
  #
729
- # Alias for {#count}.
730
- #
731
727
  # @return [Expr]
732
728
  #
733
729
  # @example
@@ -743,8 +739,9 @@ module Polars
743
739
  # # │ 3 ┆ 3 │
744
740
  # # └─────┴─────┘
745
741
  def len
746
- count
742
+ _from_rbexpr(_rbexpr.len)
747
743
  end
744
+ alias_method :length, :len
748
745
 
749
746
  # Get a slice of this expression.
750
747
  #
@@ -781,7 +778,7 @@ module Polars
781
778
  if !length.is_a?(Expr)
782
779
  length = Polars.lit(length)
783
780
  end
784
- wrap_expr(_rbexpr.slice(offset._rbexpr, length._rbexpr))
781
+ _from_rbexpr(_rbexpr.slice(offset._rbexpr, length._rbexpr))
785
782
  end
786
783
 
787
784
  # Append expressions.
@@ -815,7 +812,7 @@ module Polars
815
812
  # # └─────┴──────┘
816
813
  def append(other, upcast: true)
817
814
  other = Utils.expr_to_lit_or_expr(other)
818
- wrap_expr(_rbexpr.append(other._rbexpr, upcast))
815
+ _from_rbexpr(_rbexpr.append(other._rbexpr, upcast))
819
816
  end
820
817
 
821
818
  # Create a single chunk of memory for this Series.
@@ -840,7 +837,7 @@ module Polars
840
837
  # # │ 2 │
841
838
  # # └────────┘
842
839
  def rechunk
843
- wrap_expr(_rbexpr.rechunk)
840
+ _from_rbexpr(_rbexpr.rechunk)
844
841
  end
845
842
 
846
843
  # Drop null values.
@@ -867,7 +864,7 @@ module Polars
867
864
  # # │ NaN │
868
865
  # # └─────┘
869
866
  def drop_nulls
870
- wrap_expr(_rbexpr.drop_nulls)
867
+ _from_rbexpr(_rbexpr.drop_nulls)
871
868
  end
872
869
 
873
870
  # Drop floating point NaN values.
@@ -894,7 +891,7 @@ module Polars
894
891
  # # │ 4.0 │
895
892
  # # └──────┘
896
893
  def drop_nans
897
- wrap_expr(_rbexpr.drop_nans)
894
+ _from_rbexpr(_rbexpr.drop_nans)
898
895
  end
899
896
 
900
897
  # Get an array with the cumulative sum computed at every element.
@@ -929,7 +926,7 @@ module Polars
929
926
  # # │ 10 ┆ 4 │
930
927
  # # └─────┴───────────┘
931
928
  def cum_sum(reverse: false)
932
- wrap_expr(_rbexpr.cum_sum(reverse))
929
+ _from_rbexpr(_rbexpr.cum_sum(reverse))
933
930
  end
934
931
  alias_method :cumsum, :cum_sum
935
932
 
@@ -965,7 +962,7 @@ module Polars
965
962
  # # │ 24 ┆ 4 │
966
963
  # # └─────┴───────────┘
967
964
  def cum_prod(reverse: false)
968
- wrap_expr(_rbexpr.cum_prod(reverse))
965
+ _from_rbexpr(_rbexpr.cum_prod(reverse))
969
966
  end
970
967
  alias_method :cumprod, :cum_prod
971
968
 
@@ -997,7 +994,7 @@ module Polars
997
994
  # # │ 1 ┆ 4 │
998
995
  # # └─────┴───────────┘
999
996
  def cum_min(reverse: false)
1000
- wrap_expr(_rbexpr.cum_min(reverse))
997
+ _from_rbexpr(_rbexpr.cum_min(reverse))
1001
998
  end
1002
999
  alias_method :cummin, :cum_min
1003
1000
 
@@ -1029,7 +1026,7 @@ module Polars
1029
1026
  # # │ 4 ┆ 4 │
1030
1027
  # # └─────┴───────────┘
1031
1028
  def cum_max(reverse: false)
1032
- wrap_expr(_rbexpr.cum_max(reverse))
1029
+ _from_rbexpr(_rbexpr.cum_max(reverse))
1033
1030
  end
1034
1031
  alias_method :cummax, :cum_max
1035
1032
 
@@ -1043,27 +1040,27 @@ module Polars
1043
1040
  # @return [Expr]
1044
1041
  #
1045
1042
  # @example
1046
- # df = Polars::DataFrame.new({"a" => [1, 2, 3, 4]})
1047
- # df.select(
1043
+ # df = Polars::DataFrame.new({"a" => ["x", "k", nil, "d"]})
1044
+ # df.with_columns(
1048
1045
  # [
1049
- # Polars.col("a").cum_count,
1050
- # Polars.col("a").cum_count(reverse: true).alias("a_reverse")
1046
+ # Polars.col("a").cum_count.alias("cum_count"),
1047
+ # Polars.col("a").cum_count(reverse: true).alias("cum_count_reverse")
1051
1048
  # ]
1052
1049
  # )
1053
1050
  # # =>
1054
- # # shape: (4, 2)
1055
- # # ┌─────┬───────────┐
1056
- # # │ a a_reverse
1057
- # # │ --- ┆ ---
1058
- # # │ u32 ┆ u32
1059
- # # ╞═════╪═══════════╡
1060
- # # │ 0 ┆ 3
1061
- # # │ 1 ┆ 2 │
1062
- # # │ 2 ┆ 1
1063
- # # │ 3 0
1064
- # # └─────┴───────────┘
1051
+ # # shape: (4, 3)
1052
+ # # ┌──────┬───────────┬───────────────────┐
1053
+ # # │ a cum_count ┆ cum_count_reverse
1054
+ # # │ --- --- ┆ ---
1055
+ # # │ str ┆ u32 ┆ u32
1056
+ # # ╞══════╪═══════════╪═══════════════════╡
1057
+ # # │ x 1 ┆ 3
1058
+ # # │ k ┆ 2 ┆ 2
1059
+ # # │ null ┆ 2 ┆ 1
1060
+ # # │ d ┆ 3 1
1061
+ # # └──────┴───────────┴───────────────────┘
1065
1062
  def cum_count(reverse: false)
1066
- wrap_expr(_rbexpr.cum_count(reverse))
1063
+ _from_rbexpr(_rbexpr.cum_count(reverse))
1067
1064
  end
1068
1065
  alias_method :cumcount, :cum_count
1069
1066
 
@@ -1089,7 +1086,7 @@ module Polars
1089
1086
  # # │ 1.0 │
1090
1087
  # # └─────┘
1091
1088
  def floor
1092
- wrap_expr(_rbexpr.floor)
1089
+ _from_rbexpr(_rbexpr.floor)
1093
1090
  end
1094
1091
 
1095
1092
  # Rounds up to the nearest integer value.
@@ -1114,7 +1111,7 @@ module Polars
1114
1111
  # # │ 2.0 │
1115
1112
  # # └─────┘
1116
1113
  def ceil
1117
- wrap_expr(_rbexpr.ceil)
1114
+ _from_rbexpr(_rbexpr.ceil)
1118
1115
  end
1119
1116
 
1120
1117
  # Round underlying floating point data by `decimals` digits.
@@ -1140,7 +1137,7 @@ module Polars
1140
1137
  # # │ 1.2 │
1141
1138
  # # └─────┘
1142
1139
  def round(decimals = 0)
1143
- wrap_expr(_rbexpr.round(decimals))
1140
+ _from_rbexpr(_rbexpr.round(decimals))
1144
1141
  end
1145
1142
 
1146
1143
  # Compute the dot/inner product between two Expressions.
@@ -1169,7 +1166,7 @@ module Polars
1169
1166
  # # └─────┘
1170
1167
  def dot(other)
1171
1168
  other = Utils.expr_to_lit_or_expr(other, str_to_lit: false)
1172
- wrap_expr(_rbexpr.dot(other._rbexpr))
1169
+ _from_rbexpr(_rbexpr.dot(other._rbexpr))
1173
1170
  end
1174
1171
 
1175
1172
  # Compute the most occurring value(s).
@@ -1197,7 +1194,7 @@ module Polars
1197
1194
  # # │ 1 ┆ 2 │
1198
1195
  # # └─────┴─────┘
1199
1196
  def mode
1200
- wrap_expr(_rbexpr.mode)
1197
+ _from_rbexpr(_rbexpr.mode)
1201
1198
  end
1202
1199
 
1203
1200
  # Cast between data types.
@@ -1236,7 +1233,7 @@ module Polars
1236
1233
  # # └─────┴─────┘
1237
1234
  def cast(dtype, strict: true)
1238
1235
  dtype = Utils.rb_type_to_dtype(dtype)
1239
- wrap_expr(_rbexpr.cast(dtype, strict))
1236
+ _from_rbexpr(_rbexpr.cast(dtype, strict))
1240
1237
  end
1241
1238
 
1242
1239
  # Sort this column. In projection/ selection context the whole column is sorted.
@@ -1311,7 +1308,7 @@ module Polars
1311
1308
  # # │ one ┆ [1, 2, 98] │
1312
1309
  # # └───────┴────────────┘
1313
1310
  def sort(reverse: false, nulls_last: false)
1314
- wrap_expr(_rbexpr.sort_with(reverse, nulls_last))
1311
+ _from_rbexpr(_rbexpr.sort_with(reverse, nulls_last))
1315
1312
  end
1316
1313
 
1317
1314
  # Return the `k` largest elements.
@@ -1350,7 +1347,7 @@ module Polars
1350
1347
  # # └───────┴──────────┘
1351
1348
  def top_k(k: 5)
1352
1349
  k = Utils.parse_as_expression(k)
1353
- wrap_expr(_rbexpr.top_k(k))
1350
+ _from_rbexpr(_rbexpr.top_k(k))
1354
1351
  end
1355
1352
 
1356
1353
  # Return the `k` smallest elements.
@@ -1389,7 +1386,7 @@ module Polars
1389
1386
  # # └───────┴──────────┘
1390
1387
  def bottom_k(k: 5)
1391
1388
  k = Utils.parse_as_expression(k)
1392
- wrap_expr(_rbexpr.bottom_k(k))
1389
+ _from_rbexpr(_rbexpr.bottom_k(k))
1393
1390
  end
1394
1391
 
1395
1392
  # Get the index values that would sort this column.
@@ -1420,7 +1417,7 @@ module Polars
1420
1417
  # # │ 2 │
1421
1418
  # # └─────┘
1422
1419
  def arg_sort(reverse: false, nulls_last: false)
1423
- wrap_expr(_rbexpr.arg_sort(reverse, nulls_last))
1420
+ _from_rbexpr(_rbexpr.arg_sort(reverse, nulls_last))
1424
1421
  end
1425
1422
 
1426
1423
  # Get the index of the maximal value.
@@ -1444,7 +1441,7 @@ module Polars
1444
1441
  # # │ 2 │
1445
1442
  # # └─────┘
1446
1443
  def arg_max
1447
- wrap_expr(_rbexpr.arg_max)
1444
+ _from_rbexpr(_rbexpr.arg_max)
1448
1445
  end
1449
1446
 
1450
1447
  # Get the index of the minimal value.
@@ -1468,7 +1465,7 @@ module Polars
1468
1465
  # # │ 1 │
1469
1466
  # # └─────┘
1470
1467
  def arg_min
1471
- wrap_expr(_rbexpr.arg_min)
1468
+ _from_rbexpr(_rbexpr.arg_min)
1472
1469
  end
1473
1470
 
1474
1471
  # Find indices where elements should be inserted to maintain order.
@@ -1502,7 +1499,7 @@ module Polars
1502
1499
  # # └──────┴───────┴─────┘
1503
1500
  def search_sorted(element, side: "any")
1504
1501
  element = Utils.expr_to_lit_or_expr(element, str_to_lit: false)
1505
- wrap_expr(_rbexpr.search_sorted(element._rbexpr, side))
1502
+ _from_rbexpr(_rbexpr.search_sorted(element._rbexpr, side))
1506
1503
  end
1507
1504
 
1508
1505
  # Sort this column by the ordering of another column, or multiple other columns.
@@ -1556,7 +1553,7 @@ module Polars
1556
1553
  end
1557
1554
  by = Utils.selection_to_rbexpr_list(by)
1558
1555
 
1559
- wrap_expr(_rbexpr.sort_by(by, reverse))
1556
+ _from_rbexpr(_rbexpr.sort_by(by, reverse))
1560
1557
  end
1561
1558
 
1562
1559
  # Take values by index.
@@ -1597,7 +1594,7 @@ module Polars
1597
1594
  else
1598
1595
  indices_lit = Utils.expr_to_lit_or_expr(indices, str_to_lit: false)
1599
1596
  end
1600
- wrap_expr(_rbexpr.gather(indices_lit._rbexpr))
1597
+ _from_rbexpr(_rbexpr.gather(indices_lit._rbexpr))
1601
1598
  end
1602
1599
  alias_method :take, :gather
1603
1600
 
@@ -1630,7 +1627,7 @@ module Polars
1630
1627
  fill_value = Utils.parse_as_expression(fill_value, str_as_lit: true)
1631
1628
  end
1632
1629
  n = Utils.parse_as_expression(n)
1633
- wrap_expr(_rbexpr.shift(n, fill_value))
1630
+ _from_rbexpr(_rbexpr.shift(n, fill_value))
1634
1631
  end
1635
1632
 
1636
1633
  # Shift the values by a given period and fill the resulting null values.
@@ -1733,9 +1730,9 @@ module Polars
1733
1730
 
1734
1731
  if !value.nil?
1735
1732
  value = Utils.expr_to_lit_or_expr(value, str_to_lit: true)
1736
- wrap_expr(_rbexpr.fill_null(value._rbexpr))
1733
+ _from_rbexpr(_rbexpr.fill_null(value._rbexpr))
1737
1734
  else
1738
- wrap_expr(_rbexpr.fill_null_with_strategy(strategy, limit))
1735
+ _from_rbexpr(_rbexpr.fill_null_with_strategy(strategy, limit))
1739
1736
  end
1740
1737
  end
1741
1738
 
@@ -1764,7 +1761,7 @@ module Polars
1764
1761
  # # └──────┴──────┘
1765
1762
  def fill_nan(fill_value)
1766
1763
  fill_value = Utils.expr_to_lit_or_expr(fill_value, str_to_lit: true)
1767
- wrap_expr(_rbexpr.fill_nan(fill_value._rbexpr))
1764
+ _from_rbexpr(_rbexpr.fill_nan(fill_value._rbexpr))
1768
1765
  end
1769
1766
 
1770
1767
  # Fill missing values with the latest seen values.
@@ -1794,7 +1791,7 @@ module Polars
1794
1791
  # # │ 2 ┆ 6 │
1795
1792
  # # └─────┴─────┘
1796
1793
  def forward_fill(limit: nil)
1797
- wrap_expr(_rbexpr.forward_fill(limit))
1794
+ _from_rbexpr(_rbexpr.forward_fill(limit))
1798
1795
  end
1799
1796
 
1800
1797
  # Fill missing values with the next to be seen values.
@@ -1824,14 +1821,14 @@ module Polars
1824
1821
  # # │ null ┆ 6 │
1825
1822
  # # └──────┴─────┘
1826
1823
  def backward_fill(limit: nil)
1827
- wrap_expr(_rbexpr.backward_fill(limit))
1824
+ _from_rbexpr(_rbexpr.backward_fill(limit))
1828
1825
  end
1829
1826
 
1830
1827
  # Reverse the selection.
1831
1828
  #
1832
1829
  # @return [Expr]
1833
1830
  def reverse
1834
- wrap_expr(_rbexpr.reverse)
1831
+ _from_rbexpr(_rbexpr.reverse)
1835
1832
  end
1836
1833
 
1837
1834
  # Get standard deviation.
@@ -1854,7 +1851,7 @@ module Polars
1854
1851
  # # │ 1.0 │
1855
1852
  # # └─────┘
1856
1853
  def std(ddof: 1)
1857
- wrap_expr(_rbexpr.std(ddof))
1854
+ _from_rbexpr(_rbexpr.std(ddof))
1858
1855
  end
1859
1856
 
1860
1857
  # Get variance.
@@ -1877,7 +1874,7 @@ module Polars
1877
1874
  # # │ 1.0 │
1878
1875
  # # └─────┘
1879
1876
  def var(ddof: 1)
1880
- wrap_expr(_rbexpr.var(ddof))
1877
+ _from_rbexpr(_rbexpr.var(ddof))
1881
1878
  end
1882
1879
 
1883
1880
  # Get maximum value.
@@ -1897,7 +1894,7 @@ module Polars
1897
1894
  # # │ 1.0 │
1898
1895
  # # └─────┘
1899
1896
  def max
1900
- wrap_expr(_rbexpr.max)
1897
+ _from_rbexpr(_rbexpr.max)
1901
1898
  end
1902
1899
 
1903
1900
  # Get minimum value.
@@ -1917,7 +1914,7 @@ module Polars
1917
1914
  # # │ -1.0 │
1918
1915
  # # └──────┘
1919
1916
  def min
1920
- wrap_expr(_rbexpr.min)
1917
+ _from_rbexpr(_rbexpr.min)
1921
1918
  end
1922
1919
 
1923
1920
  # Get maximum value, but propagate/poison encountered NaN values.
@@ -1937,7 +1934,7 @@ module Polars
1937
1934
  # # │ NaN │
1938
1935
  # # └─────┘
1939
1936
  def nan_max
1940
- wrap_expr(_rbexpr.nan_max)
1937
+ _from_rbexpr(_rbexpr.nan_max)
1941
1938
  end
1942
1939
 
1943
1940
  # Get minimum value, but propagate/poison encountered NaN values.
@@ -1957,7 +1954,7 @@ module Polars
1957
1954
  # # │ NaN │
1958
1955
  # # └─────┘
1959
1956
  def nan_min
1960
- wrap_expr(_rbexpr.nan_min)
1957
+ _from_rbexpr(_rbexpr.nan_min)
1961
1958
  end
1962
1959
 
1963
1960
  # Get sum value.
@@ -1981,7 +1978,7 @@ module Polars
1981
1978
  # # │ 0 │
1982
1979
  # # └─────┘
1983
1980
  def sum
1984
- wrap_expr(_rbexpr.sum)
1981
+ _from_rbexpr(_rbexpr.sum)
1985
1982
  end
1986
1983
 
1987
1984
  # Get mean value.
@@ -2001,7 +1998,7 @@ module Polars
2001
1998
  # # │ 0.0 │
2002
1999
  # # └─────┘
2003
2000
  def mean
2004
- wrap_expr(_rbexpr.mean)
2001
+ _from_rbexpr(_rbexpr.mean)
2005
2002
  end
2006
2003
 
2007
2004
  # Get median value using linear interpolation.
@@ -2021,7 +2018,7 @@ module Polars
2021
2018
  # # │ 0.0 │
2022
2019
  # # └─────┘
2023
2020
  def median
2024
- wrap_expr(_rbexpr.median)
2021
+ _from_rbexpr(_rbexpr.median)
2025
2022
  end
2026
2023
 
2027
2024
  # Compute the product of an expression.
@@ -2041,7 +2038,7 @@ module Polars
2041
2038
  # # │ 6 │
2042
2039
  # # └─────┘
2043
2040
  def product
2044
- wrap_expr(_rbexpr.product)
2041
+ _from_rbexpr(_rbexpr.product)
2045
2042
  end
2046
2043
 
2047
2044
  # Count unique values.
@@ -2061,7 +2058,7 @@ module Polars
2061
2058
  # # │ 2 │
2062
2059
  # # └─────┘
2063
2060
  def n_unique
2064
- wrap_expr(_rbexpr.n_unique)
2061
+ _from_rbexpr(_rbexpr.n_unique)
2065
2062
  end
2066
2063
 
2067
2064
  # Approx count unique values.
@@ -2072,7 +2069,7 @@ module Polars
2072
2069
  #
2073
2070
  # @example
2074
2071
  # df = Polars::DataFrame.new({"a" => [1, 1, 2]})
2075
- # df.select(Polars.col("a").approx_unique)
2072
+ # df.select(Polars.col("a").approx_n_unique)
2076
2073
  # # =>
2077
2074
  # # shape: (1, 1)
2078
2075
  # # ┌─────┐
@@ -2082,9 +2079,10 @@ module Polars
2082
2079
  # # ╞═════╡
2083
2080
  # # │ 2 │
2084
2081
  # # └─────┘
2085
- def approx_unique
2086
- wrap_expr(_rbexpr.approx_n_unique)
2082
+ def approx_n_unique
2083
+ _from_rbexpr(_rbexpr.approx_n_unique)
2087
2084
  end
2085
+ alias_method :approx_unique, :approx_n_unique
2088
2086
 
2089
2087
  # Count null values.
2090
2088
  #
@@ -2108,7 +2106,7 @@ module Polars
2108
2106
  # # │ 2 ┆ 0 │
2109
2107
  # # └─────┴─────┘
2110
2108
  def null_count
2111
- wrap_expr(_rbexpr.null_count)
2109
+ _from_rbexpr(_rbexpr.null_count)
2112
2110
  end
2113
2111
 
2114
2112
  # Get index of first unique value.
@@ -2148,7 +2146,7 @@ module Polars
2148
2146
  # # │ 1 │
2149
2147
  # # └─────┘
2150
2148
  def arg_unique
2151
- wrap_expr(_rbexpr.arg_unique)
2149
+ _from_rbexpr(_rbexpr.arg_unique)
2152
2150
  end
2153
2151
 
2154
2152
  # Get unique values of this expression.
@@ -2173,9 +2171,9 @@ module Polars
2173
2171
  # # └─────┘
2174
2172
  def unique(maintain_order: false)
2175
2173
  if maintain_order
2176
- wrap_expr(_rbexpr.unique_stable)
2174
+ _from_rbexpr(_rbexpr.unique_stable)
2177
2175
  else
2178
- wrap_expr(_rbexpr.unique)
2176
+ _from_rbexpr(_rbexpr.unique)
2179
2177
  end
2180
2178
  end
2181
2179
 
@@ -2196,7 +2194,7 @@ module Polars
2196
2194
  # # │ 1 │
2197
2195
  # # └─────┘
2198
2196
  def first
2199
- wrap_expr(_rbexpr.first)
2197
+ _from_rbexpr(_rbexpr.first)
2200
2198
  end
2201
2199
 
2202
2200
  # Get the last value.
@@ -2216,7 +2214,7 @@ module Polars
2216
2214
  # # │ 2 │
2217
2215
  # # └─────┘
2218
2216
  def last
2219
- wrap_expr(_rbexpr.last)
2217
+ _from_rbexpr(_rbexpr.last)
2220
2218
  end
2221
2219
 
2222
2220
  # Apply window function over a subgroup.
@@ -2280,7 +2278,7 @@ module Polars
2280
2278
  # # └────────┘
2281
2279
  def over(expr)
2282
2280
  rbexprs = Utils.selection_to_rbexpr_list(expr)
2283
- wrap_expr(_rbexpr.over(rbexprs))
2281
+ _from_rbexpr(_rbexpr.over(rbexprs))
2284
2282
  end
2285
2283
 
2286
2284
  # Get mask of unique values.
@@ -2302,7 +2300,7 @@ module Polars
2302
2300
  # # │ true │
2303
2301
  # # └───────┘
2304
2302
  def is_unique
2305
- wrap_expr(_rbexpr.is_unique)
2303
+ _from_rbexpr(_rbexpr.is_unique)
2306
2304
  end
2307
2305
 
2308
2306
  # Get a mask of the first unique value.
@@ -2330,7 +2328,7 @@ module Polars
2330
2328
  # # │ 5 ┆ true │
2331
2329
  # # └─────┴──────────┘
2332
2330
  def is_first_distinct
2333
- wrap_expr(_rbexpr.is_first_distinct)
2331
+ _from_rbexpr(_rbexpr.is_first_distinct)
2334
2332
  end
2335
2333
  alias_method :is_first, :is_first_distinct
2336
2334
 
@@ -2353,7 +2351,7 @@ module Polars
2353
2351
  # # │ false │
2354
2352
  # # └───────┘
2355
2353
  def is_duplicated
2356
- wrap_expr(_rbexpr.is_duplicated)
2354
+ _from_rbexpr(_rbexpr.is_duplicated)
2357
2355
  end
2358
2356
 
2359
2357
  # Get a boolean mask of the local maximum peaks.
@@ -2377,7 +2375,7 @@ module Polars
2377
2375
  # # │ true │
2378
2376
  # # └───────┘
2379
2377
  def peak_max
2380
- wrap_expr(_rbexpr.peak_max)
2378
+ _from_rbexpr(_rbexpr.peak_max)
2381
2379
  end
2382
2380
 
2383
2381
  # Get a boolean mask of the local minimum peaks.
@@ -2401,7 +2399,7 @@ module Polars
2401
2399
  # # │ false │
2402
2400
  # # └───────┘
2403
2401
  def peak_min
2404
- wrap_expr(_rbexpr.peak_min)
2402
+ _from_rbexpr(_rbexpr.peak_min)
2405
2403
  end
2406
2404
 
2407
2405
  # Get quantile value.
@@ -2423,7 +2421,7 @@ module Polars
2423
2421
  # # │ --- │
2424
2422
  # # │ f64 │
2425
2423
  # # ╞═════╡
2426
- # # │ 1.0 │
2424
+ # # │ 2.0 │
2427
2425
  # # └─────┘
2428
2426
  #
2429
2427
  # @example
@@ -2475,7 +2473,207 @@ module Polars
2475
2473
  # # └─────┘
2476
2474
  def quantile(quantile, interpolation: "nearest")
2477
2475
  quantile = Utils.expr_to_lit_or_expr(quantile, str_to_lit: false)
2478
- wrap_expr(_rbexpr.quantile(quantile._rbexpr, interpolation))
2476
+ _from_rbexpr(_rbexpr.quantile(quantile._rbexpr, interpolation))
2477
+ end
2478
+
2479
+ # Bin continuous values into discrete categories.
2480
+ #
2481
+ # @param breaks [Array]
2482
+ # List of unique cut points.
2483
+ # @param labels [Array]
2484
+ # Names of the categories. The number of labels must be equal to the number
2485
+ # of cut points plus one.
2486
+ # @param left_closed [Boolean]
2487
+ # Set the intervals to be left-closed instead of right-closed.
2488
+ # @param include_breaks [Boolean]
2489
+ # Include a column with the right endpoint of the bin each observation falls
2490
+ # in. This will change the data type of the output from a
2491
+ # `Categorical` to a `Struct`.
2492
+ #
2493
+ # @return [Expr]
2494
+ #
2495
+ # @example Divide a column into three categories.
2496
+ # df = Polars::DataFrame.new({"foo" => [-2, -1, 0, 1, 2]})
2497
+ # df.with_columns(
2498
+ # Polars.col("foo").cut([-1, 1], labels: ["a", "b", "c"]).alias("cut")
2499
+ # )
2500
+ # # =>
2501
+ # # shape: (5, 2)
2502
+ # # ┌─────┬─────┐
2503
+ # # │ foo ┆ cut │
2504
+ # # │ --- ┆ --- │
2505
+ # # │ i64 ┆ cat │
2506
+ # # ╞═════╪═════╡
2507
+ # # │ -2 ┆ a │
2508
+ # # │ -1 ┆ a │
2509
+ # # │ 0 ┆ b │
2510
+ # # │ 1 ┆ b │
2511
+ # # │ 2 ┆ c │
2512
+ # # └─────┴─────┘
2513
+ #
2514
+ # @example Add both the category and the breakpoint.
2515
+ # df.with_columns(
2516
+ # Polars.col("foo").cut([-1, 1], include_breaks: true).alias("cut")
2517
+ # ).unnest("cut")
2518
+ # # =>
2519
+ # # shape: (5, 3)
2520
+ # # ┌─────┬──────┬────────────┐
2521
+ # # │ foo ┆ brk ┆ foo_bin │
2522
+ # # │ --- ┆ --- ┆ --- │
2523
+ # # │ i64 ┆ f64 ┆ cat │
2524
+ # # ╞═════╪══════╪════════════╡
2525
+ # # │ -2 ┆ -1.0 ┆ (-inf, -1] │
2526
+ # # │ -1 ┆ -1.0 ┆ (-inf, -1] │
2527
+ # # │ 0 ┆ 1.0 ┆ (-1, 1] │
2528
+ # # │ 1 ┆ 1.0 ┆ (-1, 1] │
2529
+ # # │ 2 ┆ inf ┆ (1, inf] │
2530
+ # # └─────┴──────┴────────────┘
2531
+ def cut(breaks, labels: nil, left_closed: false, include_breaks: false)
2532
+ _from_rbexpr(_rbexpr.cut(breaks, labels, left_closed, include_breaks))
2533
+ end
2534
+
2535
+ # Bin continuous values into discrete categories based on their quantiles.
2536
+ #
2537
+ # @param quantiles [Array]
2538
+ # Either a list of quantile probabilities between 0 and 1 or a positive
2539
+ # integer determining the number of bins with uniform probability.
2540
+ # @param labels [Array]
2541
+ # Names of the categories. The number of labels must be equal to the number
2542
+ # of categories.
2543
+ # @param left_closed [Boolean]
2544
+ # Set the intervals to be left-closed instead of right-closed.
2545
+ # @param allow_duplicates [Boolean]
2546
+ # If set to `true`, duplicates in the resulting quantiles are dropped,
2547
+ # rather than raising a `DuplicateError`. This can happen even with unique
2548
+ # probabilities, depending on the data.
2549
+ # @param include_breaks [Boolean]
2550
+ # Include a column with the right endpoint of the bin each observation falls
2551
+ # in. This will change the data type of the output from a
2552
+ # `Categorical` to a `Struct`.
2553
+ #
2554
+ # @return [Expr]
2555
+ #
2556
+ # @example Divide a column into three categories according to pre-defined quantile probabilities.
2557
+ # df = Polars::DataFrame.new({"foo" => [-2, -1, 0, 1, 2]})
2558
+ # df.with_columns(
2559
+ # Polars.col("foo").qcut([0.25, 0.75], labels: ["a", "b", "c"]).alias("qcut")
2560
+ # )
2561
+ # # =>
2562
+ # # shape: (5, 2)
2563
+ # # ┌─────┬──────┐
2564
+ # # │ foo ┆ qcut │
2565
+ # # │ --- ┆ --- │
2566
+ # # │ i64 ┆ cat │
2567
+ # # ╞═════╪══════╡
2568
+ # # │ -2 ┆ a │
2569
+ # # │ -1 ┆ a │
2570
+ # # │ 0 ┆ b │
2571
+ # # │ 1 ┆ b │
2572
+ # # │ 2 ┆ c │
2573
+ # # └─────┴──────┘
2574
+ #
2575
+ # @example Divide a column into two categories using uniform quantile probabilities.
2576
+ # df.with_columns(
2577
+ # Polars.col("foo")
2578
+ # .qcut(2, labels: ["low", "high"], left_closed: true)
2579
+ # .alias("qcut")
2580
+ # )
2581
+ # # =>
2582
+ # # shape: (5, 2)
2583
+ # # ┌─────┬──────┐
2584
+ # # │ foo ┆ qcut │
2585
+ # # │ --- ┆ --- │
2586
+ # # │ i64 ┆ cat │
2587
+ # # ╞═════╪══════╡
2588
+ # # │ -2 ┆ low │
2589
+ # # │ -1 ┆ low │
2590
+ # # │ 0 ┆ high │
2591
+ # # │ 1 ┆ high │
2592
+ # # │ 2 ┆ high │
2593
+ # # └─────┴──────┘
2594
+ #
2595
+ # @example Add both the category and the breakpoint.
2596
+ # df.with_columns(
2597
+ # Polars.col("foo").qcut([0.25, 0.75], include_breaks: true).alias("qcut")
2598
+ # ).unnest("qcut")
2599
+ # # =>
2600
+ # # shape: (5, 3)
2601
+ # # ┌─────┬──────┬────────────┐
2602
+ # # │ foo ┆ brk ┆ foo_bin │
2603
+ # # │ --- ┆ --- ┆ --- │
2604
+ # # │ i64 ┆ f64 ┆ cat │
2605
+ # # ╞═════╪══════╪════════════╡
2606
+ # # │ -2 ┆ -1.0 ┆ (-inf, -1] │
2607
+ # # │ -1 ┆ -1.0 ┆ (-inf, -1] │
2608
+ # # │ 0 ┆ 1.0 ┆ (-1, 1] │
2609
+ # # │ 1 ┆ 1.0 ┆ (-1, 1] │
2610
+ # # │ 2 ┆ inf ┆ (1, inf] │
2611
+ # # └─────┴──────┴────────────┘
2612
+ def qcut(quantiles, labels: nil, left_closed: false, allow_duplicates: false, include_breaks: false)
2613
+ if quantiles.is_a?(Integer)
2614
+ rbexpr = _rbexpr.qcut_uniform(
2615
+ quantiles, labels, left_closed, allow_duplicates, include_breaks
2616
+ )
2617
+ else
2618
+ rbexpr = _rbexpr.qcut(
2619
+ quantiles, labels, left_closed, allow_duplicates, include_breaks
2620
+ )
2621
+ end
2622
+
2623
+ _from_rbexpr(rbexpr)
2624
+ end
2625
+
2626
+ # Get the lengths of runs of identical values.
2627
+ #
2628
+ # @return [Expr]
2629
+ #
2630
+ # @example
2631
+ # df = Polars::DataFrame.new(Polars::Series.new("s", [1, 1, 2, 1, nil, 1, 3, 3]))
2632
+ # df.select(Polars.col("s").rle).unnest("s")
2633
+ # # =>
2634
+ # # shape: (6, 2)
2635
+ # # ┌─────────┬────────┐
2636
+ # # │ lengths ┆ values │
2637
+ # # │ --- ┆ --- │
2638
+ # # │ i32 ┆ i64 │
2639
+ # # ╞═════════╪════════╡
2640
+ # # │ 2 ┆ 1 │
2641
+ # # │ 1 ┆ 2 │
2642
+ # # │ 1 ┆ 1 │
2643
+ # # │ 1 ┆ null │
2644
+ # # │ 1 ┆ 1 │
2645
+ # # │ 2 ┆ 3 │
2646
+ # # └─────────┴────────┘
2647
+ def rle
2648
+ _from_rbexpr(_rbexpr.rle)
2649
+ end
2650
+
2651
+ # Map values to run IDs.
2652
+ #
2653
+ # Similar to RLE, but it maps each value to an ID corresponding to the run into
2654
+ # which it falls. This is especially useful when you want to define groups by
2655
+ # runs of identical values rather than the values themselves.
2656
+ #
2657
+ # @return [Expr]
2658
+ #
2659
+ # @example
2660
+ # df = Polars::DataFrame.new({"a" => [1, 2, 1, 1, 1], "b" => ["x", "x", nil, "y", "y"]})
2661
+ # df.with_columns([Polars.col("a").rle_id.alias("a_r"), Polars.struct(["a", "b"]).rle_id.alias("ab_r")])
2662
+ # # =>
2663
+ # # shape: (5, 4)
2664
+ # # ┌─────┬──────┬─────┬──────┐
2665
+ # # │ a ┆ b ┆ a_r ┆ ab_r │
2666
+ # # │ --- ┆ --- ┆ --- ┆ --- │
2667
+ # # │ i64 ┆ str ┆ u32 ┆ u32 │
2668
+ # # ╞═════╪══════╪═════╪══════╡
2669
+ # # │ 1 ┆ x ┆ 0 ┆ 0 │
2670
+ # # │ 2 ┆ x ┆ 1 ┆ 1 │
2671
+ # # │ 1 ┆ null ┆ 2 ┆ 2 │
2672
+ # # │ 1 ┆ y ┆ 2 ┆ 3 │
2673
+ # # │ 1 ┆ y ┆ 2 ┆ 3 │
2674
+ # # └─────┴──────┴─────┴──────┘
2675
+ def rle_id
2676
+ _from_rbexpr(_rbexpr.rle_id)
2479
2677
  end
2480
2678
 
2481
2679
  # Filter a single column.
@@ -2514,7 +2712,7 @@ module Polars
2514
2712
  # # │ g2 ┆ 0 ┆ 3 │
2515
2713
  # # └───────────┴─────┴─────┘
2516
2714
  def filter(predicate)
2517
- wrap_expr(_rbexpr.filter(predicate._rbexpr))
2715
+ _from_rbexpr(_rbexpr.filter(predicate._rbexpr))
2518
2716
  end
2519
2717
 
2520
2718
  # Filter a single column.
@@ -2592,7 +2790,7 @@ module Polars
2592
2790
  # if !return_dtype.nil?
2593
2791
  # return_dtype = Utils.rb_type_to_dtype(return_dtype)
2594
2792
  # end
2595
- # wrap_expr(_rbexpr.map(f, return_dtype, agg_list))
2793
+ # _from_rbexpr(_rbexpr.map(f, return_dtype, agg_list))
2596
2794
  # end
2597
2795
 
2598
2796
  # Apply a custom/user-defined function (UDF) in a GroupBy or Projection context.
@@ -2703,7 +2901,7 @@ module Polars
2703
2901
  # # │ b ┆ [2, 3, 4] │
2704
2902
  # # └───────┴───────────┘
2705
2903
  def flatten
2706
- wrap_expr(_rbexpr.explode)
2904
+ _from_rbexpr(_rbexpr.explode)
2707
2905
  end
2708
2906
 
2709
2907
  # Explode a list or utf8 Series.
@@ -2730,7 +2928,7 @@ module Polars
2730
2928
  # # │ 6 │
2731
2929
  # # └─────┘
2732
2930
  def explode
2733
- wrap_expr(_rbexpr.explode)
2931
+ _from_rbexpr(_rbexpr.explode)
2734
2932
  end
2735
2933
 
2736
2934
  # Take every nth value in the Series and return as a new Series.
@@ -2751,8 +2949,8 @@ module Polars
2751
2949
  # # │ 4 │
2752
2950
  # # │ 7 │
2753
2951
  # # └─────┘
2754
- def gather_every(n)
2755
- wrap_expr(_rbexpr.gather_every(n))
2952
+ def gather_every(n, offset = 0)
2953
+ _from_rbexpr(_rbexpr.gather_every(n, offset))
2756
2954
  end
2757
2955
  alias_method :take_every, :gather_every
2758
2956
 
@@ -2778,7 +2976,7 @@ module Polars
2778
2976
  # # │ 3 │
2779
2977
  # # └─────┘
2780
2978
  def head(n = 10)
2781
- wrap_expr(_rbexpr.head(n))
2979
+ _from_rbexpr(_rbexpr.head(n))
2782
2980
  end
2783
2981
 
2784
2982
  # Get the last `n` rows.
@@ -2803,7 +3001,7 @@ module Polars
2803
3001
  # # │ 7 │
2804
3002
  # # └─────┘
2805
3003
  def tail(n = 10)
2806
- wrap_expr(_rbexpr.tail(n))
3004
+ _from_rbexpr(_rbexpr.tail(n))
2807
3005
  end
2808
3006
 
2809
3007
  # Get the first `n` rows.
@@ -2818,6 +3016,500 @@ module Polars
2818
3016
  head(n)
2819
3017
  end
2820
3018
 
3019
+ # Method equivalent of equality operator `expr == other`.
3020
+ #
3021
+ # @param other [Object]
3022
+ # A literal or expression value to compare with.
3023
+ #
3024
+ # @return [Expr]
3025
+ # @example
3026
+ # df = Polars::DataFrame.new(
3027
+ # {
3028
+ # "x" => [1.0, 2.0, Float::NAN, 4.0],
3029
+ # "y" => [2.0, 2.0, Float::NAN, 4.0]
3030
+ # }
3031
+ # )
3032
+ # df.with_columns(
3033
+ # Polars.col("x").eq(Polars.col("y")).alias("x == y")
3034
+ # )
3035
+ # # =>
3036
+ # # shape: (4, 3)
3037
+ # # ┌─────┬─────┬────────┐
3038
+ # # │ x ┆ y ┆ x == y │
3039
+ # # │ --- ┆ --- ┆ --- │
3040
+ # # │ f64 ┆ f64 ┆ bool │
3041
+ # # ╞═════╪═════╪════════╡
3042
+ # # │ 1.0 ┆ 2.0 ┆ false │
3043
+ # # │ 2.0 ┆ 2.0 ┆ true │
3044
+ # # │ NaN ┆ NaN ┆ true │
3045
+ # # │ 4.0 ┆ 4.0 ┆ true │
3046
+ # # └─────┴─────┴────────┘
3047
+ def eq(other)
3048
+ self == other
3049
+ end
3050
+
3051
+ # Method equivalent of equality operator `expr == other` where `None == None`.
3052
+ #
3053
+ # This differs from default `eq` where null values are propagated.
3054
+ #
3055
+ # @param other [Object]
3056
+ # A literal or expression value to compare with.
3057
+ #
3058
+ # @return [Expr]
3059
+ #
3060
+ # @example
3061
+ # df = Polars::DataFrame.new(
3062
+ # data={
3063
+ # "x" => [1.0, 2.0, Float::NAN, 4.0, nil, nil],
3064
+ # "y" => [2.0, 2.0, Float::NAN, 4.0, 5.0, nil]
3065
+ # }
3066
+ # )
3067
+ # df.with_columns(
3068
+ # Polars.col("x").eq(Polars.col("y")).alias("x eq y"),
3069
+ # Polars.col("x").eq_missing(Polars.col("y")).alias("x eq_missing y")
3070
+ # )
3071
+ # # =>
3072
+ # # shape: (6, 4)
3073
+ # # ┌──────┬──────┬────────┬────────────────┐
3074
+ # # │ x ┆ y ┆ x eq y ┆ x eq_missing y │
3075
+ # # │ --- ┆ --- ┆ --- ┆ --- │
3076
+ # # │ f64 ┆ f64 ┆ bool ┆ bool │
3077
+ # # ╞══════╪══════╪════════╪════════════════╡
3078
+ # # │ 1.0 ┆ 2.0 ┆ false ┆ false │
3079
+ # # │ 2.0 ┆ 2.0 ┆ true ┆ true │
3080
+ # # │ NaN ┆ NaN ┆ true ┆ true │
3081
+ # # │ 4.0 ┆ 4.0 ┆ true ┆ true │
3082
+ # # │ null ┆ 5.0 ┆ null ┆ false │
3083
+ # # │ null ┆ null ┆ null ┆ true │
3084
+ # # └──────┴──────┴────────┴────────────────┘
3085
+ def eq_missing(other)
3086
+ other = Utils.parse_as_expression(other, str_as_lit: true)
3087
+ _from_rbexpr(_rbexpr.eq_missing(other))
3088
+ end
3089
+
3090
+ # Method equivalent of "greater than or equal" operator `expr >= other`.
3091
+ #
3092
+ # @param other [Object]
3093
+ # A literal or expression value to compare with.
3094
+ #
3095
+ # @return [Expr]
3096
+ #
3097
+ # @example
3098
+ # df = Polars::DataFrame.new(
3099
+ # {
3100
+ # "x" => [5.0, 4.0, Float::NAN, 2.0],
3101
+ # "y" => [5.0, 3.0, Float::NAN, 1.0]
3102
+ # }
3103
+ # )
3104
+ # df.with_columns(
3105
+ # Polars.col("x").ge(Polars.col("y")).alias("x >= y")
3106
+ # )
3107
+ # # =>
3108
+ # # shape: (4, 3)
3109
+ # # ┌─────┬─────┬────────┐
3110
+ # # │ x ┆ y ┆ x >= y │
3111
+ # # │ --- ┆ --- ┆ --- │
3112
+ # # │ f64 ┆ f64 ┆ bool │
3113
+ # # ╞═════╪═════╪════════╡
3114
+ # # │ 5.0 ┆ 5.0 ┆ true │
3115
+ # # │ 4.0 ┆ 3.0 ┆ true │
3116
+ # # │ NaN ┆ NaN ┆ true │
3117
+ # # │ 2.0 ┆ 1.0 ┆ true │
3118
+ # # └─────┴─────┴────────┘
3119
+ def ge(other)
3120
+ self >= other
3121
+ end
3122
+
3123
+ # Method equivalent of "greater than" operator `expr > other`.
3124
+ #
3125
+ # @param other [Object]
3126
+ # A literal or expression value to compare with.
3127
+ #
3128
+ # @return [Expr]
3129
+ #
3130
+ # @example
3131
+ # df = Polars::DataFrame.new(
3132
+ # {
3133
+ # "x" => [5.0, 4.0, Float::NAN, 2.0],
3134
+ # "y" => [5.0, 3.0, Float::NAN, 1.0]
3135
+ # }
3136
+ # )
3137
+ # df.with_columns(
3138
+ # Polars.col("x").gt(Polars.col("y")).alias("x > y")
3139
+ # )
3140
+ # # =>
3141
+ # # shape: (4, 3)
3142
+ # # ┌─────┬─────┬───────┐
3143
+ # # │ x ┆ y ┆ x > y │
3144
+ # # │ --- ┆ --- ┆ --- │
3145
+ # # │ f64 ┆ f64 ┆ bool │
3146
+ # # ╞═════╪═════╪═══════╡
3147
+ # # │ 5.0 ┆ 5.0 ┆ false │
3148
+ # # │ 4.0 ┆ 3.0 ┆ true │
3149
+ # # │ NaN ┆ NaN ┆ false │
3150
+ # # │ 2.0 ┆ 1.0 ┆ true │
3151
+ # # └─────┴─────┴───────┘
3152
+ def gt(other)
3153
+ self > other
3154
+ end
3155
+
3156
+ # Method equivalent of "less than or equal" operator `expr <= other`.
3157
+ #
3158
+ # @param other [Object]
3159
+ # A literal or expression value to compare with.
3160
+ #
3161
+ # @return [Expr]
3162
+ #
3163
+ # @example
3164
+ # df = Polars::DataFrame.new(
3165
+ # {
3166
+ # "x" => [5.0, 4.0, Float::NAN, 0.5],
3167
+ # "y" => [5.0, 3.5, Float::NAN, 2.0]
3168
+ # }
3169
+ # )
3170
+ # df.with_columns(
3171
+ # Polars.col("x").le(Polars.col("y")).alias("x <= y")
3172
+ # )
3173
+ # # =>
3174
+ # # shape: (4, 3)
3175
+ # # ┌─────┬─────┬────────┐
3176
+ # # │ x ┆ y ┆ x <= y │
3177
+ # # │ --- ┆ --- ┆ --- │
3178
+ # # │ f64 ┆ f64 ┆ bool │
3179
+ # # ╞═════╪═════╪════════╡
3180
+ # # │ 5.0 ┆ 5.0 ┆ true │
3181
+ # # │ 4.0 ┆ 3.5 ┆ false │
3182
+ # # │ NaN ┆ NaN ┆ true │
3183
+ # # │ 0.5 ┆ 2.0 ┆ true │
3184
+ # # └─────┴─────┴────────┘
3185
+ def le(other)
3186
+ self <= other
3187
+ end
3188
+
3189
+ # Method equivalent of "less than" operator `expr < other`.
3190
+ #
3191
+ # @param other [Object]
3192
+ # A literal or expression value to compare with.
3193
+ #
3194
+ # @return [Expr]
3195
+ #
3196
+ # @example
3197
+ # df = Polars::DataFrame.new(
3198
+ # {
3199
+ # "x" => [1.0, 2.0, Float::NAN, 3.0],
3200
+ # "y" => [2.0, 2.0, Float::NAN, 4.0]
3201
+ # }
3202
+ # )
3203
+ # df.with_columns(
3204
+ # Polars.col("x").lt(Polars.col("y")).alias("x < y"),
3205
+ # )
3206
+ # # =>
3207
+ # # shape: (4, 3)
3208
+ # # ┌─────┬─────┬───────┐
3209
+ # # │ x ┆ y ┆ x < y │
3210
+ # # │ --- ┆ --- ┆ --- │
3211
+ # # │ f64 ┆ f64 ┆ bool │
3212
+ # # ╞═════╪═════╪═══════╡
3213
+ # # │ 1.0 ┆ 2.0 ┆ true │
3214
+ # # │ 2.0 ┆ 2.0 ┆ false │
3215
+ # # │ NaN ┆ NaN ┆ false │
3216
+ # # │ 3.0 ┆ 4.0 ┆ true │
3217
+ # # └─────┴─────┴───────┘
3218
+ def lt(other)
3219
+ self < other
3220
+ end
3221
+
3222
+ # Method equivalent of inequality operator `expr != other`.
3223
+ #
3224
+ # @param other [Object]
3225
+ # A literal or expression value to compare with.
3226
+ #
3227
+ # @return [Expr]
3228
+ #
3229
+ # @example
3230
+ # df = Polars::DataFrame.new(
3231
+ # {
3232
+ # "x" => [1.0, 2.0, Float::NAN, 4.0],
3233
+ # "y" => [2.0, 2.0, Float::NAN, 4.0]
3234
+ # }
3235
+ # )
3236
+ # df.with_columns(
3237
+ # Polars.col("x").ne(Polars.col("y")).alias("x != y"),
3238
+ # )
3239
+ # # =>
3240
+ # # shape: (4, 3)
3241
+ # # ┌─────┬─────┬────────┐
3242
+ # # │ x ┆ y ┆ x != y │
3243
+ # # │ --- ┆ --- ┆ --- │
3244
+ # # │ f64 ┆ f64 ┆ bool │
3245
+ # # ╞═════╪═════╪════════╡
3246
+ # # │ 1.0 ┆ 2.0 ┆ true │
3247
+ # # │ 2.0 ┆ 2.0 ┆ false │
3248
+ # # │ NaN ┆ NaN ┆ false │
3249
+ # # │ 4.0 ┆ 4.0 ┆ false │
3250
+ # # └─────┴─────┴────────┘
3251
+ def ne(other)
3252
+ self != other
3253
+ end
3254
+
3255
+ # Method equivalent of equality operator `expr != other` where `None == None`.
3256
+ #
3257
+ # This differs from default `ne` where null values are propagated.
3258
+ #
3259
+ # @param other [Object]
3260
+ # A literal or expression value to compare with.
3261
+ #
3262
+ # @return [Expr]
3263
+ #
3264
+ # @example
3265
+ # df = Polars::DataFrame.new(
3266
+ # {
3267
+ # "x" => [1.0, 2.0, Float::NAN, 4.0, nil, nil],
3268
+ # "y" => [2.0, 2.0, Float::NAN, 4.0, 5.0, nil]
3269
+ # }
3270
+ # )
3271
+ # df.with_columns(
3272
+ # Polars.col("x").ne(Polars.col("y")).alias("x ne y"),
3273
+ # Polars.col("x").ne_missing(Polars.col("y")).alias("x ne_missing y")
3274
+ # )
3275
+ # # =>
3276
+ # # shape: (6, 4)
3277
+ # # ┌──────┬──────┬────────┬────────────────┐
3278
+ # # │ x ┆ y ┆ x ne y ┆ x ne_missing y │
3279
+ # # │ --- ┆ --- ┆ --- ┆ --- │
3280
+ # # │ f64 ┆ f64 ┆ bool ┆ bool │
3281
+ # # ╞══════╪══════╪════════╪════════════════╡
3282
+ # # │ 1.0 ┆ 2.0 ┆ true ┆ true │
3283
+ # # │ 2.0 ┆ 2.0 ┆ false ┆ false │
3284
+ # # │ NaN ┆ NaN ┆ false ┆ false │
3285
+ # # │ 4.0 ┆ 4.0 ┆ false ┆ false │
3286
+ # # │ null ┆ 5.0 ┆ null ┆ true │
3287
+ # # │ null ┆ null ┆ null ┆ false │
3288
+ # # └──────┴──────┴────────┴────────────────┘
3289
+ def ne_missing(other)
3290
+ other = Utils.parse_as_expression(other, str_as_lit: true)
3291
+ _from_rbexpr(_rbexpr.neq_missing(other))
3292
+ end
3293
+
3294
+ # Method equivalent of addition operator `expr + other`.
3295
+ #
3296
+ # @param other [Object]
3297
+ # numeric or string value; accepts expression input.
3298
+ #
3299
+ # @return [Expr]
3300
+ #
3301
+ # @example
3302
+ # df = Polars::DataFrame.new({"x" => [1, 2, 3, 4, 5]})
3303
+ # df.with_columns(
3304
+ # Polars.col("x").add(2).alias("x+int"),
3305
+ # Polars.col("x").add(Polars.col("x").cum_prod).alias("x+expr")
3306
+ # )
3307
+ # # =>
3308
+ # # shape: (5, 3)
3309
+ # # ┌─────┬───────┬────────┐
3310
+ # # │ x ┆ x+int ┆ x+expr │
3311
+ # # │ --- ┆ --- ┆ --- │
3312
+ # # │ i64 ┆ i64 ┆ i64 │
3313
+ # # ╞═════╪═══════╪════════╡
3314
+ # # │ 1 ┆ 3 ┆ 2 │
3315
+ # # │ 2 ┆ 4 ┆ 4 │
3316
+ # # │ 3 ┆ 5 ┆ 9 │
3317
+ # # │ 4 ┆ 6 ┆ 28 │
3318
+ # # │ 5 ┆ 7 ┆ 125 │
3319
+ # # └─────┴───────┴────────┘
3320
+ #
3321
+ # @example
3322
+ # df = Polars::DataFrame.new(
3323
+ # {"x" => ["a", "d", "g"], "y": ["b", "e", "h"], "z": ["c", "f", "i"]}
3324
+ # )
3325
+ # df.with_columns(Polars.col("x").add(Polars.col("y")).add(Polars.col("z")).alias("xyz"))
3326
+ # # =>
3327
+ # # shape: (3, 4)
3328
+ # # ┌─────┬─────┬─────┬─────┐
3329
+ # # │ x ┆ y ┆ z ┆ xyz │
3330
+ # # │ --- ┆ --- ┆ --- ┆ --- │
3331
+ # # │ str ┆ str ┆ str ┆ str │
3332
+ # # ╞═════╪═════╪═════╪═════╡
3333
+ # # │ a ┆ b ┆ c ┆ abc │
3334
+ # # │ d ┆ e ┆ f ┆ def │
3335
+ # # │ g ┆ h ┆ i ┆ ghi │
3336
+ # # └─────┴─────┴─────┴─────┘
3337
+ def add(other)
3338
+ self + other
3339
+ end
3340
+
3341
+ # Method equivalent of integer division operator `expr // other`.
3342
+ #
3343
+ # @param other [Object]
3344
+ # Numeric literal or expression value.
3345
+ #
3346
+ # @return [Expr]
3347
+ #
3348
+ # @example
3349
+ # df = Polars::DataFrame.new({"x" => [1, 2, 3, 4, 5]})
3350
+ # df.with_columns(
3351
+ # Polars.col("x").truediv(2).alias("x/2"),
3352
+ # Polars.col("x").floordiv(2).alias("x//2")
3353
+ # )
3354
+ # # =>
3355
+ # # shape: (5, 3)
3356
+ # # ┌─────┬─────┬──────┐
3357
+ # # │ x ┆ x/2 ┆ x//2 │
3358
+ # # │ --- ┆ --- ┆ --- │
3359
+ # # │ i64 ┆ f64 ┆ i64 │
3360
+ # # ╞═════╪═════╪══════╡
3361
+ # # │ 1 ┆ 0.5 ┆ 0 │
3362
+ # # │ 2 ┆ 1.0 ┆ 1 │
3363
+ # # │ 3 ┆ 1.5 ┆ 1 │
3364
+ # # │ 4 ┆ 2.0 ┆ 2 │
3365
+ # # │ 5 ┆ 2.5 ┆ 2 │
3366
+ # # └─────┴─────┴──────┘
3367
+ def floordiv(other)
3368
+ _from_rbexpr(_rbexpr.floordiv(_to_rbexpr(other)))
3369
+ end
3370
+
3371
+ # Method equivalent of modulus operator `expr % other`.
3372
+ #
3373
+ # @param other [Object]
3374
+ # Numeric literal or expression value.
3375
+ #
3376
+ # @return [Expr]
3377
+ #
3378
+ # @example
3379
+ # df = Polars::DataFrame.new({"x" => [0, 1, 2, 3, 4]})
3380
+ # df.with_columns(Polars.col("x").mod(2).alias("x%2"))
3381
+ # # =>
3382
+ # # shape: (5, 2)
3383
+ # # ┌─────┬─────┐
3384
+ # # │ x ┆ x%2 │
3385
+ # # │ --- ┆ --- │
3386
+ # # │ i64 ┆ i64 │
3387
+ # # ╞═════╪═════╡
3388
+ # # │ 0 ┆ 0 │
3389
+ # # │ 1 ┆ 1 │
3390
+ # # │ 2 ┆ 0 │
3391
+ # # │ 3 ┆ 1 │
3392
+ # # │ 4 ┆ 0 │
3393
+ # # └─────┴─────┘
3394
+ def mod(other)
3395
+ self % other
3396
+ end
3397
+
3398
+ # Method equivalent of multiplication operator `expr * other`.
3399
+ #
3400
+ # @param other [Object]
3401
+ # Numeric literal or expression value.
3402
+ #
3403
+ # @return [Expr]
3404
+ #
3405
+ # @example
3406
+ # df = Polars::DataFrame.new({"x" => [1, 2, 4, 8, 16]})
3407
+ # df.with_columns(
3408
+ # Polars.col("x").mul(2).alias("x*2"),
3409
+ # Polars.col("x").mul(Polars.col("x").log(2)).alias("x * xlog2"),
3410
+ # )
3411
+ # # =>
3412
+ # # shape: (5, 3)
3413
+ # # ┌─────┬─────┬───────────┐
3414
+ # # │ x ┆ x*2 ┆ x * xlog2 │
3415
+ # # │ --- ┆ --- ┆ --- │
3416
+ # # │ i64 ┆ i64 ┆ f64 │
3417
+ # # ╞═════╪═════╪═══════════╡
3418
+ # # │ 1 ┆ 2 ┆ 0.0 │
3419
+ # # │ 2 ┆ 4 ┆ 2.0 │
3420
+ # # │ 4 ┆ 8 ┆ 8.0 │
3421
+ # # │ 8 ┆ 16 ┆ 24.0 │
3422
+ # # │ 16 ┆ 32 ┆ 64.0 │
3423
+ # # └─────┴─────┴───────────┘
3424
+ def mul(other)
3425
+ self * other
3426
+ end
3427
+
3428
+ # Method equivalent of subtraction operator `expr - other`.
3429
+ #
3430
+ # @param other [Object]
3431
+ # Numeric literal or expression value.
3432
+ #
3433
+ # @return [Expr]
3434
+ #
3435
+ # @example
3436
+ # df = Polars::DataFrame.new({"x" => [0, 1, 2, 3, 4]})
3437
+ # df.with_columns(
3438
+ # Polars.col("x").sub(2).alias("x-2"),
3439
+ # Polars.col("x").sub(Polars.col("x").cum_sum).alias("x-expr"),
3440
+ # )
3441
+ # # =>
3442
+ # # shape: (5, 3)
3443
+ # # ┌─────┬─────┬────────┐
3444
+ # # │ x ┆ x-2 ┆ x-expr │
3445
+ # # │ --- ┆ --- ┆ --- │
3446
+ # # │ i64 ┆ i64 ┆ i64 │
3447
+ # # ╞═════╪═════╪════════╡
3448
+ # # │ 0 ┆ -2 ┆ 0 │
3449
+ # # │ 1 ┆ -1 ┆ 0 │
3450
+ # # │ 2 ┆ 0 ┆ -1 │
3451
+ # # │ 3 ┆ 1 ┆ -3 │
3452
+ # # │ 4 ┆ 2 ┆ -6 │
3453
+ # # └─────┴─────┴────────┘
3454
+ def sub(other)
3455
+ self - other
3456
+ end
3457
+
3458
+ # Method equivalent of unary minus operator `-expr`.
3459
+ #
3460
+ # @return [Expr]
3461
+ #
3462
+ # @example
3463
+ # df = Polars::DataFrame.new({"a" => [-1, 0, 2, nil]})
3464
+ # df.with_columns(Polars.col("a").neg)
3465
+ # # =>
3466
+ # # shape: (4, 1)
3467
+ # # ┌──────┐
3468
+ # # │ a │
3469
+ # # │ --- │
3470
+ # # │ i64 │
3471
+ # # ╞══════╡
3472
+ # # │ 1 │
3473
+ # # │ 0 │
3474
+ # # │ -2 │
3475
+ # # │ null │
3476
+ # # └──────┘
3477
+ def neg
3478
+ -self
3479
+ end
3480
+
3481
+ # Method equivalent of float division operator `expr / other`.
3482
+ #
3483
+ # @param other [Object]
3484
+ # Numeric literal or expression value.
3485
+ #
3486
+ # @return [Expr]
3487
+ #
3488
+ # @example
3489
+ # df = Polars::DataFrame.new(
3490
+ # {"x" => [-2, -1, 0, 1, 2], "y" => [0.5, 0.0, 0.0, -4.0, -0.5]}
3491
+ # )
3492
+ # df.with_columns(
3493
+ # Polars.col("x").truediv(2).alias("x/2"),
3494
+ # Polars.col("x").truediv(Polars.col("y")).alias("x/y")
3495
+ # )
3496
+ # # =>
3497
+ # # shape: (5, 4)
3498
+ # # ┌─────┬──────┬──────┬───────┐
3499
+ # # │ x ┆ y ┆ x/2 ┆ x/y │
3500
+ # # │ --- ┆ --- ┆ --- ┆ --- │
3501
+ # # │ i64 ┆ f64 ┆ f64 ┆ f64 │
3502
+ # # ╞═════╪══════╪══════╪═══════╡
3503
+ # # │ -2 ┆ 0.5 ┆ -1.0 ┆ -4.0 │
3504
+ # # │ -1 ┆ 0.0 ┆ -0.5 ┆ -inf │
3505
+ # # │ 0 ┆ 0.0 ┆ 0.0 ┆ NaN │
3506
+ # # │ 1 ┆ -4.0 ┆ 0.5 ┆ -0.25 │
3507
+ # # │ 2 ┆ -0.5 ┆ 1.0 ┆ -4.0 │
3508
+ # # └─────┴──────┴──────┴───────┘
3509
+ def truediv(other)
3510
+ self / other
3511
+ end
3512
+
2821
3513
  # Raise expression to the power of exponent.
2822
3514
  #
2823
3515
  # @return [Expr]
@@ -2838,8 +3530,35 @@ module Polars
2838
3530
  # # │ 64.0 │
2839
3531
  # # └──────┘
2840
3532
  def pow(exponent)
2841
- exponent = Utils.expr_to_lit_or_expr(exponent)
2842
- wrap_expr(_rbexpr.pow(exponent._rbexpr))
3533
+ self**exponent
3534
+ end
3535
+
3536
+ # Method equivalent of bitwise exclusive-or operator `expr ^ other`.
3537
+ #
3538
+ # @param other [Object]
3539
+ # Integer or boolean value; accepts expression input.
3540
+ #
3541
+ # @return [Expr]
3542
+ #
3543
+ # @example
3544
+ # df = Polars::DataFrame.new(
3545
+ # {"x" => [true, false, true, false], "y" => [true, true, false, false]}
3546
+ # )
3547
+ # df.with_columns(Polars.col("x").xor(Polars.col("y")).alias("x ^ y"))
3548
+ # # =>
3549
+ # # shape: (4, 3)
3550
+ # # ┌───────┬───────┬───────┐
3551
+ # # │ x ┆ y ┆ x ^ y │
3552
+ # # │ --- ┆ --- ┆ --- │
3553
+ # # │ bool ┆ bool ┆ bool │
3554
+ # # ╞═══════╪═══════╪═══════╡
3555
+ # # │ true ┆ true ┆ false │
3556
+ # # │ false ┆ true ┆ true │
3557
+ # # │ true ┆ false ┆ true │
3558
+ # # │ false ┆ false ┆ false │
3559
+ # # └───────┴───────┴───────┘
3560
+ def xor(other)
3561
+ self ^ other
2843
3562
  end
2844
3563
 
2845
3564
  # Check if elements of this expression are present in the other Series.
@@ -2875,7 +3594,7 @@ module Polars
2875
3594
  else
2876
3595
  other = Utils.expr_to_lit_or_expr(other, str_to_lit: false)
2877
3596
  end
2878
- wrap_expr(_rbexpr.is_in(other._rbexpr))
3597
+ _from_rbexpr(_rbexpr.is_in(other._rbexpr))
2879
3598
  end
2880
3599
  alias_method :in?, :is_in
2881
3600
 
@@ -2911,7 +3630,7 @@ module Polars
2911
3630
  # # └─────────────────┘
2912
3631
  def repeat_by(by)
2913
3632
  by = Utils.expr_to_lit_or_expr(by, str_to_lit: false)
2914
- wrap_expr(_rbexpr.repeat_by(by._rbexpr))
3633
+ _from_rbexpr(_rbexpr.repeat_by(by._rbexpr))
2915
3634
  end
2916
3635
 
2917
3636
  # Check if this expression is between start and end.
@@ -3037,7 +3756,7 @@ module Polars
3037
3756
  k1 = seed_1.nil? ? seed : seed_1
3038
3757
  k2 = seed_2.nil? ? seed : seed_2
3039
3758
  k3 = seed_3.nil? ? seed : seed_3
3040
- wrap_expr(_rbexpr._hash(k0, k1, k2, k3))
3759
+ _from_rbexpr(_rbexpr._hash(k0, k1, k2, k3))
3041
3760
  end
3042
3761
 
3043
3762
  # Reinterpret the underlying bits as a signed/unsigned integer.
@@ -3071,7 +3790,7 @@ module Polars
3071
3790
  # # │ 2 ┆ 2 │
3072
3791
  # # └───────────────┴──────────┘
3073
3792
  def reinterpret(signed: false)
3074
- wrap_expr(_rbexpr.reinterpret(signed))
3793
+ _from_rbexpr(_rbexpr.reinterpret(signed))
3075
3794
  end
3076
3795
 
3077
3796
  # Print the value that this expression evaluates to and pass on the value.
@@ -3134,7 +3853,7 @@ module Polars
3134
3853
  # # │ 3.0 ┆ 3.0 │
3135
3854
  # # └─────┴─────┘
3136
3855
  def interpolate(method: "linear")
3137
- wrap_expr(_rbexpr.interpolate(method))
3856
+ _from_rbexpr(_rbexpr.interpolate(method))
3138
3857
  end
3139
3858
 
3140
3859
  # Apply a rolling min (moving min) over the values in this array.
@@ -3219,7 +3938,7 @@ module Polars
3219
3938
  window_size, min_periods = _prepare_rolling_window_args(
3220
3939
  window_size, min_periods
3221
3940
  )
3222
- wrap_expr(
3941
+ _from_rbexpr(
3223
3942
  _rbexpr.rolling_min(
3224
3943
  window_size, weights, min_periods, center, by, closed
3225
3944
  )
@@ -3308,7 +4027,7 @@ module Polars
3308
4027
  window_size, min_periods = _prepare_rolling_window_args(
3309
4028
  window_size, min_periods
3310
4029
  )
3311
- wrap_expr(
4030
+ _from_rbexpr(
3312
4031
  _rbexpr.rolling_max(
3313
4032
  window_size, weights, min_periods, center, by, closed
3314
4033
  )
@@ -3397,7 +4116,7 @@ module Polars
3397
4116
  window_size, min_periods = _prepare_rolling_window_args(
3398
4117
  window_size, min_periods
3399
4118
  )
3400
- wrap_expr(
4119
+ _from_rbexpr(
3401
4120
  _rbexpr.rolling_mean(
3402
4121
  window_size, weights, min_periods, center, by, closed
3403
4122
  )
@@ -3486,7 +4205,7 @@ module Polars
3486
4205
  window_size, min_periods = _prepare_rolling_window_args(
3487
4206
  window_size, min_periods
3488
4207
  )
3489
- wrap_expr(
4208
+ _from_rbexpr(
3490
4209
  _rbexpr.rolling_sum(
3491
4210
  window_size, weights, min_periods, center, by, closed
3492
4211
  )
@@ -3571,14 +4290,15 @@ module Polars
3571
4290
  center: false,
3572
4291
  by: nil,
3573
4292
  closed: "left",
3574
- ddof: 1
4293
+ ddof: 1,
4294
+ warn_if_unsorted: true
3575
4295
  )
3576
4296
  window_size, min_periods = _prepare_rolling_window_args(
3577
4297
  window_size, min_periods
3578
4298
  )
3579
- wrap_expr(
4299
+ _from_rbexpr(
3580
4300
  _rbexpr.rolling_std(
3581
- window_size, weights, min_periods, center, by, closed, ddof
4301
+ window_size, weights, min_periods, center, by, closed, ddof, warn_if_unsorted
3582
4302
  )
3583
4303
  )
3584
4304
  end
@@ -3661,14 +4381,15 @@ module Polars
3661
4381
  center: false,
3662
4382
  by: nil,
3663
4383
  closed: "left",
3664
- ddof: 1
4384
+ ddof: 1,
4385
+ warn_if_unsorted: true
3665
4386
  )
3666
4387
  window_size, min_periods = _prepare_rolling_window_args(
3667
4388
  window_size, min_periods
3668
4389
  )
3669
- wrap_expr(
4390
+ _from_rbexpr(
3670
4391
  _rbexpr.rolling_var(
3671
- window_size, weights, min_periods, center, by, closed, ddof
4392
+ window_size, weights, min_periods, center, by, closed, ddof, warn_if_unsorted
3672
4393
  )
3673
4394
  )
3674
4395
  end
@@ -3746,14 +4467,15 @@ module Polars
3746
4467
  min_periods: nil,
3747
4468
  center: false,
3748
4469
  by: nil,
3749
- closed: "left"
4470
+ closed: "left",
4471
+ warn_if_unsorted: true
3750
4472
  )
3751
4473
  window_size, min_periods = _prepare_rolling_window_args(
3752
4474
  window_size, min_periods
3753
4475
  )
3754
- wrap_expr(
4476
+ _from_rbexpr(
3755
4477
  _rbexpr.rolling_median(
3756
- window_size, weights, min_periods, center, by, closed
4478
+ window_size, weights, min_periods, center, by, closed, warn_if_unsorted
3757
4479
  )
3758
4480
  )
3759
4481
  end
@@ -3837,14 +4559,15 @@ module Polars
3837
4559
  min_periods: nil,
3838
4560
  center: false,
3839
4561
  by: nil,
3840
- closed: "left"
4562
+ closed: "left",
4563
+ warn_if_unsorted: true
3841
4564
  )
3842
4565
  window_size, min_periods = _prepare_rolling_window_args(
3843
4566
  window_size, min_periods
3844
4567
  )
3845
- wrap_expr(
4568
+ _from_rbexpr(
3846
4569
  _rbexpr.rolling_quantile(
3847
- quantile, interpolation, window_size, weights, min_periods, center, by, closed
4570
+ quantile, interpolation, window_size, weights, min_periods, center, by, closed, warn_if_unsorted
3848
4571
  )
3849
4572
  )
3850
4573
  end
@@ -3906,7 +4629,7 @@ module Polars
3906
4629
  # if min_periods.nil?
3907
4630
  # min_periods = window_size
3908
4631
  # end
3909
- # wrap_expr(
4632
+ # _from_rbexpr(
3910
4633
  # _rbexpr.rolling_apply(
3911
4634
  # function, window_size, weights, min_periods, center
3912
4635
  # )
@@ -3922,7 +4645,7 @@ module Polars
3922
4645
  #
3923
4646
  # @return [Expr]
3924
4647
  def rolling_skew(window_size, bias: true)
3925
- wrap_expr(_rbexpr.rolling_skew(window_size, bias))
4648
+ _from_rbexpr(_rbexpr.rolling_skew(window_size, bias))
3926
4649
  end
3927
4650
 
3928
4651
  # Compute absolute values.
@@ -3949,7 +4672,7 @@ module Polars
3949
4672
  # # │ 2.0 │
3950
4673
  # # └─────┘
3951
4674
  def abs
3952
- wrap_expr(_rbexpr.abs)
4675
+ _from_rbexpr(_rbexpr.abs)
3953
4676
  end
3954
4677
 
3955
4678
  # Get the index values that would sort this column.
@@ -4044,7 +4767,7 @@ module Polars
4044
4767
  # # │ 5 │
4045
4768
  # # └─────┘
4046
4769
  def rank(method: "average", reverse: false, seed: nil)
4047
- wrap_expr(_rbexpr.rank(method, reverse, seed))
4770
+ _from_rbexpr(_rbexpr.rank(method, reverse, seed))
4048
4771
  end
4049
4772
 
4050
4773
  # Calculate the n-th discrete difference.
@@ -4075,7 +4798,7 @@ module Polars
4075
4798
  # # │ 20 │
4076
4799
  # # └──────┘
4077
4800
  def diff(n: 1, null_behavior: "ignore")
4078
- wrap_expr(_rbexpr.diff(n, null_behavior))
4801
+ _from_rbexpr(_rbexpr.diff(n, null_behavior))
4079
4802
  end
4080
4803
 
4081
4804
  # Computes percentage change between values.
@@ -4112,7 +4835,7 @@ module Polars
4112
4835
  # # └──────┴────────────┘
4113
4836
  def pct_change(n: 1)
4114
4837
  n = Utils.parse_as_expression(n)
4115
- wrap_expr(_rbexpr.pct_change(n))
4838
+ _from_rbexpr(_rbexpr.pct_change(n))
4116
4839
  end
4117
4840
 
4118
4841
  # Compute the sample skewness of a data set.
@@ -4141,7 +4864,7 @@ module Polars
4141
4864
  # # │ 0.343622 │
4142
4865
  # # └──────────┘
4143
4866
  def skew(bias: true)
4144
- wrap_expr(_rbexpr.skew(bias))
4867
+ _from_rbexpr(_rbexpr.skew(bias))
4145
4868
  end
4146
4869
 
4147
4870
  # Compute the kurtosis (Fisher or Pearson) of a dataset.
@@ -4173,7 +4896,7 @@ module Polars
4173
4896
  # # │ -1.153061 │
4174
4897
  # # └───────────┘
4175
4898
  def kurtosis(fisher: true, bias: true)
4176
- wrap_expr(_rbexpr.kurtosis(fisher, bias))
4899
+ _from_rbexpr(_rbexpr.kurtosis(fisher, bias))
4177
4900
  end
4178
4901
 
4179
4902
  # Set values outside the given boundaries to the boundary value.
@@ -4210,7 +4933,7 @@ module Polars
4210
4933
  if !upper_bound.nil?
4211
4934
  upper_bound = Utils.parse_as_expression(upper_bound, str_as_lit: true)
4212
4935
  end
4213
- wrap_expr(_rbexpr.clip(lower_bound, upper_bound))
4936
+ _from_rbexpr(_rbexpr.clip(lower_bound, upper_bound))
4214
4937
  end
4215
4938
 
4216
4939
  # Clip (limit) the values in an array to a `min` boundary.
@@ -4295,7 +5018,7 @@ module Polars
4295
5018
  # # │ -9223372036854775808 │
4296
5019
  # # └──────────────────────┘
4297
5020
  def lower_bound
4298
- wrap_expr(_rbexpr.lower_bound)
5021
+ _from_rbexpr(_rbexpr.lower_bound)
4299
5022
  end
4300
5023
 
4301
5024
  # Calculate the upper bound.
@@ -4318,7 +5041,7 @@ module Polars
4318
5041
  # # │ 9223372036854775807 │
4319
5042
  # # └─────────────────────┘
4320
5043
  def upper_bound
4321
- wrap_expr(_rbexpr.upper_bound)
5044
+ _from_rbexpr(_rbexpr.upper_bound)
4322
5045
  end
4323
5046
 
4324
5047
  # Compute the element-wise indication of the sign.
@@ -4342,7 +5065,7 @@ module Polars
4342
5065
  # # │ null │
4343
5066
  # # └──────┘
4344
5067
  def sign
4345
- wrap_expr(_rbexpr.sign)
5068
+ _from_rbexpr(_rbexpr.sign)
4346
5069
  end
4347
5070
 
4348
5071
  # Compute the element-wise value for the sine.
@@ -4362,7 +5085,7 @@ module Polars
4362
5085
  # # │ 0.0 │
4363
5086
  # # └─────┘
4364
5087
  def sin
4365
- wrap_expr(_rbexpr.sin)
5088
+ _from_rbexpr(_rbexpr.sin)
4366
5089
  end
4367
5090
 
4368
5091
  # Compute the element-wise value for the cosine.
@@ -4382,7 +5105,7 @@ module Polars
4382
5105
  # # │ 1.0 │
4383
5106
  # # └─────┘
4384
5107
  def cos
4385
- wrap_expr(_rbexpr.cos)
5108
+ _from_rbexpr(_rbexpr.cos)
4386
5109
  end
4387
5110
 
4388
5111
  # Compute the element-wise value for the tangent.
@@ -4402,7 +5125,7 @@ module Polars
4402
5125
  # # │ 1.557408 │
4403
5126
  # # └──────────┘
4404
5127
  def tan
4405
- wrap_expr(_rbexpr.tan)
5128
+ _from_rbexpr(_rbexpr.tan)
4406
5129
  end
4407
5130
 
4408
5131
  # Compute the element-wise value for the inverse sine.
@@ -4422,7 +5145,7 @@ module Polars
4422
5145
  # # │ 1.570796 │
4423
5146
  # # └──────────┘
4424
5147
  def arcsin
4425
- wrap_expr(_rbexpr.arcsin)
5148
+ _from_rbexpr(_rbexpr.arcsin)
4426
5149
  end
4427
5150
 
4428
5151
  # Compute the element-wise value for the inverse cosine.
@@ -4442,7 +5165,7 @@ module Polars
4442
5165
  # # │ 1.570796 │
4443
5166
  # # └──────────┘
4444
5167
  def arccos
4445
- wrap_expr(_rbexpr.arccos)
5168
+ _from_rbexpr(_rbexpr.arccos)
4446
5169
  end
4447
5170
 
4448
5171
  # Compute the element-wise value for the inverse tangent.
@@ -4462,7 +5185,7 @@ module Polars
4462
5185
  # # │ 0.785398 │
4463
5186
  # # └──────────┘
4464
5187
  def arctan
4465
- wrap_expr(_rbexpr.arctan)
5188
+ _from_rbexpr(_rbexpr.arctan)
4466
5189
  end
4467
5190
 
4468
5191
  # Compute the element-wise value for the hyperbolic sine.
@@ -4482,7 +5205,7 @@ module Polars
4482
5205
  # # │ 1.175201 │
4483
5206
  # # └──────────┘
4484
5207
  def sinh
4485
- wrap_expr(_rbexpr.sinh)
5208
+ _from_rbexpr(_rbexpr.sinh)
4486
5209
  end
4487
5210
 
4488
5211
  # Compute the element-wise value for the hyperbolic cosine.
@@ -4502,7 +5225,7 @@ module Polars
4502
5225
  # # │ 1.543081 │
4503
5226
  # # └──────────┘
4504
5227
  def cosh
4505
- wrap_expr(_rbexpr.cosh)
5228
+ _from_rbexpr(_rbexpr.cosh)
4506
5229
  end
4507
5230
 
4508
5231
  # Compute the element-wise value for the hyperbolic tangent.
@@ -4522,7 +5245,7 @@ module Polars
4522
5245
  # # │ 0.761594 │
4523
5246
  # # └──────────┘
4524
5247
  def tanh
4525
- wrap_expr(_rbexpr.tanh)
5248
+ _from_rbexpr(_rbexpr.tanh)
4526
5249
  end
4527
5250
 
4528
5251
  # Compute the element-wise value for the inverse hyperbolic sine.
@@ -4542,7 +5265,7 @@ module Polars
4542
5265
  # # │ 0.881374 │
4543
5266
  # # └──────────┘
4544
5267
  def arcsinh
4545
- wrap_expr(_rbexpr.arcsinh)
5268
+ _from_rbexpr(_rbexpr.arcsinh)
4546
5269
  end
4547
5270
 
4548
5271
  # Compute the element-wise value for the inverse hyperbolic cosine.
@@ -4562,7 +5285,7 @@ module Polars
4562
5285
  # # │ 0.0 │
4563
5286
  # # └─────┘
4564
5287
  def arccosh
4565
- wrap_expr(_rbexpr.arccosh)
5288
+ _from_rbexpr(_rbexpr.arccosh)
4566
5289
  end
4567
5290
 
4568
5291
  # Compute the element-wise value for the inverse hyperbolic tangent.
@@ -4582,7 +5305,7 @@ module Polars
4582
5305
  # # │ inf │
4583
5306
  # # └─────┘
4584
5307
  def arctanh
4585
- wrap_expr(_rbexpr.arctanh)
5308
+ _from_rbexpr(_rbexpr.arctanh)
4586
5309
  end
4587
5310
 
4588
5311
  # Reshape this Expr to a flat Series or a Series of Lists.
@@ -4608,7 +5331,7 @@ module Polars
4608
5331
  # # │ [7, 8, 9] │
4609
5332
  # # └───────────┘
4610
5333
  def reshape(dims)
4611
- wrap_expr(_rbexpr.reshape(dims))
5334
+ _from_rbexpr(_rbexpr.reshape(dims))
4612
5335
  end
4613
5336
 
4614
5337
  # Shuffle the contents of this expr.
@@ -4637,7 +5360,7 @@ module Polars
4637
5360
  if seed.nil?
4638
5361
  seed = rand(10000)
4639
5362
  end
4640
- wrap_expr(_rbexpr.shuffle(seed))
5363
+ _from_rbexpr(_rbexpr.shuffle(seed))
4641
5364
  end
4642
5365
 
4643
5366
  # Sample from this expression.
@@ -4683,14 +5406,14 @@ module Polars
4683
5406
 
4684
5407
  if !n.nil? && frac.nil?
4685
5408
  n = Utils.parse_as_expression(n)
4686
- return wrap_expr(_rbexpr.sample_n(n, with_replacement, shuffle, seed))
5409
+ return _from_rbexpr(_rbexpr.sample_n(n, with_replacement, shuffle, seed))
4687
5410
  end
4688
5411
 
4689
5412
  if frac.nil?
4690
5413
  frac = 1.0
4691
5414
  end
4692
5415
  frac = Utils.parse_as_expression(frac)
4693
- wrap_expr(
5416
+ _from_rbexpr(
4694
5417
  _rbexpr.sample_frac(frac, with_replacement, shuffle, seed)
4695
5418
  )
4696
5419
  end
@@ -4723,7 +5446,7 @@ module Polars
4723
5446
  ignore_nulls: true
4724
5447
  )
4725
5448
  alpha = _prepare_alpha(com, span, half_life, alpha)
4726
- wrap_expr(_rbexpr.ewm_mean(alpha, adjust, min_periods, ignore_nulls))
5449
+ _from_rbexpr(_rbexpr.ewm_mean(alpha, adjust, min_periods, ignore_nulls))
4727
5450
  end
4728
5451
 
4729
5452
  # Exponentially-weighted moving standard deviation.
@@ -4755,7 +5478,7 @@ module Polars
4755
5478
  ignore_nulls: true
4756
5479
  )
4757
5480
  alpha = _prepare_alpha(com, span, half_life, alpha)
4758
- wrap_expr(_rbexpr.ewm_std(alpha, adjust, bias, min_periods, ignore_nulls))
5481
+ _from_rbexpr(_rbexpr.ewm_std(alpha, adjust, bias, min_periods, ignore_nulls))
4759
5482
  end
4760
5483
 
4761
5484
  # Exponentially-weighted moving variance.
@@ -4787,7 +5510,7 @@ module Polars
4787
5510
  ignore_nulls: true
4788
5511
  )
4789
5512
  alpha = _prepare_alpha(com, span, half_life, alpha)
4790
- wrap_expr(_rbexpr.ewm_var(alpha, adjust, bias, min_periods, ignore_nulls))
5513
+ _from_rbexpr(_rbexpr.ewm_var(alpha, adjust, bias, min_periods, ignore_nulls))
4791
5514
  end
4792
5515
 
4793
5516
  # Extend the Series with given number of values.
@@ -4817,7 +5540,7 @@ module Polars
4817
5540
  # # │ 99 │
4818
5541
  # # └────────┘
4819
5542
  def extend_constant(value, n)
4820
- wrap_expr(_rbexpr.extend_constant(value, n))
5543
+ _from_rbexpr(_rbexpr.extend_constant(value, n))
4821
5544
  end
4822
5545
 
4823
5546
  # Count all unique values and create a struct mapping value to count.
@@ -4853,7 +5576,7 @@ module Polars
4853
5576
  # # │ {"a",1} │
4854
5577
  # # └───────────┘
4855
5578
  def value_counts(multithreaded: false, sort: false)
4856
- wrap_expr(_rbexpr.value_counts(multithreaded, sort))
5579
+ _from_rbexpr(_rbexpr.value_counts(multithreaded, sort))
4857
5580
  end
4858
5581
 
4859
5582
  # Return a count of the unique values in the order of appearance.
@@ -4886,7 +5609,7 @@ module Polars
4886
5609
  # # │ 3 │
4887
5610
  # # └─────┘
4888
5611
  def unique_counts
4889
- wrap_expr(_rbexpr.unique_counts)
5612
+ _from_rbexpr(_rbexpr.unique_counts)
4890
5613
  end
4891
5614
 
4892
5615
  # Compute the logarithm to a given base.
@@ -4911,7 +5634,7 @@ module Polars
4911
5634
  # # │ 1.584963 │
4912
5635
  # # └──────────┘
4913
5636
  def log(base = Math::E)
4914
- wrap_expr(_rbexpr.log(base))
5637
+ _from_rbexpr(_rbexpr.log(base))
4915
5638
  end
4916
5639
 
4917
5640
  # Computes the entropy.
@@ -4950,7 +5673,7 @@ module Polars
4950
5673
  # # │ -6.754888 │
4951
5674
  # # └───────────┘
4952
5675
  def entropy(base: 2, normalize: true)
4953
- wrap_expr(_rbexpr.entropy(base, normalize))
5676
+ _from_rbexpr(_rbexpr.entropy(base, normalize))
4954
5677
  end
4955
5678
 
4956
5679
  # Run an expression over a sliding window that increases `1` slot every iteration.
@@ -4997,7 +5720,7 @@ module Polars
4997
5720
  # # │ -24.0 │
4998
5721
  # # └────────┘
4999
5722
  def cumulative_eval(expr, min_periods: 1, parallel: false)
5000
- wrap_expr(
5723
+ _from_rbexpr(
5001
5724
  _rbexpr.cumulative_eval(expr._rbexpr, min_periods, parallel)
5002
5725
  )
5003
5726
  end
@@ -5028,7 +5751,7 @@ module Polars
5028
5751
  # # │ 3 │
5029
5752
  # # └────────┘
5030
5753
  def set_sorted(descending: false)
5031
- wrap_expr(_rbexpr.set_sorted_flag(descending))
5754
+ _from_rbexpr(_rbexpr.set_sorted_flag(descending))
5032
5755
  end
5033
5756
 
5034
5757
  # Aggregate to list.
@@ -5053,7 +5776,7 @@ module Polars
5053
5776
  # # │ [1, 2, 3] ┆ [4, 5, 6] │
5054
5777
  # # └───────────┴───────────┘
5055
5778
  def implode
5056
- wrap_expr(_rbexpr.implode)
5779
+ _from_rbexpr(_rbexpr.implode)
5057
5780
  end
5058
5781
 
5059
5782
  # Shrink numeric columns to the minimal required datatype.
@@ -5088,7 +5811,169 @@ module Polars
5088
5811
  # # │ 3 ┆ 8589934592 ┆ 1073741824 ┆ 112 ┆ 129 ┆ c ┆ 0.12 ┆ false │
5089
5812
  # # └─────┴────────────┴────────────┴──────┴──────┴─────┴──────┴───────┘
5090
5813
  def shrink_dtype
5091
- wrap_expr(_rbexpr.shrink_dtype)
5814
+ _from_rbexpr(_rbexpr.shrink_dtype)
5815
+ end
5816
+
5817
+ # Replace values by different values.
5818
+ #
5819
+ # @param old [Object]
5820
+ # Value or sequence of values to replace.
5821
+ # Accepts expression input. Sequences are parsed as Series,
5822
+ # other non-expression inputs are parsed as literals.
5823
+ # Also accepts a mapping of values to their replacement.
5824
+ # @param new [Object]
5825
+ # Value or sequence of values to replace by.
5826
+ # Accepts expression input. Sequences are parsed as Series,
5827
+ # other non-expression inputs are parsed as literals.
5828
+ # Length must match the length of `old` or have length 1.
5829
+ # @param default [Object]
5830
+ # Set values that were not replaced to this value.
5831
+ # Defaults to keeping the original value.
5832
+ # Accepts expression input. Non-expression inputs are parsed as literals.
5833
+ # @param return_dtype [Object]
5834
+ # The data type of the resulting expression. If set to `nil` (default),
5835
+ # the data type is determined automatically based on the other inputs.
5836
+ #
5837
+ # @return [Expr]
5838
+ #
5839
+ # @example Replace a single value by another value. Values that were not replaced remain unchanged.
5840
+ # df = Polars::DataFrame.new({"a" => [1, 2, 2, 3]})
5841
+ # df.with_columns(replaced: Polars.col("a").replace(2, 100))
5842
+ # # =>
5843
+ # # shape: (4, 2)
5844
+ # # ┌─────┬──────────┐
5845
+ # # │ a ┆ replaced │
5846
+ # # │ --- ┆ --- │
5847
+ # # │ i64 ┆ i64 │
5848
+ # # ╞═════╪══════════╡
5849
+ # # │ 1 ┆ 1 │
5850
+ # # │ 2 ┆ 100 │
5851
+ # # │ 2 ┆ 100 │
5852
+ # # │ 3 ┆ 3 │
5853
+ # # └─────┴──────────┘
5854
+ #
5855
+ # @example Replace multiple values by passing sequences to the `old` and `new` parameters.
5856
+ # df.with_columns(replaced: Polars.col("a").replace([2, 3], [100, 200]))
5857
+ # # =>
5858
+ # # shape: (4, 2)
5859
+ # # ┌─────┬──────────┐
5860
+ # # │ a ┆ replaced │
5861
+ # # │ --- ┆ --- │
5862
+ # # │ i64 ┆ i64 │
5863
+ # # ╞═════╪══════════╡
5864
+ # # │ 1 ┆ 1 │
5865
+ # # │ 2 ┆ 100 │
5866
+ # # │ 2 ┆ 100 │
5867
+ # # │ 3 ┆ 200 │
5868
+ # # └─────┴──────────┘
5869
+ #
5870
+ # @example Passing a mapping with replacements is also supported as syntactic sugar. Specify a default to set all values that were not matched.
5871
+ # mapping = {2 => 100, 3 => 200}
5872
+ # df.with_columns(replaced: Polars.col("a").replace(mapping, default: -1))
5873
+ # # =>
5874
+ # # shape: (4, 2)
5875
+ # # ┌─────┬──────────┐
5876
+ # # │ a ┆ replaced │
5877
+ # # │ --- ┆ --- │
5878
+ # # │ i64 ┆ i64 │
5879
+ # # ╞═════╪══════════╡
5880
+ # # │ 1 ┆ -1 │
5881
+ # # │ 2 ┆ 100 │
5882
+ # # │ 2 ┆ 100 │
5883
+ # # │ 3 ┆ 200 │
5884
+ # # └─────┴──────────┘
5885
+ #
5886
+ # @example Replacing by values of a different data type sets the return type based on a combination of the `new` data type and either the original data type or the default data type if it was set.
5887
+ # df = Polars::DataFrame.new({"a" => ["x", "y", "z"]})
5888
+ # mapping = {"x" => 1, "y" => 2, "z" => 3}
5889
+ # df.with_columns(replaced: Polars.col("a").replace(mapping))
5890
+ # # =>
5891
+ # # shape: (3, 2)
5892
+ # # ┌─────┬──────────┐
5893
+ # # │ a ┆ replaced │
5894
+ # # │ --- ┆ --- │
5895
+ # # │ str ┆ str │
5896
+ # # ╞═════╪══════════╡
5897
+ # # │ x ┆ 1 │
5898
+ # # │ y ┆ 2 │
5899
+ # # │ z ┆ 3 │
5900
+ # # └─────┴──────────┘
5901
+ #
5902
+ # @example
5903
+ # df.with_columns(replaced: Polars.col("a").replace(mapping, default: nil))
5904
+ # # =>
5905
+ # # shape: (3, 2)
5906
+ # # ┌─────┬──────────┐
5907
+ # # │ a ┆ replaced │
5908
+ # # │ --- ┆ --- │
5909
+ # # │ str ┆ i64 │
5910
+ # # ╞═════╪══════════╡
5911
+ # # │ x ┆ 1 │
5912
+ # # │ y ┆ 2 │
5913
+ # # │ z ┆ 3 │
5914
+ # # └─────┴──────────┘
5915
+ #
5916
+ # @example Set the `return_dtype` parameter to control the resulting data type directly.
5917
+ # df.with_columns(
5918
+ # replaced: Polars.col("a").replace(mapping, return_dtype: Polars::UInt8)
5919
+ # )
5920
+ # # =>
5921
+ # # shape: (3, 2)
5922
+ # # ┌─────┬──────────┐
5923
+ # # │ a ┆ replaced │
5924
+ # # │ --- ┆ --- │
5925
+ # # │ str ┆ u8 │
5926
+ # # ╞═════╪══════════╡
5927
+ # # │ x ┆ 1 │
5928
+ # # │ y ┆ 2 │
5929
+ # # │ z ┆ 3 │
5930
+ # # └─────┴──────────┘
5931
+ #
5932
+ # @example Expression input is supported for all parameters.
5933
+ # df = Polars::DataFrame.new({"a" => [1, 2, 2, 3], "b" => [1.5, 2.5, 5.0, 1.0]})
5934
+ # df.with_columns(
5935
+ # replaced: Polars.col("a").replace(
5936
+ # Polars.col("a").max,
5937
+ # Polars.col("b").sum,
5938
+ # default: Polars.col("b")
5939
+ # )
5940
+ # )
5941
+ # # =>
5942
+ # # shape: (4, 3)
5943
+ # # ┌─────┬─────┬──────────┐
5944
+ # # │ a ┆ b ┆ replaced │
5945
+ # # │ --- ┆ --- ┆ --- │
5946
+ # # │ i64 ┆ f64 ┆ f64 │
5947
+ # # ╞═════╪═════╪══════════╡
5948
+ # # │ 1 ┆ 1.5 ┆ 1.5 │
5949
+ # # │ 2 ┆ 2.5 ┆ 2.5 │
5950
+ # # │ 2 ┆ 5.0 ┆ 5.0 │
5951
+ # # │ 3 ┆ 1.0 ┆ 10.0 │
5952
+ # # └─────┴─────┴──────────┘
5953
+ def replace(old, new = NO_DEFAULT, default: NO_DEFAULT, return_dtype: nil)
5954
+ if new.eql?(NO_DEFAULT) && old.is_a?(Hash)
5955
+ new = Series.new(old.values)
5956
+ old = Series.new(old.keys)
5957
+ else
5958
+ if old.is_a?(::Array)
5959
+ old = Series.new(old)
5960
+ end
5961
+ if new.is_a?(::Array)
5962
+ new = Series.new(new)
5963
+ end
5964
+ end
5965
+
5966
+ old = Utils.parse_as_expression(old, str_as_lit: true)
5967
+ new = Utils.parse_as_expression(new, str_as_lit: true)
5968
+
5969
+ default =
5970
+ if default.eql?(NO_DEFAULT)
5971
+ nil
5972
+ else
5973
+ Utils.parse_as_expression(default, str_as_lit: true)
5974
+ end
5975
+
5976
+ _from_rbexpr(_rbexpr.replace(old, new, default, return_dtype))
5092
5977
  end
5093
5978
 
5094
5979
  # Create an object namespace of all list related methods.
@@ -5156,7 +6041,7 @@ module Polars
5156
6041
 
5157
6042
  private
5158
6043
 
5159
- def wrap_expr(expr)
6044
+ def _from_rbexpr(expr)
5160
6045
  Utils.wrap_expr(expr)
5161
6046
  end
5162
6047