polars-df 0.7.0-x86_64-linux → 0.9.0-x86_64-linux

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 (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 +1978 -1459
  6. data/LICENSE.txt +1 -1
  7. data/README.md +2 -2
  8. data/lib/polars/3.1/polars.so +0 -0
  9. data/lib/polars/3.2/polars.so +0 -0
  10. data/lib/polars/{3.0 → 3.3}/polars.so +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