polars-df 0.21.0 → 0.21.1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Cargo.lock +1 -1
  4. data/ext/polars/Cargo.toml +7 -1
  5. data/ext/polars/src/conversion/mod.rs +92 -4
  6. data/ext/polars/src/exceptions.rs +1 -0
  7. data/ext/polars/src/expr/array.rs +73 -4
  8. data/ext/polars/src/expr/binary.rs +26 -1
  9. data/ext/polars/src/expr/bitwise.rs +39 -0
  10. data/ext/polars/src/expr/categorical.rs +20 -0
  11. data/ext/polars/src/expr/datatype.rs +24 -1
  12. data/ext/polars/src/expr/datetime.rs +58 -0
  13. data/ext/polars/src/expr/general.rs +84 -5
  14. data/ext/polars/src/expr/list.rs +24 -0
  15. data/ext/polars/src/expr/meta.rs +11 -0
  16. data/ext/polars/src/expr/mod.rs +1 -0
  17. data/ext/polars/src/expr/name.rs +8 -0
  18. data/ext/polars/src/expr/rolling.rs +20 -0
  19. data/ext/polars/src/expr/string.rs +59 -0
  20. data/ext/polars/src/expr/struct.rs +9 -1
  21. data/ext/polars/src/functions/io.rs +19 -0
  22. data/ext/polars/src/functions/lazy.rs +4 -0
  23. data/ext/polars/src/lazyframe/general.rs +51 -0
  24. data/ext/polars/src/lib.rs +119 -10
  25. data/ext/polars/src/map/dataframe.rs +2 -2
  26. data/ext/polars/src/map/series.rs +1 -1
  27. data/ext/polars/src/series/aggregation.rs +44 -0
  28. data/ext/polars/src/series/general.rs +64 -4
  29. data/lib/polars/array_expr.rb +382 -3
  30. data/lib/polars/array_name_space.rb +281 -0
  31. data/lib/polars/binary_expr.rb +67 -0
  32. data/lib/polars/binary_name_space.rb +43 -0
  33. data/lib/polars/cat_expr.rb +224 -0
  34. data/lib/polars/cat_name_space.rb +138 -0
  35. data/lib/polars/config.rb +2 -2
  36. data/lib/polars/convert.rb +6 -6
  37. data/lib/polars/data_frame.rb +684 -19
  38. data/lib/polars/data_type_expr.rb +52 -0
  39. data/lib/polars/data_types.rb +14 -2
  40. data/lib/polars/date_time_expr.rb +251 -0
  41. data/lib/polars/date_time_name_space.rb +299 -0
  42. data/lib/polars/expr.rb +1213 -180
  43. data/lib/polars/functions/datatype.rb +21 -0
  44. data/lib/polars/functions/lazy.rb +13 -0
  45. data/lib/polars/io/csv.rb +1 -1
  46. data/lib/polars/io/json.rb +4 -4
  47. data/lib/polars/io/ndjson.rb +4 -4
  48. data/lib/polars/io/parquet.rb +27 -5
  49. data/lib/polars/lazy_frame.rb +936 -20
  50. data/lib/polars/list_expr.rb +196 -4
  51. data/lib/polars/list_name_space.rb +201 -4
  52. data/lib/polars/meta_expr.rb +64 -0
  53. data/lib/polars/name_expr.rb +36 -0
  54. data/lib/polars/schema.rb +79 -3
  55. data/lib/polars/selector.rb +72 -0
  56. data/lib/polars/selectors.rb +3 -3
  57. data/lib/polars/series.rb +1051 -54
  58. data/lib/polars/string_expr.rb +411 -6
  59. data/lib/polars/string_name_space.rb +722 -49
  60. data/lib/polars/struct_expr.rb +103 -0
  61. data/lib/polars/struct_name_space.rb +19 -1
  62. data/lib/polars/utils/various.rb +18 -1
  63. data/lib/polars/utils.rb +5 -1
  64. data/lib/polars/version.rb +1 -1
  65. data/lib/polars.rb +2 -0
  66. metadata +4 -1
data/lib/polars/expr.rb CHANGED
@@ -26,56 +26,59 @@ module Polars
26
26
  #
27
27
  # @return [Expr]
28
28
  def ^(other)
29
- _from_rbexpr(_rbexpr._xor(_to_rbexpr(other)))
29
+ other = Utils.parse_into_expression(other)
30
+ wrap_expr(_rbexpr.xor_(other))
30
31
  end
31
32
 
32
33
  # Bitwise AND.
33
34
  #
34
35
  # @return [Expr]
35
36
  def &(other)
36
- _from_rbexpr(_rbexpr._and(_to_rbexpr(other)))
37
+ other = Utils.parse_into_expression(other)
38
+ wrap_expr(_rbexpr.and_(other))
37
39
  end
38
40
 
39
41
  # Bitwise OR.
40
42
  #
41
43
  # @return [Expr]
42
44
  def |(other)
43
- _from_rbexpr(_rbexpr._or(_to_rbexpr(other)))
45
+ other = Utils.parse_into_expression(other)
46
+ wrap_expr(_rbexpr.or_(other))
44
47
  end
45
48
 
46
49
  # Performs addition.
47
50
  #
48
51
  # @return [Expr]
49
52
  def +(other)
50
- _from_rbexpr(_rbexpr + _to_rbexpr(other))
53
+ wrap_expr(_rbexpr + _to_rbexpr(other))
51
54
  end
52
55
 
53
56
  # Performs subtraction.
54
57
  #
55
58
  # @return [Expr]
56
59
  def -(other)
57
- _from_rbexpr(_rbexpr - _to_rbexpr(other))
60
+ wrap_expr(_rbexpr - _to_rbexpr(other))
58
61
  end
59
62
 
60
63
  # Performs multiplication.
61
64
  #
62
65
  # @return [Expr]
63
66
  def *(other)
64
- _from_rbexpr(_rbexpr * _to_rbexpr(other))
67
+ wrap_expr(_rbexpr * _to_rbexpr(other))
65
68
  end
66
69
 
67
70
  # Performs division.
68
71
  #
69
72
  # @return [Expr]
70
73
  def /(other)
71
- _from_rbexpr(_rbexpr / _to_rbexpr(other))
74
+ wrap_expr(_rbexpr / _to_rbexpr(other))
72
75
  end
73
76
 
74
77
  # Returns the modulo.
75
78
  #
76
79
  # @return [Expr]
77
80
  def %(other)
78
- _from_rbexpr(_rbexpr % _to_rbexpr(other))
81
+ wrap_expr(_rbexpr % _to_rbexpr(other))
79
82
  end
80
83
 
81
84
  # Raises to the power of exponent.
@@ -83,49 +86,49 @@ module Polars
83
86
  # @return [Expr]
84
87
  def **(power)
85
88
  exponent = Utils.parse_into_expression(power)
86
- _from_rbexpr(_rbexpr.pow(exponent))
89
+ wrap_expr(_rbexpr.pow(exponent))
87
90
  end
88
91
 
89
92
  # Greater than or equal.
90
93
  #
91
94
  # @return [Expr]
92
95
  def >=(other)
93
- _from_rbexpr(_rbexpr.gt_eq(_to_expr(other)._rbexpr))
96
+ wrap_expr(_rbexpr.gt_eq(_to_expr(other)._rbexpr))
94
97
  end
95
98
 
96
99
  # Less than or equal.
97
100
  #
98
101
  # @return [Expr]
99
102
  def <=(other)
100
- _from_rbexpr(_rbexpr.lt_eq(_to_expr(other)._rbexpr))
103
+ wrap_expr(_rbexpr.lt_eq(_to_expr(other)._rbexpr))
101
104
  end
102
105
 
103
106
  # Equal.
104
107
  #
105
108
  # @return [Expr]
106
109
  def ==(other)
107
- _from_rbexpr(_rbexpr.eq(_to_expr(other)._rbexpr))
110
+ wrap_expr(_rbexpr.eq(_to_expr(other)._rbexpr))
108
111
  end
109
112
 
110
113
  # Not equal.
111
114
  #
112
115
  # @return [Expr]
113
116
  def !=(other)
114
- _from_rbexpr(_rbexpr.neq(_to_expr(other)._rbexpr))
117
+ wrap_expr(_rbexpr.neq(_to_expr(other)._rbexpr))
115
118
  end
116
119
 
117
120
  # Less than.
118
121
  #
119
122
  # @return [Expr]
120
123
  def <(other)
121
- _from_rbexpr(_rbexpr.lt(_to_expr(other)._rbexpr))
124
+ wrap_expr(_rbexpr.lt(_to_expr(other)._rbexpr))
122
125
  end
123
126
 
124
127
  # Greater than.
125
128
  #
126
129
  # @return [Expr]
127
130
  def >(other)
128
- _from_rbexpr(_rbexpr.gt(_to_expr(other)._rbexpr))
131
+ wrap_expr(_rbexpr.gt(_to_expr(other)._rbexpr))
129
132
  end
130
133
 
131
134
  # Performs boolean not.
@@ -134,12 +137,13 @@ module Polars
134
137
  def !
135
138
  is_not
136
139
  end
140
+ alias_method :~, :!
137
141
 
138
142
  # Performs negation.
139
143
  #
140
144
  # @return [Expr]
141
145
  def -@
142
- _from_rbexpr(_rbexpr.neg)
146
+ wrap_expr(_rbexpr.neg)
143
147
  end
144
148
 
145
149
  # Cast to physical representation of the logical dtype.
@@ -176,7 +180,7 @@ module Polars
176
180
  # # │ a ┆ 0 │
177
181
  # # └──────┴───────────────┘
178
182
  def to_physical
179
- _from_rbexpr(_rbexpr.to_physical)
183
+ wrap_expr(_rbexpr.to_physical)
180
184
  end
181
185
 
182
186
  # Check if any boolean value in a Boolean column is `true`.
@@ -196,7 +200,7 @@ module Polars
196
200
  # # │ true ┆ false │
197
201
  # # └──────┴───────┘
198
202
  def any(drop_nulls: true)
199
- _from_rbexpr(_rbexpr.any(drop_nulls))
203
+ wrap_expr(_rbexpr.any(drop_nulls))
200
204
  end
201
205
 
202
206
  # Check if all boolean values in a Boolean column are `true`.
@@ -221,7 +225,33 @@ module Polars
221
225
  # # │ true ┆ false ┆ false │
222
226
  # # └──────┴───────┴───────┘
223
227
  def all(drop_nulls: true)
224
- _from_rbexpr(_rbexpr.all(drop_nulls))
228
+ wrap_expr(_rbexpr.all(drop_nulls))
229
+ end
230
+
231
+ # Return indices where expression evaluates `true`.
232
+ #
233
+ # @return [Expr]
234
+ #
235
+ # @note
236
+ # Modifies number of rows returned, so will fail in combination with other
237
+ # expressions. Use as only expression in `select` / `with_columns`.
238
+ #
239
+ # @example
240
+ # df = Polars::DataFrame.new({"a" => [1, 1, 2, 1]})
241
+ # df.select((Polars.col("a") == 1).arg_true)
242
+ # # =>
243
+ # # shape: (3, 1)
244
+ # # ┌─────┐
245
+ # # │ a │
246
+ # # │ --- │
247
+ # # │ u32 │
248
+ # # ╞═════╡
249
+ # # │ 0 │
250
+ # # │ 1 │
251
+ # # │ 3 │
252
+ # # └─────┘
253
+ def arg_true
254
+ wrap_expr(Plr.arg_where(_rbexpr))
225
255
  end
226
256
 
227
257
  # Compute the square root of the elements.
@@ -243,7 +273,29 @@ module Polars
243
273
  # # │ 2.0 │
244
274
  # # └──────────┘
245
275
  def sqrt
246
- self**0.5
276
+ wrap_expr(_rbexpr.sqrt)
277
+ end
278
+
279
+ # Compute the cube root of the elements.
280
+ #
281
+ # @return [Expr]
282
+ #
283
+ # @example
284
+ # df = Polars::DataFrame.new({"values" => [1.0, 2.0, 4.0]})
285
+ # df.select(Polars.col("values").cbrt)
286
+ # # =>
287
+ # # shape: (3, 1)
288
+ # # ┌──────────┐
289
+ # # │ values │
290
+ # # │ --- │
291
+ # # │ f64 │
292
+ # # ╞══════════╡
293
+ # # │ 1.0 │
294
+ # # │ 1.259921 │
295
+ # # │ 1.587401 │
296
+ # # └──────────┘
297
+ def cbrt
298
+ wrap_expr(_rbexpr.cbrt)
247
299
  end
248
300
 
249
301
  # Compute the base 10 logarithm of the input array, element-wise.
@@ -287,7 +339,7 @@ module Polars
287
339
  # # │ 54.59815 │
288
340
  # # └──────────┘
289
341
  def exp
290
- _from_rbexpr(_rbexpr.exp)
342
+ wrap_expr(_rbexpr.exp)
291
343
  end
292
344
 
293
345
  # Rename the output of an expression.
@@ -322,7 +374,7 @@ module Polars
322
374
  # # │ 3 ┆ null │
323
375
  # # └─────┴──────┘
324
376
  def alias(name)
325
- _from_rbexpr(_rbexpr._alias(name))
377
+ wrap_expr(_rbexpr._alias(name))
326
378
  end
327
379
 
328
380
  # TODO support symbols for exclude
@@ -510,7 +562,7 @@ module Polars
510
562
  # # │ true │
511
563
  # # └───────┘
512
564
  def is_not
513
- _from_rbexpr(_rbexpr.not_)
565
+ wrap_expr(_rbexpr.not_)
514
566
  end
515
567
  alias_method :not_, :is_not
516
568
 
@@ -540,7 +592,7 @@ module Polars
540
592
  # # │ 5 ┆ 5.0 ┆ false ┆ false │
541
593
  # # └──────┴─────┴──────────┴──────────┘
542
594
  def is_null
543
- _from_rbexpr(_rbexpr.is_null)
595
+ wrap_expr(_rbexpr.is_null)
544
596
  end
545
597
 
546
598
  # Returns a boolean Series indicating which values are not null.
@@ -569,7 +621,7 @@ module Polars
569
621
  # # │ 5 ┆ 5.0 ┆ true ┆ true │
570
622
  # # └──────┴─────┴────────────┴────────────┘
571
623
  def is_not_null
572
- _from_rbexpr(_rbexpr.is_not_null)
624
+ wrap_expr(_rbexpr.is_not_null)
573
625
  end
574
626
 
575
627
  # Returns a boolean Series indicating which values are finite.
@@ -595,7 +647,7 @@ module Polars
595
647
  # # │ true ┆ false │
596
648
  # # └──────┴───────┘
597
649
  def is_finite
598
- _from_rbexpr(_rbexpr.is_finite)
650
+ wrap_expr(_rbexpr.is_finite)
599
651
  end
600
652
 
601
653
  # Returns a boolean Series indicating which values are infinite.
@@ -621,7 +673,7 @@ module Polars
621
673
  # # │ false ┆ true │
622
674
  # # └───────┴───────┘
623
675
  def is_infinite
624
- _from_rbexpr(_rbexpr.is_infinite)
676
+ wrap_expr(_rbexpr.is_infinite)
625
677
  end
626
678
 
627
679
  # Returns a boolean Series indicating which values are NaN.
@@ -654,7 +706,7 @@ module Polars
654
706
  # # │ 5 ┆ 5.0 ┆ false │
655
707
  # # └──────┴─────┴─────────┘
656
708
  def is_nan
657
- _from_rbexpr(_rbexpr.is_nan)
709
+ wrap_expr(_rbexpr.is_nan)
658
710
  end
659
711
 
660
712
  # Returns a boolean Series indicating which values are not NaN.
@@ -687,7 +739,7 @@ module Polars
687
739
  # # │ 5 ┆ 5.0 ┆ true │
688
740
  # # └──────┴─────┴──────────────┘
689
741
  def is_not_nan
690
- _from_rbexpr(_rbexpr.is_not_nan)
742
+ wrap_expr(_rbexpr.is_not_nan)
691
743
  end
692
744
 
693
745
  # Get the group indexes of the group by operation.
@@ -722,7 +774,7 @@ module Polars
722
774
  # # │ two ┆ [3, 4, 5] │
723
775
  # # └───────┴───────────┘
724
776
  def agg_groups
725
- _from_rbexpr(_rbexpr.agg_groups)
777
+ wrap_expr(_rbexpr.agg_groups)
726
778
  end
727
779
 
728
780
  # Count the number of values in this expression.
@@ -742,7 +794,7 @@ module Polars
742
794
  # # │ 3 ┆ 2 │
743
795
  # # └─────┴─────┘
744
796
  def count
745
- _from_rbexpr(_rbexpr.count)
797
+ wrap_expr(_rbexpr.count)
746
798
  end
747
799
 
748
800
  # Count the number of values in this expression.
@@ -762,7 +814,7 @@ module Polars
762
814
  # # │ 3 ┆ 3 │
763
815
  # # └─────┴─────┘
764
816
  def len
765
- _from_rbexpr(_rbexpr.len)
817
+ wrap_expr(_rbexpr.len)
766
818
  end
767
819
  alias_method :length, :len
768
820
 
@@ -801,7 +853,7 @@ module Polars
801
853
  if !length.is_a?(Expr)
802
854
  length = Polars.lit(length)
803
855
  end
804
- _from_rbexpr(_rbexpr.slice(offset._rbexpr, length._rbexpr))
856
+ wrap_expr(_rbexpr.slice(offset._rbexpr, length._rbexpr))
805
857
  end
806
858
 
807
859
  # Append expressions.
@@ -835,7 +887,7 @@ module Polars
835
887
  # # └─────┴──────┘
836
888
  def append(other, upcast: true)
837
889
  other = Utils.parse_into_expression(other)
838
- _from_rbexpr(_rbexpr.append(other, upcast))
890
+ wrap_expr(_rbexpr.append(other, upcast))
839
891
  end
840
892
 
841
893
  # Create a single chunk of memory for this Series.
@@ -860,7 +912,7 @@ module Polars
860
912
  # # │ 2 │
861
913
  # # └────────┘
862
914
  def rechunk
863
- _from_rbexpr(_rbexpr.rechunk)
915
+ wrap_expr(_rbexpr.rechunk)
864
916
  end
865
917
 
866
918
  # Drop null values.
@@ -887,7 +939,7 @@ module Polars
887
939
  # # │ NaN │
888
940
  # # └─────┘
889
941
  def drop_nulls
890
- _from_rbexpr(_rbexpr.drop_nulls)
942
+ wrap_expr(_rbexpr.drop_nulls)
891
943
  end
892
944
 
893
945
  # Drop floating point NaN values.
@@ -914,7 +966,7 @@ module Polars
914
966
  # # │ 4.0 │
915
967
  # # └──────┘
916
968
  def drop_nans
917
- _from_rbexpr(_rbexpr.drop_nans)
969
+ wrap_expr(_rbexpr.drop_nans)
918
970
  end
919
971
 
920
972
  # Get an array with the cumulative sum computed at every element.
@@ -949,7 +1001,7 @@ module Polars
949
1001
  # # │ 10 ┆ 4 │
950
1002
  # # └─────┴───────────┘
951
1003
  def cum_sum(reverse: false)
952
- _from_rbexpr(_rbexpr.cum_sum(reverse))
1004
+ wrap_expr(_rbexpr.cum_sum(reverse))
953
1005
  end
954
1006
  alias_method :cumsum, :cum_sum
955
1007
 
@@ -985,7 +1037,7 @@ module Polars
985
1037
  # # │ 24 ┆ 4 │
986
1038
  # # └─────┴───────────┘
987
1039
  def cum_prod(reverse: false)
988
- _from_rbexpr(_rbexpr.cum_prod(reverse))
1040
+ wrap_expr(_rbexpr.cum_prod(reverse))
989
1041
  end
990
1042
  alias_method :cumprod, :cum_prod
991
1043
 
@@ -1017,7 +1069,7 @@ module Polars
1017
1069
  # # │ 1 ┆ 4 │
1018
1070
  # # └─────┴───────────┘
1019
1071
  def cum_min(reverse: false)
1020
- _from_rbexpr(_rbexpr.cum_min(reverse))
1072
+ wrap_expr(_rbexpr.cum_min(reverse))
1021
1073
  end
1022
1074
  alias_method :cummin, :cum_min
1023
1075
 
@@ -1049,7 +1101,7 @@ module Polars
1049
1101
  # # │ 4 ┆ 4 │
1050
1102
  # # └─────┴───────────┘
1051
1103
  def cum_max(reverse: false)
1052
- _from_rbexpr(_rbexpr.cum_max(reverse))
1104
+ wrap_expr(_rbexpr.cum_max(reverse))
1053
1105
  end
1054
1106
  alias_method :cummax, :cum_max
1055
1107
 
@@ -1083,7 +1135,7 @@ module Polars
1083
1135
  # # │ d ┆ 3 ┆ 1 │
1084
1136
  # # └──────┴───────────┴───────────────────┘
1085
1137
  def cum_count(reverse: false)
1086
- _from_rbexpr(_rbexpr.cum_count(reverse))
1138
+ wrap_expr(_rbexpr.cum_count(reverse))
1087
1139
  end
1088
1140
  alias_method :cumcount, :cum_count
1089
1141
 
@@ -1109,7 +1161,7 @@ module Polars
1109
1161
  # # │ 1.0 │
1110
1162
  # # └─────┘
1111
1163
  def floor
1112
- _from_rbexpr(_rbexpr.floor)
1164
+ wrap_expr(_rbexpr.floor)
1113
1165
  end
1114
1166
 
1115
1167
  # Rounds up to the nearest integer value.
@@ -1134,7 +1186,7 @@ module Polars
1134
1186
  # # │ 2.0 │
1135
1187
  # # └─────┘
1136
1188
  def ceil
1137
- _from_rbexpr(_rbexpr.ceil)
1189
+ wrap_expr(_rbexpr.ceil)
1138
1190
  end
1139
1191
 
1140
1192
  # Round underlying floating point data by `decimals` digits.
@@ -1167,7 +1219,32 @@ module Polars
1167
1219
  # # │ 1.2 │
1168
1220
  # # └─────┘
1169
1221
  def round(decimals = 0, mode: "half_to_even")
1170
- _from_rbexpr(_rbexpr.round(decimals, mode))
1222
+ wrap_expr(_rbexpr.round(decimals, mode))
1223
+ end
1224
+
1225
+ # Round to a number of significant figures.
1226
+ #
1227
+ # @param digits [Integer]
1228
+ # Number of significant figures to round to.
1229
+ #
1230
+ # @return [Expr]
1231
+ #
1232
+ # @example
1233
+ # df = Polars::DataFrame.new({"a" => [0.01234, 3.333, 1234.0]})
1234
+ # df.with_columns(Polars.col("a").round_sig_figs(2).alias("round_sig_figs"))
1235
+ # # =>
1236
+ # # shape: (3, 2)
1237
+ # # ┌─────────┬────────────────┐
1238
+ # # │ a ┆ round_sig_figs │
1239
+ # # │ --- ┆ --- │
1240
+ # # │ f64 ┆ f64 │
1241
+ # # ╞═════════╪════════════════╡
1242
+ # # │ 0.01234 ┆ 0.012 │
1243
+ # # │ 3.333 ┆ 3.3 │
1244
+ # # │ 1234.0 ┆ 1200.0 │
1245
+ # # └─────────┴────────────────┘
1246
+ def round_sig_figs(digits)
1247
+ wrap_expr(_rbexpr.round_sig_figs(digits))
1171
1248
  end
1172
1249
 
1173
1250
  # Compute the dot/inner product between two Expressions.
@@ -1196,7 +1273,7 @@ module Polars
1196
1273
  # # └─────┘
1197
1274
  def dot(other)
1198
1275
  other = Utils.parse_into_expression(other, str_as_lit: false)
1199
- _from_rbexpr(_rbexpr.dot(other))
1276
+ wrap_expr(_rbexpr.dot(other))
1200
1277
  end
1201
1278
 
1202
1279
  # Compute the most occurring value(s).
@@ -1224,7 +1301,7 @@ module Polars
1224
1301
  # # │ 1 ┆ 2 │
1225
1302
  # # └─────┴─────┘
1226
1303
  def mode
1227
- _from_rbexpr(_rbexpr.mode)
1304
+ wrap_expr(_rbexpr.mode)
1228
1305
  end
1229
1306
 
1230
1307
  # Cast between data types.
@@ -1263,7 +1340,7 @@ module Polars
1263
1340
  # # └─────┴─────┘
1264
1341
  def cast(dtype, strict: true)
1265
1342
  dtype = Utils.rb_type_to_dtype(dtype)
1266
- _from_rbexpr(_rbexpr.cast(dtype, strict))
1343
+ wrap_expr(_rbexpr.cast(dtype, strict))
1267
1344
  end
1268
1345
 
1269
1346
  # Sort this column. In projection/ selection context the whole column is sorted.
@@ -1338,7 +1415,7 @@ module Polars
1338
1415
  # # │ one ┆ [1, 2, 98] │
1339
1416
  # # └───────┴────────────┘
1340
1417
  def sort(reverse: false, nulls_last: false)
1341
- _from_rbexpr(_rbexpr.sort_with(reverse, nulls_last))
1418
+ wrap_expr(_rbexpr.sort_with(reverse, nulls_last))
1342
1419
  end
1343
1420
 
1344
1421
  # Return the `k` largest elements.
@@ -1377,7 +1454,113 @@ module Polars
1377
1454
  # # └───────┴──────────┘
1378
1455
  def top_k(k: 5)
1379
1456
  k = Utils.parse_into_expression(k)
1380
- _from_rbexpr(_rbexpr.top_k(k))
1457
+ wrap_expr(_rbexpr.top_k(k))
1458
+ end
1459
+
1460
+ # Return the elements corresponding to the `k` largest elements of the `by` column(s).
1461
+ #
1462
+ # Non-null elements are always preferred over null elements, regardless of
1463
+ # the value of `reverse`. The output is not guaranteed to be in any
1464
+ # particular order, call :func:`sort` after this function if you wish the
1465
+ # output to be sorted.
1466
+ #
1467
+ # @param by [Object]
1468
+ # Column(s) used to determine the largest elements.
1469
+ # Accepts expression input. Strings are parsed as column names.
1470
+ # @param k [Integer]
1471
+ # Number of elements to return.
1472
+ # @param reverse [Object]
1473
+ # Consider the `k` smallest elements of the `by` column(s) (instead of the `k`
1474
+ # largest). This can be specified per column by passing a sequence of
1475
+ # booleans.
1476
+ #
1477
+ # @return [Expr]
1478
+ #
1479
+ # @example
1480
+ # df = Polars::DataFrame.new(
1481
+ # {
1482
+ # "a" => [1, 2, 3, 4, 5, 6],
1483
+ # "b" => [6, 5, 4, 3, 2, 1],
1484
+ # "c" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
1485
+ # }
1486
+ # )
1487
+ # # =>
1488
+ # # shape: (6, 3)
1489
+ # # ┌─────┬─────┬────────┐
1490
+ # # │ a ┆ b ┆ c │
1491
+ # # │ --- ┆ --- ┆ --- │
1492
+ # # │ i64 ┆ i64 ┆ str │
1493
+ # # ╞═════╪═════╪════════╡
1494
+ # # │ 1 ┆ 6 ┆ Apple │
1495
+ # # │ 2 ┆ 5 ┆ Orange │
1496
+ # # │ 3 ┆ 4 ┆ Apple │
1497
+ # # │ 4 ┆ 3 ┆ Apple │
1498
+ # # │ 5 ┆ 2 ┆ Banana │
1499
+ # # │ 6 ┆ 1 ┆ Banana │
1500
+ # # └─────┴─────┴────────┘
1501
+ #
1502
+ # @example Get the top 2 rows by column `a` or `b`.
1503
+ # df.select(
1504
+ # Polars.all.top_k_by("a", k: 2).name.suffix("_top_by_a"),
1505
+ # Polars.all.top_k_by("b", k: 2).name.suffix("_top_by_b")
1506
+ # )
1507
+ # # =>
1508
+ # # shape: (2, 6)
1509
+ # # ┌────────────┬────────────┬────────────┬────────────┬────────────┬────────────┐
1510
+ # # │ a_top_by_a ┆ b_top_by_a ┆ c_top_by_a ┆ a_top_by_b ┆ b_top_by_b ┆ c_top_by_b │
1511
+ # # │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
1512
+ # # │ i64 ┆ i64 ┆ str ┆ i64 ┆ i64 ┆ str │
1513
+ # # ╞════════════╪════════════╪════════════╪════════════╪════════════╪════════════╡
1514
+ # # │ 6 ┆ 1 ┆ Banana ┆ 1 ┆ 6 ┆ Apple │
1515
+ # # │ 5 ┆ 2 ┆ Banana ┆ 2 ┆ 5 ┆ Orange │
1516
+ # # └────────────┴────────────┴────────────┴────────────┴────────────┴────────────┘
1517
+ #
1518
+ # @example Get the top 2 rows by multiple columns with given order.
1519
+ # df.select(
1520
+ # Polars.all
1521
+ # .top_k_by(["c", "a"], k: 2, reverse: [false, true])
1522
+ # .name.suffix("_by_ca"),
1523
+ # Polars.all
1524
+ # .top_k_by(["c", "b"], k: 2, reverse: [false, true])
1525
+ # .name.suffix("_by_cb")
1526
+ # )
1527
+ # # =>
1528
+ # # shape: (2, 6)
1529
+ # # ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
1530
+ # # │ a_by_ca ┆ b_by_ca ┆ c_by_ca ┆ a_by_cb ┆ b_by_cb ┆ c_by_cb │
1531
+ # # │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
1532
+ # # │ i64 ┆ i64 ┆ str ┆ i64 ┆ i64 ┆ str │
1533
+ # # ╞═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
1534
+ # # │ 2 ┆ 5 ┆ Orange ┆ 2 ┆ 5 ┆ Orange │
1535
+ # # │ 5 ┆ 2 ┆ Banana ┆ 6 ┆ 1 ┆ Banana │
1536
+ # # └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
1537
+ #
1538
+ # @example Get the top 2 rows by column `a` in each group.
1539
+ # df.group_by("c", maintain_order: true)
1540
+ # .agg(Polars.all.top_k_by("a", k: 2))
1541
+ # .explode(Polars.all.exclude("c"))
1542
+ # # =>
1543
+ # # shape: (5, 3)
1544
+ # # ┌────────┬─────┬─────┐
1545
+ # # │ c ┆ a ┆ b │
1546
+ # # │ --- ┆ --- ┆ --- │
1547
+ # # │ str ┆ i64 ┆ i64 │
1548
+ # # ╞════════╪═════╪═════╡
1549
+ # # │ Apple ┆ 4 ┆ 3 │
1550
+ # # │ Apple ┆ 3 ┆ 4 │
1551
+ # # │ Orange ┆ 2 ┆ 5 │
1552
+ # # │ Banana ┆ 6 ┆ 1 │
1553
+ # # │ Banana ┆ 5 ┆ 2 │
1554
+ # # └────────┴─────┴─────┘
1555
+ def top_k_by(
1556
+ by,
1557
+ k: 5,
1558
+ reverse: false
1559
+ )
1560
+ k = Utils.parse_into_expression(k)
1561
+ by = Utils.parse_into_list_of_expressions(by)
1562
+ reverse = Utils.extend_bool(reverse, by.length, "reverse", "by")
1563
+ wrap_expr(_rbexpr.top_k_by(by, k, reverse))
1381
1564
  end
1382
1565
 
1383
1566
  # Return the `k` smallest elements.
@@ -1416,7 +1599,113 @@ module Polars
1416
1599
  # # └───────┴──────────┘
1417
1600
  def bottom_k(k: 5)
1418
1601
  k = Utils.parse_into_expression(k)
1419
- _from_rbexpr(_rbexpr.bottom_k(k))
1602
+ wrap_expr(_rbexpr.bottom_k(k))
1603
+ end
1604
+
1605
+ # Return the elements corresponding to the `k` smallest elements of the `by` column(s).
1606
+ #
1607
+ # Non-null elements are always preferred over null elements, regardless of
1608
+ # the value of `reverse`. The output is not guaranteed to be in any
1609
+ # particular order, call :func:`sort` after this function if you wish the
1610
+ # output to be sorted.
1611
+ #
1612
+ # @param by [Object]
1613
+ # Column(s) used to determine the smallest elements.
1614
+ # Accepts expression input. Strings are parsed as column names.
1615
+ # @param k [Integer]
1616
+ # Number of elements to return.
1617
+ # @param reverse [Object]
1618
+ # Consider the `k` largest elements of the `by` column(s) (instead of the `k`
1619
+ # smallest). This can be specified per column by passing a sequence of
1620
+ # booleans.
1621
+ #
1622
+ # @return [Expr]
1623
+ #
1624
+ # @example
1625
+ # df = Polars::DataFrame.new(
1626
+ # {
1627
+ # "a" => [1, 2, 3, 4, 5, 6],
1628
+ # "b" => [6, 5, 4, 3, 2, 1],
1629
+ # "c" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"],
1630
+ # }
1631
+ # )
1632
+ # # =>
1633
+ # # shape: (6, 3)
1634
+ # # ┌─────┬─────┬────────┐
1635
+ # # │ a ┆ b ┆ c │
1636
+ # # │ --- ┆ --- ┆ --- │
1637
+ # # │ i64 ┆ i64 ┆ str │
1638
+ # # ╞═════╪═════╪════════╡
1639
+ # # │ 1 ┆ 6 ┆ Apple │
1640
+ # # │ 2 ┆ 5 ┆ Orange │
1641
+ # # │ 3 ┆ 4 ┆ Apple │
1642
+ # # │ 4 ┆ 3 ┆ Apple │
1643
+ # # │ 5 ┆ 2 ┆ Banana │
1644
+ # # │ 6 ┆ 1 ┆ Banana │
1645
+ # # └─────┴─────┴────────┘
1646
+ #
1647
+ # @example Get the bottom 2 rows by column `a` or `b`.
1648
+ # df.select(
1649
+ # Polars.all.bottom_k_by("a", k: 2).name.suffix("_btm_by_a"),
1650
+ # Polars.all.bottom_k_by("b", k: 2).name.suffix("_btm_by_b")
1651
+ # )
1652
+ # # =>
1653
+ # # shape: (2, 6)
1654
+ # # ┌────────────┬────────────┬────────────┬────────────┬────────────┬────────────┐
1655
+ # # │ a_btm_by_a ┆ b_btm_by_a ┆ c_btm_by_a ┆ a_btm_by_b ┆ b_btm_by_b ┆ c_btm_by_b │
1656
+ # # │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
1657
+ # # │ i64 ┆ i64 ┆ str ┆ i64 ┆ i64 ┆ str │
1658
+ # # ╞════════════╪════════════╪════════════╪════════════╪════════════╪════════════╡
1659
+ # # │ 1 ┆ 6 ┆ Apple ┆ 6 ┆ 1 ┆ Banana │
1660
+ # # │ 2 ┆ 5 ┆ Orange ┆ 5 ┆ 2 ┆ Banana │
1661
+ # # └────────────┴────────────┴────────────┴────────────┴────────────┴────────────┘
1662
+ #
1663
+ # @example Get the bottom 2 rows by multiple columns with given order.
1664
+ # df.select(
1665
+ # Polars.all
1666
+ # .bottom_k_by(["c", "a"], k: 2, reverse: [false, true])
1667
+ # .name.suffix("_by_ca"),
1668
+ # Polars.all
1669
+ # .bottom_k_by(["c", "b"], k: 2, reverse: [false, true])
1670
+ # .name.suffix("_by_cb"),
1671
+ # )
1672
+ # # =>
1673
+ # # shape: (2, 6)
1674
+ # # ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
1675
+ # # │ a_by_ca ┆ b_by_ca ┆ c_by_ca ┆ a_by_cb ┆ b_by_cb ┆ c_by_cb │
1676
+ # # │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
1677
+ # # │ i64 ┆ i64 ┆ str ┆ i64 ┆ i64 ┆ str │
1678
+ # # ╞═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
1679
+ # # │ 4 ┆ 3 ┆ Apple ┆ 1 ┆ 6 ┆ Apple │
1680
+ # # │ 3 ┆ 4 ┆ Apple ┆ 3 ┆ 4 ┆ Apple │
1681
+ # # └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
1682
+ #
1683
+ # @example Get the bottom 2 rows by column `a` in each group.
1684
+ # df.group_by("c", maintain_order: true)
1685
+ # .agg(Polars.all.bottom_k_by("a", k: 2))
1686
+ # .explode(Polars.all.exclude("c"))
1687
+ # # =>
1688
+ # # shape: (5, 3)
1689
+ # # ┌────────┬─────┬─────┐
1690
+ # # │ c ┆ a ┆ b │
1691
+ # # │ --- ┆ --- ┆ --- │
1692
+ # # │ str ┆ i64 ┆ i64 │
1693
+ # # ╞════════╪═════╪═════╡
1694
+ # # │ Apple ┆ 1 ┆ 6 │
1695
+ # # │ Apple ┆ 3 ┆ 4 │
1696
+ # # │ Orange ┆ 2 ┆ 5 │
1697
+ # # │ Banana ┆ 5 ┆ 2 │
1698
+ # # │ Banana ┆ 6 ┆ 1 │
1699
+ # # └────────┴─────┴─────┘
1700
+ def bottom_k_by(
1701
+ by,
1702
+ k: 5,
1703
+ reverse: false
1704
+ )
1705
+ k = Utils.parse_into_expression(k)
1706
+ by = Utils.parse_into_list_of_expressions(by)
1707
+ reverse = Utils.extend_bool(reverse, by.length, "reverse", "by")
1708
+ wrap_expr(_rbexpr.bottom_k_by(by, k, reverse))
1420
1709
  end
1421
1710
 
1422
1711
  # Get the index values that would sort this column.
@@ -1447,7 +1736,7 @@ module Polars
1447
1736
  # # │ 2 │
1448
1737
  # # └─────┘
1449
1738
  def arg_sort(reverse: false, nulls_last: false)
1450
- _from_rbexpr(_rbexpr.arg_sort(reverse, nulls_last))
1739
+ wrap_expr(_rbexpr.arg_sort(reverse, nulls_last))
1451
1740
  end
1452
1741
 
1453
1742
  # Get the index of the maximal value.
@@ -1471,7 +1760,7 @@ module Polars
1471
1760
  # # │ 2 │
1472
1761
  # # └─────┘
1473
1762
  def arg_max
1474
- _from_rbexpr(_rbexpr.arg_max)
1763
+ wrap_expr(_rbexpr.arg_max)
1475
1764
  end
1476
1765
 
1477
1766
  # Get the index of the minimal value.
@@ -1495,7 +1784,37 @@ module Polars
1495
1784
  # # │ 1 │
1496
1785
  # # └─────┘
1497
1786
  def arg_min
1498
- _from_rbexpr(_rbexpr.arg_min)
1787
+ wrap_expr(_rbexpr.arg_min)
1788
+ end
1789
+
1790
+ # Get the index of the first occurrence of a value, or ``None`` if it's not found.
1791
+ #
1792
+ # @param element [Object]
1793
+ # Value to find.
1794
+ #
1795
+ # @return [Expr]
1796
+ #
1797
+ # @example
1798
+ # df = Polars::DataFrame.new({"a" => [1, nil, 17]})
1799
+ # df.select(
1800
+ # [
1801
+ # Polars.col("a").index_of(17).alias("seventeen"),
1802
+ # Polars.col("a").index_of(nil).alias("null"),
1803
+ # Polars.col("a").index_of(55).alias("fiftyfive")
1804
+ # ]
1805
+ # )
1806
+ # # =>
1807
+ # # shape: (1, 3)
1808
+ # # ┌───────────┬──────┬───────────┐
1809
+ # # │ seventeen ┆ null ┆ fiftyfive │
1810
+ # # │ --- ┆ --- ┆ --- │
1811
+ # # │ u32 ┆ u32 ┆ u32 │
1812
+ # # ╞═══════════╪══════╪═══════════╡
1813
+ # # │ 2 ┆ 1 ┆ null │
1814
+ # # └───────────┴──────┴───────────┘
1815
+ def index_of(element)
1816
+ element = Utils.parse_into_expression(element, str_as_lit: true)
1817
+ wrap_expr(_rbexpr.index_of(element))
1499
1818
  end
1500
1819
 
1501
1820
  # Find indices where elements should be inserted to maintain order.
@@ -1536,7 +1855,7 @@ module Polars
1536
1855
  # # └──────┴───────┴─────┘
1537
1856
  def search_sorted(element, side: "any", descending: false)
1538
1857
  element = Utils.parse_into_expression(element, str_as_lit: false)
1539
- _from_rbexpr(_rbexpr.search_sorted(element, side, descending))
1858
+ wrap_expr(_rbexpr.search_sorted(element, side, descending))
1540
1859
  end
1541
1860
 
1542
1861
  # Sort this column by the ordering of another column, or multiple other columns.
@@ -1594,7 +1913,7 @@ module Polars
1594
1913
  by = Utils.parse_into_list_of_expressions(by, *more_by)
1595
1914
  reverse = Utils.extend_bool(reverse, by.length, "reverse", "by")
1596
1915
  nulls_last = Utils.extend_bool(nulls_last, by.length, "nulls_last", "by")
1597
- _from_rbexpr(
1916
+ wrap_expr(
1598
1917
  _rbexpr.sort_by(
1599
1918
  by, reverse, nulls_last, multithreaded, maintain_order
1600
1919
  )
@@ -1639,7 +1958,7 @@ module Polars
1639
1958
  else
1640
1959
  indices_lit = Utils.parse_into_expression(indices, str_as_lit: false)
1641
1960
  end
1642
- _from_rbexpr(_rbexpr.gather(indices_lit))
1961
+ wrap_expr(_rbexpr.gather(indices_lit))
1643
1962
  end
1644
1963
  alias_method :take, :gather
1645
1964
 
@@ -1677,7 +1996,7 @@ module Polars
1677
1996
  # # └───────┴───────┘
1678
1997
  def get(index)
1679
1998
  index_lit = Utils.parse_into_expression(index)
1680
- _from_rbexpr(_rbexpr.get(index_lit))
1999
+ wrap_expr(_rbexpr.get(index_lit))
1681
2000
  end
1682
2001
 
1683
2002
  # Shift the values by a given period.
@@ -1709,7 +2028,7 @@ module Polars
1709
2028
  fill_value = Utils.parse_into_expression(fill_value, str_as_lit: true)
1710
2029
  end
1711
2030
  n = Utils.parse_into_expression(n)
1712
- _from_rbexpr(_rbexpr.shift(n, fill_value))
2031
+ wrap_expr(_rbexpr.shift(n, fill_value))
1713
2032
  end
1714
2033
 
1715
2034
  # Shift the values by a given period and fill the resulting null values.
@@ -1812,9 +2131,9 @@ module Polars
1812
2131
 
1813
2132
  if !value.nil?
1814
2133
  value = Utils.parse_into_expression(value, str_as_lit: true)
1815
- _from_rbexpr(_rbexpr.fill_null(value))
2134
+ wrap_expr(_rbexpr.fill_null(value))
1816
2135
  else
1817
- _from_rbexpr(_rbexpr.fill_null_with_strategy(strategy, limit))
2136
+ wrap_expr(_rbexpr.fill_null_with_strategy(strategy, limit))
1818
2137
  end
1819
2138
  end
1820
2139
 
@@ -1843,7 +2162,7 @@ module Polars
1843
2162
  # # └──────┴──────┘
1844
2163
  def fill_nan(fill_value)
1845
2164
  fill_value = Utils.parse_into_expression(fill_value, str_as_lit: true)
1846
- _from_rbexpr(_rbexpr.fill_nan(fill_value))
2165
+ wrap_expr(_rbexpr.fill_nan(fill_value))
1847
2166
  end
1848
2167
 
1849
2168
  # Fill missing values with the latest seen values.
@@ -1939,7 +2258,7 @@ module Polars
1939
2258
  # # │ 5 ┆ banana ┆ 1 ┆ beetle ┆ 1 ┆ banana ┆ 5 ┆ beetle │
1940
2259
  # # └─────┴────────┴─────┴────────┴───────────┴────────────────┴───────────┴──────────────┘
1941
2260
  def reverse
1942
- _from_rbexpr(_rbexpr.reverse)
2261
+ wrap_expr(_rbexpr.reverse)
1943
2262
  end
1944
2263
 
1945
2264
  # Get standard deviation.
@@ -1962,7 +2281,7 @@ module Polars
1962
2281
  # # │ 1.0 │
1963
2282
  # # └─────┘
1964
2283
  def std(ddof: 1)
1965
- _from_rbexpr(_rbexpr.std(ddof))
2284
+ wrap_expr(_rbexpr.std(ddof))
1966
2285
  end
1967
2286
 
1968
2287
  # Get variance.
@@ -1985,7 +2304,7 @@ module Polars
1985
2304
  # # │ 1.0 │
1986
2305
  # # └─────┘
1987
2306
  def var(ddof: 1)
1988
- _from_rbexpr(_rbexpr.var(ddof))
2307
+ wrap_expr(_rbexpr.var(ddof))
1989
2308
  end
1990
2309
 
1991
2310
  # Get maximum value.
@@ -2005,7 +2324,7 @@ module Polars
2005
2324
  # # │ 1.0 │
2006
2325
  # # └─────┘
2007
2326
  def max
2008
- _from_rbexpr(_rbexpr.max)
2327
+ wrap_expr(_rbexpr.max)
2009
2328
  end
2010
2329
 
2011
2330
  # Get minimum value.
@@ -2025,7 +2344,7 @@ module Polars
2025
2344
  # # │ -1.0 │
2026
2345
  # # └──────┘
2027
2346
  def min
2028
- _from_rbexpr(_rbexpr.min)
2347
+ wrap_expr(_rbexpr.min)
2029
2348
  end
2030
2349
 
2031
2350
  # Get maximum value, but propagate/poison encountered NaN values.
@@ -2045,7 +2364,7 @@ module Polars
2045
2364
  # # │ NaN │
2046
2365
  # # └─────┘
2047
2366
  def nan_max
2048
- _from_rbexpr(_rbexpr.nan_max)
2367
+ wrap_expr(_rbexpr.nan_max)
2049
2368
  end
2050
2369
 
2051
2370
  # Get minimum value, but propagate/poison encountered NaN values.
@@ -2065,7 +2384,7 @@ module Polars
2065
2384
  # # │ NaN │
2066
2385
  # # └─────┘
2067
2386
  def nan_min
2068
- _from_rbexpr(_rbexpr.nan_min)
2387
+ wrap_expr(_rbexpr.nan_min)
2069
2388
  end
2070
2389
 
2071
2390
  # Get sum value.
@@ -2089,7 +2408,7 @@ module Polars
2089
2408
  # # │ 0 │
2090
2409
  # # └─────┘
2091
2410
  def sum
2092
- _from_rbexpr(_rbexpr.sum)
2411
+ wrap_expr(_rbexpr.sum)
2093
2412
  end
2094
2413
 
2095
2414
  # Get mean value.
@@ -2109,7 +2428,7 @@ module Polars
2109
2428
  # # │ 0.0 │
2110
2429
  # # └─────┘
2111
2430
  def mean
2112
- _from_rbexpr(_rbexpr.mean)
2431
+ wrap_expr(_rbexpr.mean)
2113
2432
  end
2114
2433
 
2115
2434
  # Get median value using linear interpolation.
@@ -2129,7 +2448,7 @@ module Polars
2129
2448
  # # │ 0.0 │
2130
2449
  # # └─────┘
2131
2450
  def median
2132
- _from_rbexpr(_rbexpr.median)
2451
+ wrap_expr(_rbexpr.median)
2133
2452
  end
2134
2453
 
2135
2454
  # Compute the product of an expression.
@@ -2149,7 +2468,7 @@ module Polars
2149
2468
  # # │ 6 │
2150
2469
  # # └─────┘
2151
2470
  def product
2152
- _from_rbexpr(_rbexpr.product)
2471
+ wrap_expr(_rbexpr.product)
2153
2472
  end
2154
2473
 
2155
2474
  # Count unique values.
@@ -2169,7 +2488,7 @@ module Polars
2169
2488
  # # │ 2 │
2170
2489
  # # └─────┘
2171
2490
  def n_unique
2172
- _from_rbexpr(_rbexpr.n_unique)
2491
+ wrap_expr(_rbexpr.n_unique)
2173
2492
  end
2174
2493
 
2175
2494
  # Approx count unique values.
@@ -2191,7 +2510,7 @@ module Polars
2191
2510
  # # │ 2 │
2192
2511
  # # └─────┘
2193
2512
  def approx_n_unique
2194
- _from_rbexpr(_rbexpr.approx_n_unique)
2513
+ wrap_expr(_rbexpr.approx_n_unique)
2195
2514
  end
2196
2515
  alias_method :approx_unique, :approx_n_unique
2197
2516
 
@@ -2217,7 +2536,33 @@ module Polars
2217
2536
  # # │ 2 ┆ 0 │
2218
2537
  # # └─────┴─────┘
2219
2538
  def null_count
2220
- _from_rbexpr(_rbexpr.null_count)
2539
+ wrap_expr(_rbexpr.null_count)
2540
+ end
2541
+
2542
+ # Check whether the expression contains one or more null values.
2543
+ #
2544
+ # @return [Expr]
2545
+ #
2546
+ # @example
2547
+ # df = Polars::DataFrame.new(
2548
+ # {
2549
+ # "a" => [nil, 1, nil],
2550
+ # "b" => [10, nil, 300],
2551
+ # "c" => [350, 650, 850]
2552
+ # }
2553
+ # )
2554
+ # df.select(Polars.all.has_nulls)
2555
+ # # =>
2556
+ # # shape: (1, 3)
2557
+ # # ┌──────┬──────┬───────┐
2558
+ # # │ a ┆ b ┆ c │
2559
+ # # │ --- ┆ --- ┆ --- │
2560
+ # # │ bool ┆ bool ┆ bool │
2561
+ # # ╞══════╪══════╪═══════╡
2562
+ # # │ true ┆ true ┆ false │
2563
+ # # └──────┴──────┴───────┘
2564
+ def has_nulls
2565
+ null_count > 0
2221
2566
  end
2222
2567
 
2223
2568
  # Get index of first unique value.
@@ -2257,7 +2602,7 @@ module Polars
2257
2602
  # # │ 1 │
2258
2603
  # # └─────┘
2259
2604
  def arg_unique
2260
- _from_rbexpr(_rbexpr.arg_unique)
2605
+ wrap_expr(_rbexpr.arg_unique)
2261
2606
  end
2262
2607
 
2263
2608
  # Get unique values of this expression.
@@ -2282,9 +2627,9 @@ module Polars
2282
2627
  # # └─────┘
2283
2628
  def unique(maintain_order: false)
2284
2629
  if maintain_order
2285
- _from_rbexpr(_rbexpr.unique_stable)
2630
+ wrap_expr(_rbexpr.unique_stable)
2286
2631
  else
2287
- _from_rbexpr(_rbexpr.unique)
2632
+ wrap_expr(_rbexpr.unique)
2288
2633
  end
2289
2634
  end
2290
2635
 
@@ -2305,7 +2650,7 @@ module Polars
2305
2650
  # # │ 1 │
2306
2651
  # # └─────┘
2307
2652
  def first
2308
- _from_rbexpr(_rbexpr.first)
2653
+ wrap_expr(_rbexpr.first)
2309
2654
  end
2310
2655
 
2311
2656
  # Get the last value.
@@ -2325,7 +2670,7 @@ module Polars
2325
2670
  # # │ 2 │
2326
2671
  # # └─────┘
2327
2672
  def last
2328
- _from_rbexpr(_rbexpr.last)
2673
+ wrap_expr(_rbexpr.last)
2329
2674
  end
2330
2675
 
2331
2676
  # Apply window function over a subgroup.
@@ -2389,7 +2734,110 @@ module Polars
2389
2734
  # # └────────┘
2390
2735
  def over(expr)
2391
2736
  rbexprs = Utils.parse_into_list_of_expressions(expr)
2392
- _from_rbexpr(_rbexpr.over(rbexprs))
2737
+ wrap_expr(_rbexpr.over(rbexprs))
2738
+ end
2739
+
2740
+ # Create rolling groups based on a temporal or integer column.
2741
+ #
2742
+ # If you have a time series `<t_0, t_1, ..., t_n>`, then by default the
2743
+ # windows created will be
2744
+ #
2745
+ # * (t_0 - period, t_0]
2746
+ # * (t_1 - period, t_1]
2747
+ # * ...
2748
+ # * (t_n - period, t_n]
2749
+ #
2750
+ # whereas if you pass a non-default `offset`, then the windows will be
2751
+ #
2752
+ # * (t_0 + offset, t_0 + offset + period]
2753
+ # * (t_1 + offset, t_1 + offset + period]
2754
+ # * ...
2755
+ # * (t_n + offset, t_n + offset + period]
2756
+ #
2757
+ # The `period` and `offset` arguments are created either from a timedelta, or
2758
+ # by using the following string language:
2759
+ #
2760
+ # - 1ns (1 nanosecond)
2761
+ # - 1us (1 microsecond)
2762
+ # - 1ms (1 millisecond)
2763
+ # - 1s (1 second)
2764
+ # - 1m (1 minute)
2765
+ # - 1h (1 hour)
2766
+ # - 1d (1 calendar day)
2767
+ # - 1w (1 calendar week)
2768
+ # - 1mo (1 calendar month)
2769
+ # - 1q (1 calendar quarter)
2770
+ # - 1y (1 calendar year)
2771
+ # - 1i (1 index count)
2772
+ #
2773
+ # Or combine them:
2774
+ # "3d12h4m25s" # 3 days, 12 hours, 4 minutes, and 25 seconds
2775
+ #
2776
+ # By "calendar day", we mean the corresponding time on the next day (which may
2777
+ # not be 24 hours, due to daylight savings). Similarly for "calendar week",
2778
+ # "calendar month", "calendar quarter", and "calendar year".
2779
+ #
2780
+ # @param index_column [Object]
2781
+ # Column used to group based on the time window.
2782
+ # Often of type Date/Datetime.
2783
+ # This column must be sorted in ascending order.
2784
+ # In case of a rolling group by on indices, dtype needs to be one of
2785
+ # \\\\{UInt32, UInt64, Int32, Int64}. Note that the first three get temporarily
2786
+ # cast to Int64, so if performance matters use an Int64 column.
2787
+ # @param period [Object]
2788
+ # Length of the window - must be non-negative.
2789
+ # @param offset [Object]
2790
+ # Offset of the window. Default is `-period`.
2791
+ # @param closed ['right', 'left', 'both', 'none']
2792
+ # Define which sides of the temporal interval are closed (inclusive).
2793
+ #
2794
+ # @return [Expr]
2795
+ #
2796
+ # @example
2797
+ # dates = [
2798
+ # "2020-01-01 13:45:48",
2799
+ # "2020-01-01 16:42:13",
2800
+ # "2020-01-01 16:45:09",
2801
+ # "2020-01-02 18:12:48",
2802
+ # "2020-01-03 19:45:32",
2803
+ # "2020-01-08 23:16:43"
2804
+ # ]
2805
+ # df = Polars::DataFrame.new({"dt" => dates, "a": [3, 7, 5, 9, 2, 1]}).with_columns(
2806
+ # Polars.col("dt").str.strptime(Polars::Datetime).set_sorted
2807
+ # )
2808
+ # df.with_columns(
2809
+ # sum_a: Polars.sum("a").rolling(index_column: "dt", period: "2d"),
2810
+ # min_a: Polars.min("a").rolling(index_column: "dt", period: "2d"),
2811
+ # max_a: Polars.max("a").rolling(index_column: "dt", period: "2d")
2812
+ # )
2813
+ # # =>
2814
+ # # shape: (6, 5)
2815
+ # # ┌─────────────────────┬─────┬───────┬───────┬───────┐
2816
+ # # │ dt ┆ a ┆ sum_a ┆ min_a ┆ max_a │
2817
+ # # │ --- ┆ --- ┆ --- ┆ --- ┆ --- │
2818
+ # # │ datetime[μs] ┆ i64 ┆ i64 ┆ i64 ┆ i64 │
2819
+ # # ╞═════════════════════╪═════╪═══════╪═══════╪═══════╡
2820
+ # # │ 2020-01-01 13:45:48 ┆ 3 ┆ 3 ┆ 3 ┆ 3 │
2821
+ # # │ 2020-01-01 16:42:13 ┆ 7 ┆ 10 ┆ 3 ┆ 7 │
2822
+ # # │ 2020-01-01 16:45:09 ┆ 5 ┆ 15 ┆ 3 ┆ 7 │
2823
+ # # │ 2020-01-02 18:12:48 ┆ 9 ┆ 24 ┆ 3 ┆ 9 │
2824
+ # # │ 2020-01-03 19:45:32 ┆ 2 ┆ 11 ┆ 2 ┆ 9 │
2825
+ # # │ 2020-01-08 23:16:43 ┆ 1 ┆ 1 ┆ 1 ┆ 1 │
2826
+ # # └─────────────────────┴─────┴───────┴───────┴───────┘
2827
+ def rolling(
2828
+ index_column:,
2829
+ period:,
2830
+ offset: nil,
2831
+ closed: "right"
2832
+ )
2833
+ if offset.nil?
2834
+ offset = Utils.negate_duration_string(Utils.parse_as_duration_string(period))
2835
+ end
2836
+
2837
+ period = Utils.parse_as_duration_string(period)
2838
+ offset = Utils.parse_as_duration_string(offset)
2839
+
2840
+ wrap_expr(_rbexpr.rolling(index_column, period, offset, closed))
2393
2841
  end
2394
2842
 
2395
2843
  # Get mask of unique values.
@@ -2411,7 +2859,7 @@ module Polars
2411
2859
  # # │ true │
2412
2860
  # # └───────┘
2413
2861
  def is_unique
2414
- _from_rbexpr(_rbexpr.is_unique)
2862
+ wrap_expr(_rbexpr.is_unique)
2415
2863
  end
2416
2864
 
2417
2865
  # Get a mask of the first unique value.
@@ -2439,10 +2887,34 @@ module Polars
2439
2887
  # # │ 5 ┆ true │
2440
2888
  # # └─────┴──────────┘
2441
2889
  def is_first_distinct
2442
- _from_rbexpr(_rbexpr.is_first_distinct)
2890
+ wrap_expr(_rbexpr.is_first_distinct)
2443
2891
  end
2444
2892
  alias_method :is_first, :is_first_distinct
2445
2893
 
2894
+ # Return a boolean mask indicating the last occurrence of each distinct value.
2895
+ #
2896
+ # @return [Expr]
2897
+ #
2898
+ # @example
2899
+ # df = Polars::DataFrame.new({"a" => [1, 1, 2, 3, 2]})
2900
+ # df.with_columns(Polars.col("a").is_last_distinct.alias("last"))
2901
+ # # =>
2902
+ # # shape: (5, 2)
2903
+ # # ┌─────┬───────┐
2904
+ # # │ a ┆ last │
2905
+ # # │ --- ┆ --- │
2906
+ # # │ i64 ┆ bool │
2907
+ # # ╞═════╪═══════╡
2908
+ # # │ 1 ┆ false │
2909
+ # # │ 1 ┆ true │
2910
+ # # │ 2 ┆ false │
2911
+ # # │ 3 ┆ true │
2912
+ # # │ 2 ┆ true │
2913
+ # # └─────┴───────┘
2914
+ def is_last_distinct
2915
+ wrap_expr(_rbexpr.is_last_distinct)
2916
+ end
2917
+
2446
2918
  # Get mask of duplicated values.
2447
2919
  #
2448
2920
  # @return [Expr]
@@ -2462,7 +2934,7 @@ module Polars
2462
2934
  # # │ false │
2463
2935
  # # └───────┘
2464
2936
  def is_duplicated
2465
- _from_rbexpr(_rbexpr.is_duplicated)
2937
+ wrap_expr(_rbexpr.is_duplicated)
2466
2938
  end
2467
2939
 
2468
2940
  # Get a boolean mask of the local maximum peaks.
@@ -2486,7 +2958,7 @@ module Polars
2486
2958
  # # │ true │
2487
2959
  # # └───────┘
2488
2960
  def peak_max
2489
- _from_rbexpr(_rbexpr.peak_max)
2961
+ wrap_expr(_rbexpr.peak_max)
2490
2962
  end
2491
2963
 
2492
2964
  # Get a boolean mask of the local minimum peaks.
@@ -2510,7 +2982,7 @@ module Polars
2510
2982
  # # │ false │
2511
2983
  # # └───────┘
2512
2984
  def peak_min
2513
- _from_rbexpr(_rbexpr.peak_min)
2985
+ wrap_expr(_rbexpr.peak_min)
2514
2986
  end
2515
2987
 
2516
2988
  # Get quantile value.
@@ -2584,7 +3056,7 @@ module Polars
2584
3056
  # # └─────┘
2585
3057
  def quantile(quantile, interpolation: "nearest")
2586
3058
  quantile = Utils.parse_into_expression(quantile, str_as_lit: false)
2587
- _from_rbexpr(_rbexpr.quantile(quantile, interpolation))
3059
+ wrap_expr(_rbexpr.quantile(quantile, interpolation))
2588
3060
  end
2589
3061
 
2590
3062
  # Bin continuous values into discrete categories.
@@ -2640,7 +3112,7 @@ module Polars
2640
3112
  # # │ 2 ┆ inf ┆ (1, inf] │
2641
3113
  # # └─────┴────────────┴────────────┘
2642
3114
  def cut(breaks, labels: nil, left_closed: false, include_breaks: false)
2643
- _from_rbexpr(_rbexpr.cut(breaks, labels, left_closed, include_breaks))
3115
+ wrap_expr(_rbexpr.cut(breaks, labels, left_closed, include_breaks))
2644
3116
  end
2645
3117
 
2646
3118
  # Bin continuous values into discrete categories based on their quantiles.
@@ -2731,7 +3203,7 @@ module Polars
2731
3203
  )
2732
3204
  end
2733
3205
 
2734
- _from_rbexpr(rbexpr)
3206
+ wrap_expr(rbexpr)
2735
3207
  end
2736
3208
 
2737
3209
  # Get the lengths of runs of identical values.
@@ -2756,7 +3228,7 @@ module Polars
2756
3228
  # # │ 2 ┆ 3 │
2757
3229
  # # └─────┴───────┘
2758
3230
  def rle
2759
- _from_rbexpr(_rbexpr.rle)
3231
+ wrap_expr(_rbexpr.rle)
2760
3232
  end
2761
3233
 
2762
3234
  # Map values to run IDs.
@@ -2784,7 +3256,7 @@ module Polars
2784
3256
  # # │ 1 ┆ y ┆ 2 ┆ 3 │
2785
3257
  # # └─────┴──────┴─────┴──────┘
2786
3258
  def rle_id
2787
- _from_rbexpr(_rbexpr.rle_id)
3259
+ wrap_expr(_rbexpr.rle_id)
2788
3260
  end
2789
3261
 
2790
3262
  # Filter a single column.
@@ -2823,7 +3295,7 @@ module Polars
2823
3295
  # # │ g2 ┆ 0 ┆ 3 │
2824
3296
  # # └───────────┴─────┴─────┘
2825
3297
  def filter(predicate)
2826
- _from_rbexpr(_rbexpr.filter(predicate._rbexpr))
3298
+ wrap_expr(_rbexpr.filter(predicate._rbexpr))
2827
3299
  end
2828
3300
 
2829
3301
  # Filter a single column.
@@ -2904,7 +3376,7 @@ module Polars
2904
3376
  # if !return_dtype.nil?
2905
3377
  # return_dtype = Utils.rb_type_to_dtype(return_dtype)
2906
3378
  # end
2907
- # _from_rbexpr(
3379
+ # wrap_expr(
2908
3380
  # _rbexpr.map_batches(
2909
3381
  # # TODO _map_batches_wrapper
2910
3382
  # f,
@@ -3036,7 +3508,7 @@ module Polars
3036
3508
  # # │ b ┆ [2, 3, 4] │
3037
3509
  # # └───────┴───────────┘
3038
3510
  def flatten
3039
- _from_rbexpr(_rbexpr.explode)
3511
+ wrap_expr(_rbexpr.explode)
3040
3512
  end
3041
3513
 
3042
3514
  # Explode a list or utf8 Series.
@@ -3063,7 +3535,7 @@ module Polars
3063
3535
  # # │ 6 │
3064
3536
  # # └─────┘
3065
3537
  def explode
3066
- _from_rbexpr(_rbexpr.explode)
3538
+ wrap_expr(_rbexpr.explode)
3067
3539
  end
3068
3540
 
3069
3541
  # Take every nth value in the Series and return as a new Series.
@@ -3085,7 +3557,7 @@ module Polars
3085
3557
  # # │ 7 │
3086
3558
  # # └─────┘
3087
3559
  def gather_every(n, offset = 0)
3088
- _from_rbexpr(_rbexpr.gather_every(n, offset))
3560
+ wrap_expr(_rbexpr.gather_every(n, offset))
3089
3561
  end
3090
3562
  alias_method :take_every, :gather_every
3091
3563
 
@@ -3111,7 +3583,7 @@ module Polars
3111
3583
  # # │ 3 │
3112
3584
  # # └─────┘
3113
3585
  def head(n = 10)
3114
- _from_rbexpr(_rbexpr.head(n))
3586
+ wrap_expr(_rbexpr.head(n))
3115
3587
  end
3116
3588
 
3117
3589
  # Get the last `n` rows.
@@ -3136,7 +3608,7 @@ module Polars
3136
3608
  # # │ 7 │
3137
3609
  # # └─────┘
3138
3610
  def tail(n = 10)
3139
- _from_rbexpr(_rbexpr.tail(n))
3611
+ wrap_expr(_rbexpr.tail(n))
3140
3612
  end
3141
3613
 
3142
3614
  # Get the first `n` rows.
@@ -3166,6 +3638,89 @@ module Polars
3166
3638
  head(n)
3167
3639
  end
3168
3640
 
3641
+ # Method equivalent of bitwise "and" operator `expr & other & ...`.
3642
+ #
3643
+ # @param others [Array]
3644
+ # One or more integer or boolean expressions to evaluate/combine.
3645
+ #
3646
+ # @return [Expr]
3647
+ #
3648
+ # @example
3649
+ # df = Polars::DataFrame.new(
3650
+ # {
3651
+ # "x" => [5, 6, 7, 4, 8],
3652
+ # "y" => [1.5, 2.5, 1.0, 4.0, -5.75],
3653
+ # "z" => [-9, 2, -1, 4, 8]
3654
+ # }
3655
+ # )
3656
+ # df.select(
3657
+ # (Polars.col("x") >= Polars.col("z"))
3658
+ # .and_(
3659
+ # Polars.col("y") >= Polars.col("z"),
3660
+ # Polars.col("y") == Polars.col("y"),
3661
+ # Polars.col("z") <= Polars.col("x"),
3662
+ # Polars.col("y") != Polars.col("x"),
3663
+ # )
3664
+ # .alias("all")
3665
+ # )
3666
+ # # =>
3667
+ # # shape: (5, 1)
3668
+ # # ┌───────┐
3669
+ # # │ all │
3670
+ # # │ --- │
3671
+ # # │ bool │
3672
+ # # ╞═══════╡
3673
+ # # │ true │
3674
+ # # │ true │
3675
+ # # │ true │
3676
+ # # │ false │
3677
+ # # │ false │
3678
+ # # └───────┘
3679
+ def and_(*others)
3680
+ ([self] + others).reduce(:&)
3681
+ end
3682
+
3683
+ # Method equivalent of bitwise "or" operator `expr | other | ...`.
3684
+ #
3685
+ # @param others [Array]
3686
+ # One or more integer or boolean expressions to evaluate/combine.
3687
+ #
3688
+ # @return [Expr]
3689
+ #
3690
+ # @example
3691
+ # df = Polars::DataFrame.new(
3692
+ # {
3693
+ # "x" => [5, 6, 7, 4, 8],
3694
+ # "y" => [1.5, 2.5, 1.0, 4.0, -5.75],
3695
+ # "z" => [-9, 2, -1, 4, 8]
3696
+ # }
3697
+ # )
3698
+ # df.select(
3699
+ # (Polars.col("x") == Polars.col("y"))
3700
+ # .or_(
3701
+ # Polars.col("x") == Polars.col("y"),
3702
+ # Polars.col("y") == Polars.col("z"),
3703
+ # Polars.col("y").cast(Integer) == Polars.col("z"),
3704
+ # )
3705
+ # .alias("any")
3706
+ # )
3707
+ # # =>
3708
+ # # shape: (5, 1)
3709
+ # # ┌───────┐
3710
+ # # │ any │
3711
+ # # │ --- │
3712
+ # # │ bool │
3713
+ # # ╞═══════╡
3714
+ # # │ false │
3715
+ # # │ true │
3716
+ # # │ false │
3717
+ # # │ true │
3718
+ # # │ false │
3719
+ # # └───────┘
3720
+ def or_(*others)
3721
+ ([self] + others).reduce(:|)
3722
+ end
3723
+
3169
3724
  # Method equivalent of equality operator `expr == other`.
3170
3725
  #
3171
3726
  # @param other [Object]
@@ -3198,7 +3753,7 @@ module Polars
3198
3753
  self == other
3199
3754
  end
3200
3755
 
3201
- # Method equivalent of equality operator `expr == other` where `None == None`.
3756
+ # Method equivalent of equality operator `expr == other` where `nil == nil`.
3202
3757
  #
3203
3758
  # This differs from default `eq` where null values are propagated.
3204
3759
  #
@@ -3234,7 +3789,7 @@ module Polars
3234
3789
  # # └──────┴──────┴────────┴────────────────┘
3235
3790
  def eq_missing(other)
3236
3791
  other = Utils.parse_into_expression(other, str_as_lit: true)
3237
- _from_rbexpr(_rbexpr.eq_missing(other))
3792
+ wrap_expr(_rbexpr.eq_missing(other))
3238
3793
  end
3239
3794
 
3240
3795
  # Method equivalent of "greater than or equal" operator `expr >= other`.
@@ -3402,7 +3957,7 @@ module Polars
3402
3957
  self != other
3403
3958
  end
3404
3959
 
3405
- # Method equivalent of equality operator `expr != other` where `None == None`.
3960
+ # Method equivalent of equality operator `expr != other` where `nil == nil`.
3406
3961
  #
3407
3962
  # This differs from default `ne` where null values are propagated.
3408
3963
  #
@@ -3438,7 +3993,7 @@ module Polars
3438
3993
  # # └──────┴──────┴────────┴────────────────┘
3439
3994
  def ne_missing(other)
3440
3995
  other = Utils.parse_into_expression(other, str_as_lit: true)
3441
- _from_rbexpr(_rbexpr.neq_missing(other))
3996
+ wrap_expr(_rbexpr.neq_missing(other))
3442
3997
  end
3443
3998
 
3444
3999
  # Method equivalent of addition operator `expr + other`.
@@ -3515,7 +4070,7 @@ module Polars
3515
4070
  # # │ 5 ┆ 2.5 ┆ 2 │
3516
4071
  # # └─────┴─────┴──────┘
3517
4072
  def floordiv(other)
3518
- _from_rbexpr(_rbexpr.floordiv(_to_rbexpr(other)))
4073
+ wrap_expr(_rbexpr.floordiv(_to_rbexpr(other)))
3519
4074
  end
3520
4075
 
3521
4076
  # Method equivalent of modulus operator `expr % other`.
@@ -3741,7 +4296,7 @@ module Polars
3741
4296
  # # └───────────┴──────────────────┴──────────┘
3742
4297
  def is_in(other, nulls_equal: false)
3743
4298
  other = Utils.parse_into_expression(other)
3744
- _from_rbexpr(_rbexpr.is_in(other, nulls_equal))
4299
+ wrap_expr(_rbexpr.is_in(other, nulls_equal))
3745
4300
  end
3746
4301
  alias_method :in?, :is_in
3747
4302
 
@@ -3777,7 +4332,7 @@ module Polars
3777
4332
  # # └─────────────────┘
3778
4333
  def repeat_by(by)
3779
4334
  by = Utils.parse_into_expression(by, str_as_lit: false)
3780
- _from_rbexpr(_rbexpr.repeat_by(by))
4335
+ wrap_expr(_rbexpr.repeat_by(by))
3781
4336
  end
3782
4337
 
3783
4338
  # Check if this expression is between start and end.
@@ -3850,11 +4405,48 @@ module Polars
3850
4405
  lower_bound = Utils.parse_into_expression(lower_bound)
3851
4406
  upper_bound = Utils.parse_into_expression(upper_bound)
3852
4407
 
3853
- _from_rbexpr(
4408
+ wrap_expr(
3854
4409
  _rbexpr.is_between(lower_bound, upper_bound, closed)
3855
4410
  )
3856
4411
  end
3857
4412
 
4413
+ # Check if this expression is close, i.e. almost equal, to the other expression.
4414
+ #
4415
+ # @param abs_tol [Float]
4416
+ # Absolute tolerance. This is the maximum allowed absolute difference between
4417
+ # two values. Must be non-negative.
4418
+ # @param rel_tol [Float]
4419
+ # Relative tolerance. This is the maximum allowed difference between two
4420
+ # values, relative to the larger absolute value. Must be in the range [0, 1).
4421
+ # @param nans_equal [Boolean]
4422
+ # Whether NaN values should be considered equal.
4423
+ #
4424
+ # @return [Expr]
4425
+ #
4426
+ # @example
4427
+ # df = Polars::DataFrame.new({"a" => [1.5, 2.0, 2.5], "b" => [1.55, 2.2, 3.0]})
4428
+ # df.with_columns(Polars.col("a").is_close("b", abs_tol: 0.1).alias("is_close"))
4429
+ # # =>
4430
+ # # shape: (3, 3)
4431
+ # # ┌─────┬──────┬──────────┐
4432
+ # # │ a ┆ b ┆ is_close │
4433
+ # # │ --- ┆ --- ┆ --- │
4434
+ # # │ f64 ┆ f64 ┆ bool │
4435
+ # # ╞═════╪══════╪══════════╡
4436
+ # # │ 1.5 ┆ 1.55 ┆ true │
4437
+ # # │ 2.0 ┆ 2.2 ┆ false │
4438
+ # # │ 2.5 ┆ 3.0 ┆ false │
4439
+ # # └─────┴──────┴──────────┘
4440
+ def is_close(
4441
+ other,
4442
+ abs_tol: 0.0,
4443
+ rel_tol: 1e-09,
4444
+ nans_equal: false
4445
+ )
4446
+ other = Utils.parse_into_expression(other)
4447
+ wrap_expr(_rbexpr.is_close(other, abs_tol, rel_tol, nans_equal))
4448
+ end
4449
+
3858
4450
  # Hash the elements in the selection.
3859
4451
  #
3860
4452
  # The hash value is of type `:u64`.
@@ -3894,7 +4486,7 @@ module Polars
3894
4486
  k1 = seed_1.nil? ? seed : seed_1
3895
4487
  k2 = seed_2.nil? ? seed : seed_2
3896
4488
  k3 = seed_3.nil? ? seed : seed_3
3897
- _from_rbexpr(_rbexpr._hash(k0, k1, k2, k3))
4489
+ wrap_expr(_rbexpr._hash(k0, k1, k2, k3))
3898
4490
  end
3899
4491
 
3900
4492
  # Reinterpret the underlying bits as a signed/unsigned integer.
@@ -3928,7 +4520,7 @@ module Polars
3928
4520
  # # │ 2 ┆ 2 │
3929
4521
  # # └───────────────┴──────────┘
3930
4522
  def reinterpret(signed: false)
3931
- _from_rbexpr(_rbexpr.reinterpret(signed))
4523
+ wrap_expr(_rbexpr.reinterpret(signed))
3932
4524
  end
3933
4525
 
3934
4526
  # Print the value that this expression evaluates to and pass on the value.
@@ -3991,7 +4583,7 @@ module Polars
3991
4583
  # # │ 3.0 ┆ 3.0 │
3992
4584
  # # └─────┴─────┘
3993
4585
  def interpolate(method: "linear")
3994
- _from_rbexpr(_rbexpr.interpolate(method))
4586
+ wrap_expr(_rbexpr.interpolate(method))
3995
4587
  end
3996
4588
 
3997
4589
  # Fill null values using interpolation based on another column.
@@ -4022,7 +4614,7 @@ module Polars
4022
4614
  # # └──────┴─────┴────────────────┘
4023
4615
  def interpolate_by(by)
4024
4616
  by = Utils.parse_into_expression(by)
4025
- _from_rbexpr(_rbexpr.interpolate_by(by))
4617
+ wrap_expr(_rbexpr.interpolate_by(by))
4026
4618
  end
4027
4619
 
4028
4620
  # Apply a rolling min based on another column.
@@ -4123,7 +4715,7 @@ module Polars
4123
4715
  )
4124
4716
  window_size = _prepare_rolling_by_window_args(window_size)
4125
4717
  by = Utils.parse_into_expression(by)
4126
- _from_rbexpr(
4718
+ wrap_expr(
4127
4719
  _rbexpr.rolling_min_by(by, window_size, min_periods, closed)
4128
4720
  )
4129
4721
  end
@@ -4252,7 +4844,7 @@ module Polars
4252
4844
  )
4253
4845
  window_size = _prepare_rolling_by_window_args(window_size)
4254
4846
  by = Utils.parse_into_expression(by)
4255
- _from_rbexpr(
4847
+ wrap_expr(
4256
4848
  _rbexpr.rolling_max_by(by, window_size, min_periods, closed)
4257
4849
  )
4258
4850
  end
@@ -4383,7 +4975,7 @@ module Polars
4383
4975
  )
4384
4976
  window_size = _prepare_rolling_by_window_args(window_size)
4385
4977
  by = Utils.parse_into_expression(by)
4386
- _from_rbexpr(
4978
+ wrap_expr(
4387
4979
  _rbexpr.rolling_mean_by(
4388
4980
  by,
4389
4981
  window_size,
@@ -4517,7 +5109,7 @@ module Polars
4517
5109
  )
4518
5110
  window_size = _prepare_rolling_by_window_args(window_size)
4519
5111
  by = Utils.parse_into_expression(by)
4520
- _from_rbexpr(
5112
+ wrap_expr(
4521
5113
  _rbexpr.rolling_sum_by(by, window_size, min_periods, closed)
4522
5114
  )
4523
5115
  end
@@ -4649,7 +5241,7 @@ module Polars
4649
5241
  )
4650
5242
  window_size = _prepare_rolling_by_window_args(window_size)
4651
5243
  by = Utils.parse_into_expression(by)
4652
- _from_rbexpr(
5244
+ wrap_expr(
4653
5245
  _rbexpr.rolling_std_by(
4654
5246
  by,
4655
5247
  window_size,
@@ -4787,7 +5379,7 @@ module Polars
4787
5379
  )
4788
5380
  window_size = _prepare_rolling_by_window_args(window_size)
4789
5381
  by = Utils.parse_into_expression(by)
4790
- _from_rbexpr(
5382
+ wrap_expr(
4791
5383
  _rbexpr.rolling_var_by(
4792
5384
  by,
4793
5385
  window_size,
@@ -4898,7 +5490,7 @@ module Polars
4898
5490
  )
4899
5491
  window_size = _prepare_rolling_by_window_args(window_size)
4900
5492
  by = Utils.parse_into_expression(by)
4901
- _from_rbexpr(
5493
+ wrap_expr(
4902
5494
  _rbexpr.rolling_median_by(by, window_size, min_periods, closed)
4903
5495
  )
4904
5496
  end
@@ -5009,7 +5601,7 @@ module Polars
5009
5601
  )
5010
5602
  window_size = _prepare_rolling_by_window_args(window_size)
5011
5603
  by = Utils.parse_into_expression(by)
5012
- _from_rbexpr(
5604
+ wrap_expr(
5013
5605
  _rbexpr.rolling_quantile_by(
5014
5606
  by,
5015
5607
  quantile,
@@ -5050,7 +5642,7 @@ module Polars
5050
5642
  # elementwise with the values in the window.
5051
5643
  # @param min_periods [Integer]
5052
5644
  # The number of values in the window that should be non-null before computing
5053
- # a result. If None, it will be set equal to window size.
5645
+ # a result. If nil, it will be set equal to window size.
5054
5646
  # @param center [Boolean]
5055
5647
  # Set the labels at the center of the window
5056
5648
  #
@@ -5092,7 +5684,7 @@ module Polars
5092
5684
  min_periods: nil,
5093
5685
  center: false
5094
5686
  )
5095
- _from_rbexpr(
5687
+ wrap_expr(
5096
5688
  _rbexpr.rolling_min(
5097
5689
  window_size, weights, min_periods, center
5098
5690
  )
@@ -5128,7 +5720,7 @@ module Polars
5128
5720
  # elementwise with the values in the window.
5129
5721
  # @param min_periods [Integer]
5130
5722
  # The number of values in the window that should be non-null before computing
5131
- # a result. If None, it will be set equal to window size.
5723
+ # a result. If nil, it will be set equal to window size.
5132
5724
  # @param center [Boolean]
5133
5725
  # Set the labels at the center of the window
5134
5726
  #
@@ -5170,7 +5762,7 @@ module Polars
5170
5762
  min_periods: nil,
5171
5763
  center: false
5172
5764
  )
5173
- _from_rbexpr(
5765
+ wrap_expr(
5174
5766
  _rbexpr.rolling_max(
5175
5767
  window_size, weights, min_periods, center
5176
5768
  )
@@ -5206,7 +5798,7 @@ module Polars
5206
5798
  # elementwise with the values in the window.
5207
5799
  # @param min_periods [Integer]
5208
5800
  # The number of values in the window that should be non-null before computing
5209
- # a result. If None, it will be set equal to window size.
5801
+ # a result. If nil, it will be set equal to window size.
5210
5802
  # @param center [Boolean]
5211
5803
  # Set the labels at the center of the window
5212
5804
  #
@@ -5248,7 +5840,7 @@ module Polars
5248
5840
  min_periods: nil,
5249
5841
  center: false
5250
5842
  )
5251
- _from_rbexpr(
5843
+ wrap_expr(
5252
5844
  _rbexpr.rolling_mean(
5253
5845
  window_size, weights, min_periods, center
5254
5846
  )
@@ -5284,7 +5876,7 @@ module Polars
5284
5876
  # elementwise with the values in the window.
5285
5877
  # @param min_periods [Integer]
5286
5878
  # The number of values in the window that should be non-null before computing
5287
- # a result. If None, it will be set equal to window size.
5879
+ # a result. If nil, it will be set equal to window size.
5288
5880
  # @param center [Boolean]
5289
5881
  # Set the labels at the center of the window
5290
5882
  #
@@ -5326,7 +5918,7 @@ module Polars
5326
5918
  min_periods: nil,
5327
5919
  center: false
5328
5920
  )
5329
- _from_rbexpr(
5921
+ wrap_expr(
5330
5922
  _rbexpr.rolling_sum(
5331
5923
  window_size, weights, min_periods, center
5332
5924
  )
@@ -5362,7 +5954,7 @@ module Polars
5362
5954
  # elementwise with the values in the window.
5363
5955
  # @param min_periods [Integer]
5364
5956
  # The number of values in the window that should be non-null before computing
5365
- # a result. If None, it will be set equal to window size.
5957
+ # a result. If nil, it will be set equal to window size.
5366
5958
  # @param center [Boolean]
5367
5959
  # Set the labels at the center of the window
5368
5960
  # @param ddof [Integer]
@@ -5407,7 +5999,7 @@ module Polars
5407
5999
  center: false,
5408
6000
  ddof: 1
5409
6001
  )
5410
- _from_rbexpr(
6002
+ wrap_expr(
5411
6003
  _rbexpr.rolling_std(
5412
6004
  window_size, weights, min_periods, center, ddof
5413
6005
  )
@@ -5443,7 +6035,7 @@ module Polars
5443
6035
  # elementwise with the values in the window.
5444
6036
  # @param min_periods [Integer]
5445
6037
  # The number of values in the window that should be non-null before computing
5446
- # a result. If None, it will be set equal to window size.
6038
+ # a result. If nil, it will be set equal to window size.
5447
6039
  # @param center [Boolean]
5448
6040
  # Set the labels at the center of the window
5449
6041
  # @param ddof [Integer]
@@ -5488,7 +6080,7 @@ module Polars
5488
6080
  center: false,
5489
6081
  ddof: 1
5490
6082
  )
5491
- _from_rbexpr(
6083
+ wrap_expr(
5492
6084
  _rbexpr.rolling_var(
5493
6085
  window_size, weights, min_periods, center, ddof
5494
6086
  )
@@ -5520,7 +6112,7 @@ module Polars
5520
6112
  # elementwise with the values in the window.
5521
6113
  # @param min_periods [Integer]
5522
6114
  # The number of values in the window that should be non-null before computing
5523
- # a result. If None, it will be set equal to window size.
6115
+ # a result. If nil, it will be set equal to window size.
5524
6116
  # @param center [Boolean]
5525
6117
  # Set the labels at the center of the window
5526
6118
  #
@@ -5562,7 +6154,7 @@ module Polars
5562
6154
  min_periods: nil,
5563
6155
  center: false
5564
6156
  )
5565
- _from_rbexpr(
6157
+ wrap_expr(
5566
6158
  _rbexpr.rolling_median(
5567
6159
  window_size, weights, min_periods, center
5568
6160
  )
@@ -5598,7 +6190,7 @@ module Polars
5598
6190
  # elementwise with the values in the window.
5599
6191
  # @param min_periods [Integer]
5600
6192
  # The number of values in the window that should be non-null before computing
5601
- # a result. If None, it will be set equal to window size.
6193
+ # a result. If nil, it will be set equal to window size.
5602
6194
  # @param center [Boolean]
5603
6195
  # Set the labels at the center of the window
5604
6196
  #
@@ -5642,7 +6234,7 @@ module Polars
5642
6234
  min_periods: nil,
5643
6235
  center: false
5644
6236
  )
5645
- _from_rbexpr(
6237
+ wrap_expr(
5646
6238
  _rbexpr.rolling_quantile(
5647
6239
  quantile, interpolation, window_size, weights, min_periods, center
5648
6240
  )
@@ -5706,7 +6298,7 @@ module Polars
5706
6298
  # if min_periods.nil?
5707
6299
  # min_periods = window_size
5708
6300
  # end
5709
- # _from_rbexpr(
6301
+ # wrap_expr(
5710
6302
  # _rbexpr.rolling_apply(
5711
6303
  # function, window_size, weights, min_periods, center
5712
6304
  # )
@@ -5743,7 +6335,64 @@ module Polars
5743
6335
  # # │ 0.47033 │
5744
6336
  # # └──────────┘
5745
6337
  def rolling_skew(window_size, bias: true, min_samples: nil, center: false)
5746
- _from_rbexpr(_rbexpr.rolling_skew(window_size, bias, min_samples, center))
6338
+ wrap_expr(_rbexpr.rolling_skew(window_size, bias, min_samples, center))
6339
+ end
6340
+
6341
+ # Compute a rolling kurtosis.
6342
+ #
6343
+ # @note
6344
+ # This functionality is considered **unstable**. It may be changed
6345
+ # at any point without it being considered a breaking change.
6346
+ #
6347
+ # The window at a given row will include the row itself, and the `window_size - 1`
6348
+ # elements before it.
6349
+ #
6350
+ # @param window_size [Integer]
6351
+ # Integer size of the rolling window.
6352
+ # @param fisher [Boolean]
6353
+ # If true, Fisher's definition is used (normal ==> 0.0). If false,
6354
+ # Pearson's definition is used (normal ==> 3.0).
6355
+ # @param bias [Boolean]
6356
+ # If false, the calculations are corrected for statistical bias.
6357
+ # @param min_samples [Integer]
6358
+ # The number of values in the window that should be non-null before computing
6359
+ # a result. If set to `nil` (default), it will be set equal to `window_size`.
6360
+ # @param center
6361
+ # Set the labels at the center of the window.
6362
+ #
6363
+ # @return [Expr]
6364
+ #
6365
+ # @example
6366
+ # df = Polars::DataFrame.new({"a" => [1, 4, 2, 9]})
6367
+ # df.select(Polars.col("a").rolling_kurtosis(3))
6368
+ # # =>
6369
+ # # shape: (4, 1)
6370
+ # # ┌──────┐
6371
+ # # │ a │
6372
+ # # │ --- │
6373
+ # # │ f64 │
6374
+ # # ╞══════╡
6375
+ # # │ null │
6376
+ # # │ null │
6377
+ # # │ -1.5 │
6378
+ # # │ -1.5 │
6379
+ # # └──────┘
6380
+ def rolling_kurtosis(
6381
+ window_size,
6382
+ fisher: true,
6383
+ bias: true,
6384
+ min_samples: nil,
6385
+ center: false
6386
+ )
6387
+ wrap_expr(
6388
+ _rbexpr.rolling_kurtosis(
6389
+ window_size,
6390
+ fisher,
6391
+ bias,
6392
+ min_samples,
6393
+ center
6394
+ )
6395
+ )
5747
6396
  end
5748
6397
 
5749
6398
  # Compute absolute values.
@@ -5770,7 +6419,7 @@ module Polars
5770
6419
  # # │ 2.0 │
5771
6420
  # # └─────┘
5772
6421
  def abs
5773
- _from_rbexpr(_rbexpr.abs)
6422
+ wrap_expr(_rbexpr.abs)
5774
6423
  end
5775
6424
 
5776
6425
  # Get the index values that would sort this column.
@@ -5867,7 +6516,7 @@ module Polars
5867
6516
  # # │ 5 │
5868
6517
  # # └─────┘
5869
6518
  def rank(method: "average", reverse: false, seed: nil)
5870
- _from_rbexpr(_rbexpr.rank(method, reverse, seed))
6519
+ wrap_expr(_rbexpr.rank(method, reverse, seed))
5871
6520
  end
5872
6521
 
5873
6522
  # Calculate the n-th discrete difference.
@@ -5899,7 +6548,7 @@ module Polars
5899
6548
  # # └──────┘
5900
6549
  def diff(n: 1, null_behavior: "ignore")
5901
6550
  n = Utils.parse_into_expression(n)
5902
- _from_rbexpr(_rbexpr.diff(n, null_behavior))
6551
+ wrap_expr(_rbexpr.diff(n, null_behavior))
5903
6552
  end
5904
6553
 
5905
6554
  # Computes percentage change between values.
@@ -5936,7 +6585,7 @@ module Polars
5936
6585
  # # └──────┴────────────┘
5937
6586
  def pct_change(n: 1)
5938
6587
  n = Utils.parse_into_expression(n)
5939
- _from_rbexpr(_rbexpr.pct_change(n))
6588
+ wrap_expr(_rbexpr.pct_change(n))
5940
6589
  end
5941
6590
 
5942
6591
  # Compute the sample skewness of a data set.
@@ -5965,7 +6614,7 @@ module Polars
5965
6614
  # # │ 0.343622 │
5966
6615
  # # └──────────┘
5967
6616
  def skew(bias: true)
5968
- _from_rbexpr(_rbexpr.skew(bias))
6617
+ wrap_expr(_rbexpr.skew(bias))
5969
6618
  end
5970
6619
 
5971
6620
  # Compute the kurtosis (Fisher or Pearson) of a dataset.
@@ -5997,7 +6646,7 @@ module Polars
5997
6646
  # # │ -1.153061 │
5998
6647
  # # └───────────┘
5999
6648
  def kurtosis(fisher: true, bias: true)
6000
- _from_rbexpr(_rbexpr.kurtosis(fisher, bias))
6649
+ wrap_expr(_rbexpr.kurtosis(fisher, bias))
6001
6650
  end
6002
6651
 
6003
6652
  # Set values outside the given boundaries to the boundary value.
@@ -6034,7 +6683,7 @@ module Polars
6034
6683
  if !upper_bound.nil?
6035
6684
  upper_bound = Utils.parse_into_expression(upper_bound)
6036
6685
  end
6037
- _from_rbexpr(_rbexpr.clip(lower_bound, upper_bound))
6686
+ wrap_expr(_rbexpr.clip(lower_bound, upper_bound))
6038
6687
  end
6039
6688
 
6040
6689
  # Clip (limit) the values in an array to a `min` boundary.
@@ -6119,7 +6768,7 @@ module Polars
6119
6768
  # # │ -9223372036854775808 │
6120
6769
  # # └──────────────────────┘
6121
6770
  def lower_bound
6122
- _from_rbexpr(_rbexpr.lower_bound)
6771
+ wrap_expr(_rbexpr.lower_bound)
6123
6772
  end
6124
6773
 
6125
6774
  # Calculate the upper bound.
@@ -6142,7 +6791,7 @@ module Polars
6142
6791
  # # │ 9223372036854775807 │
6143
6792
  # # └─────────────────────┘
6144
6793
  def upper_bound
6145
- _from_rbexpr(_rbexpr.upper_bound)
6794
+ wrap_expr(_rbexpr.upper_bound)
6146
6795
  end
6147
6796
 
6148
6797
  # Compute the element-wise indication of the sign.
@@ -6166,7 +6815,7 @@ module Polars
6166
6815
  # # │ null │
6167
6816
  # # └──────┘
6168
6817
  def sign
6169
- _from_rbexpr(_rbexpr.sign)
6818
+ wrap_expr(_rbexpr.sign)
6170
6819
  end
6171
6820
 
6172
6821
  # Compute the element-wise value for the sine.
@@ -6186,7 +6835,7 @@ module Polars
6186
6835
  # # │ 0.0 │
6187
6836
  # # └─────┘
6188
6837
  def sin
6189
- _from_rbexpr(_rbexpr.sin)
6838
+ wrap_expr(_rbexpr.sin)
6190
6839
  end
6191
6840
 
6192
6841
  # Compute the element-wise value for the cosine.
@@ -6206,7 +6855,7 @@ module Polars
6206
6855
  # # │ 1.0 │
6207
6856
  # # └─────┘
6208
6857
  def cos
6209
- _from_rbexpr(_rbexpr.cos)
6858
+ wrap_expr(_rbexpr.cos)
6210
6859
  end
6211
6860
 
6212
6861
  # Compute the element-wise value for the tangent.
@@ -6226,7 +6875,27 @@ module Polars
6226
6875
  # # │ 1.557408 │
6227
6876
  # # └──────────┘
6228
6877
  def tan
6229
- _from_rbexpr(_rbexpr.tan)
6878
+ wrap_expr(_rbexpr.tan)
6879
+ end
6880
+
6881
+ # Compute the element-wise value for the cotangent.
6882
+ #
6883
+ # @return [Expr]
6884
+ #
6885
+ # @example
6886
+ # df = Polars::DataFrame.new({"a" => [1.0]})
6887
+ # df.select(Polars.col("a").cot.round(2))
6888
+ # # =>
6889
+ # # shape: (1, 1)
6890
+ # # ┌──────┐
6891
+ # # │ a │
6892
+ # # │ --- │
6893
+ # # │ f64 │
6894
+ # # ╞══════╡
6895
+ # # │ 0.64 │
6896
+ # # └──────┘
6897
+ def cot
6898
+ wrap_expr(_rbexpr.cot)
6230
6899
  end
6231
6900
 
6232
6901
  # Compute the element-wise value for the inverse sine.
@@ -6246,7 +6915,7 @@ module Polars
6246
6915
  # # │ 1.570796 │
6247
6916
  # # └──────────┘
6248
6917
  def arcsin
6249
- _from_rbexpr(_rbexpr.arcsin)
6918
+ wrap_expr(_rbexpr.arcsin)
6250
6919
  end
6251
6920
 
6252
6921
  # Compute the element-wise value for the inverse cosine.
@@ -6266,7 +6935,7 @@ module Polars
6266
6935
  # # │ 1.570796 │
6267
6936
  # # └──────────┘
6268
6937
  def arccos
6269
- _from_rbexpr(_rbexpr.arccos)
6938
+ wrap_expr(_rbexpr.arccos)
6270
6939
  end
6271
6940
 
6272
6941
  # Compute the element-wise value for the inverse tangent.
@@ -6286,7 +6955,7 @@ module Polars
6286
6955
  # # │ 0.785398 │
6287
6956
  # # └──────────┘
6288
6957
  def arctan
6289
- _from_rbexpr(_rbexpr.arctan)
6958
+ wrap_expr(_rbexpr.arctan)
6290
6959
  end
6291
6960
 
6292
6961
  # Compute the element-wise value for the hyperbolic sine.
@@ -6306,7 +6975,7 @@ module Polars
6306
6975
  # # │ 1.175201 │
6307
6976
  # # └──────────┘
6308
6977
  def sinh
6309
- _from_rbexpr(_rbexpr.sinh)
6978
+ wrap_expr(_rbexpr.sinh)
6310
6979
  end
6311
6980
 
6312
6981
  # Compute the element-wise value for the hyperbolic cosine.
@@ -6326,7 +6995,7 @@ module Polars
6326
6995
  # # │ 1.543081 │
6327
6996
  # # └──────────┘
6328
6997
  def cosh
6329
- _from_rbexpr(_rbexpr.cosh)
6998
+ wrap_expr(_rbexpr.cosh)
6330
6999
  end
6331
7000
 
6332
7001
  # Compute the element-wise value for the hyperbolic tangent.
@@ -6346,7 +7015,7 @@ module Polars
6346
7015
  # # │ 0.761594 │
6347
7016
  # # └──────────┘
6348
7017
  def tanh
6349
- _from_rbexpr(_rbexpr.tanh)
7018
+ wrap_expr(_rbexpr.tanh)
6350
7019
  end
6351
7020
 
6352
7021
  # Compute the element-wise value for the inverse hyperbolic sine.
@@ -6366,7 +7035,7 @@ module Polars
6366
7035
  # # │ 0.881374 │
6367
7036
  # # └──────────┘
6368
7037
  def arcsinh
6369
- _from_rbexpr(_rbexpr.arcsinh)
7038
+ wrap_expr(_rbexpr.arcsinh)
6370
7039
  end
6371
7040
 
6372
7041
  # Compute the element-wise value for the inverse hyperbolic cosine.
@@ -6386,7 +7055,7 @@ module Polars
6386
7055
  # # │ 0.0 │
6387
7056
  # # └─────┘
6388
7057
  def arccosh
6389
- _from_rbexpr(_rbexpr.arccosh)
7058
+ wrap_expr(_rbexpr.arccosh)
6390
7059
  end
6391
7060
 
6392
7061
  # Compute the element-wise value for the inverse hyperbolic tangent.
@@ -6406,7 +7075,63 @@ module Polars
6406
7075
  # # │ inf │
6407
7076
  # # └─────┘
6408
7077
  def arctanh
6409
- _from_rbexpr(_rbexpr.arctanh)
7078
+ wrap_expr(_rbexpr.arctanh)
7079
+ end
7080
+
7081
+ # Convert from radians to degrees.
7082
+ #
7083
+ # @return [Expr]
7084
+ #
7085
+ # @example
7086
+ # df = Polars::DataFrame.new({"a" => (-4...5).map { |x| x * Math::PI }})
7087
+ # df.select(Polars.col("a").degrees)
7088
+ # # =>
7089
+ # # shape: (9, 1)
7090
+ # # ┌────────┐
7091
+ # # │ a │
7092
+ # # │ --- │
7093
+ # # │ f64 │
7094
+ # # ╞════════╡
7095
+ # # │ -720.0 │
7096
+ # # │ -540.0 │
7097
+ # # │ -360.0 │
7098
+ # # │ -180.0 │
7099
+ # # │ 0.0 │
7100
+ # # │ 180.0 │
7101
+ # # │ 360.0 │
7102
+ # # │ 540.0 │
7103
+ # # │ 720.0 │
7104
+ # # └────────┘
7105
+ def degrees
7106
+ wrap_expr(_rbexpr.degrees)
7107
+ end
7108
+
7109
+ # Convert from degrees to radians.
7110
+ #
7111
+ # @return [Expr]
7112
+ #
7113
+ # @example
7114
+ # df = Polars::DataFrame.new({"a" => [-720, -540, -360, -180, 0, 180, 360, 540, 720]})
7115
+ # df.select(Polars.col("a").radians)
7116
+ # # =>
7117
+ # # shape: (9, 1)
7118
+ # # ┌────────────┐
7119
+ # # │ a │
7120
+ # # │ --- │
7121
+ # # │ f64 │
7122
+ # # ╞════════════╡
7123
+ # # │ -12.566371 │
7124
+ # # │ -9.424778 │
7125
+ # # │ -6.283185 │
7126
+ # # │ -3.141593 │
7127
+ # # │ 0.0 │
7128
+ # # │ 3.141593 │
7129
+ # # │ 6.283185 │
7130
+ # # │ 9.424778 │
7131
+ # # │ 12.566371 │
7132
+ # # └────────────┘
7133
+ def radians
7134
+ wrap_expr(_rbexpr.radians)
6410
7135
  end
6411
7136
 
6412
7137
  # Reshape this Expr to a flat Series or a Series of Lists.
@@ -6452,13 +7177,13 @@ module Polars
6452
7177
  # # │ 9 │
6453
7178
  # # └─────┘
6454
7179
  def reshape(dims)
6455
- _from_rbexpr(_rbexpr.reshape(dims))
7180
+ wrap_expr(_rbexpr.reshape(dims))
6456
7181
  end
6457
7182
 
6458
7183
  # Shuffle the contents of this expr.
6459
7184
  #
6460
7185
  # @param seed [Integer]
6461
- # Seed for the random number generator. If set to None (default), a random
7186
+ # Seed for the random number generator. If set to nil (default), a random
6462
7187
  # seed is generated using the `random` module.
6463
7188
  #
6464
7189
  # @return [Expr]
@@ -6481,7 +7206,7 @@ module Polars
6481
7206
  if seed.nil?
6482
7207
  seed = rand(10000)
6483
7208
  end
6484
- _from_rbexpr(_rbexpr.shuffle(seed))
7209
+ wrap_expr(_rbexpr.shuffle(seed))
6485
7210
  end
6486
7211
 
6487
7212
  # Sample from this expression.
@@ -6493,7 +7218,7 @@ module Polars
6493
7218
  # @param shuffle [Boolean]
6494
7219
  # Shuffle the order of sampled data points.
6495
7220
  # @param seed [Integer]
6496
- # Seed for the random number generator. If set to None (default), a random
7221
+ # Seed for the random number generator. If set to nil (default), a random
6497
7222
  # seed is used.
6498
7223
  # @param n [Integer]
6499
7224
  # Number of items to return. Cannot be used with `frac`.
@@ -6527,14 +7252,14 @@ module Polars
6527
7252
 
6528
7253
  if !n.nil? && frac.nil?
6529
7254
  n = Utils.parse_into_expression(n)
6530
- return _from_rbexpr(_rbexpr.sample_n(n, with_replacement, shuffle, seed))
7255
+ return wrap_expr(_rbexpr.sample_n(n, with_replacement, shuffle, seed))
6531
7256
  end
6532
7257
 
6533
7258
  if frac.nil?
6534
7259
  frac = 1.0
6535
7260
  end
6536
7261
  frac = Utils.parse_into_expression(frac)
6537
- _from_rbexpr(
7262
+ wrap_expr(
6538
7263
  _rbexpr.sample_frac(frac, with_replacement, shuffle, seed)
6539
7264
  )
6540
7265
  end
@@ -6567,7 +7292,76 @@ module Polars
6567
7292
  ignore_nulls: true
6568
7293
  )
6569
7294
  alpha = _prepare_alpha(com, span, half_life, alpha)
6570
- _from_rbexpr(_rbexpr.ewm_mean(alpha, adjust, min_periods, ignore_nulls))
7295
+ wrap_expr(_rbexpr.ewm_mean(alpha, adjust, min_periods, ignore_nulls))
7296
+ end
7297
+
7298
+ # Compute time-based exponentially weighted moving average.
7299
+ #
7300
+ # @param by [Object]
7301
+ # Times to calculate average by. Should be `DateTime`, `Date`, `UInt64`,
7302
+ # `UInt32`, `Int64`, or `Int32` data type.
7303
+ # @param half_life [Object]
7304
+ # Unit over which observation decays to half its value.
7305
+ #
7306
+ # Can be created either from a timedelta, or
7307
+ # by using the following string language:
7308
+ #
7309
+ # - 1ns (1 nanosecond)
7310
+ # - 1us (1 microsecond)
7311
+ # - 1ms (1 millisecond)
7312
+ # - 1s (1 second)
7313
+ # - 1m (1 minute)
7314
+ # - 1h (1 hour)
7315
+ # - 1d (1 day)
7316
+ # - 1w (1 week)
7317
+ # - 1i (1 index count)
7318
+ #
7319
+ # Or combine them:
7320
+ # "3d12h4m25s" # 3 days, 12 hours, 4 minutes, and 25 seconds
7321
+ #
7322
+ # Note that `half_life` is treated as a constant duration - calendar
7323
+ # durations such as months (or even days in the time-zone-aware case)
7324
+ # are not supported, please express your duration in an approximately
7325
+ # equivalent number of hours (e.g. '370h' instead of '1mo').
7326
+ #
7327
+ # @return [Expr]
7328
+ #
7329
+ # @example
7330
+ # df = Polars::DataFrame.new(
7331
+ # {
7332
+ # "values": [0, 1, 2, nil, 4],
7333
+ # "times": [
7334
+ # Date.new(2020, 1, 1),
7335
+ # Date.new(2020, 1, 3),
7336
+ # Date.new(2020, 1, 10),
7337
+ # Date.new(2020, 1, 15),
7338
+ # Date.new(2020, 1, 17)
7339
+ # ]
7340
+ # }
7341
+ # ).sort("times")
7342
+ # df.with_columns(
7343
+ # result: Polars.col("values").ewm_mean_by("times", half_life: "4d")
7344
+ # )
7345
+ # # =>
7346
+ # # shape: (5, 3)
7347
+ # # ┌────────┬────────────┬──────────┐
7348
+ # # │ values ┆ times ┆ result │
7349
+ # # │ --- ┆ --- ┆ --- │
7350
+ # # │ i64 ┆ date ┆ f64 │
7351
+ # # ╞════════╪════════════╪══════════╡
7352
+ # # │ 0 ┆ 2020-01-01 ┆ 0.0 │
7353
+ # # │ 1 ┆ 2020-01-03 ┆ 0.292893 │
7354
+ # # │ 2 ┆ 2020-01-10 ┆ 1.492474 │
7355
+ # # │ null ┆ 2020-01-15 ┆ null │
7356
+ # # │ 4 ┆ 2020-01-17 ┆ 3.254508 │
7357
+ # # └────────┴────────────┴──────────┘
7358
+ def ewm_mean_by(
7359
+ by,
7360
+ half_life:
7361
+ )
7362
+ by = Utils.parse_into_expression(by)
7363
+ half_life = Utils.parse_as_duration_string(half_life)
7364
+ wrap_expr(_rbexpr.ewm_mean_by(by, half_life))
6571
7365
  end
6572
7366
 
6573
7367
  # Exponentially-weighted moving standard deviation.
@@ -6599,7 +7393,7 @@ module Polars
6599
7393
  ignore_nulls: true
6600
7394
  )
6601
7395
  alpha = _prepare_alpha(com, span, half_life, alpha)
6602
- _from_rbexpr(_rbexpr.ewm_std(alpha, adjust, bias, min_periods, ignore_nulls))
7396
+ wrap_expr(_rbexpr.ewm_std(alpha, adjust, bias, min_periods, ignore_nulls))
6603
7397
  end
6604
7398
 
6605
7399
  # Exponentially-weighted moving variance.
@@ -6631,7 +7425,7 @@ module Polars
6631
7425
  ignore_nulls: true
6632
7426
  )
6633
7427
  alpha = _prepare_alpha(com, span, half_life, alpha)
6634
- _from_rbexpr(_rbexpr.ewm_var(alpha, adjust, bias, min_periods, ignore_nulls))
7428
+ wrap_expr(_rbexpr.ewm_var(alpha, adjust, bias, min_periods, ignore_nulls))
6635
7429
  end
6636
7430
 
6637
7431
  # Extend the Series with given number of values.
@@ -6663,7 +7457,7 @@ module Polars
6663
7457
  def extend_constant(value, n)
6664
7458
  value = Utils.parse_into_expression(value, str_as_lit: true)
6665
7459
  n = Utils.parse_into_expression(n)
6666
- _from_rbexpr(_rbexpr.extend_constant(value, n))
7460
+ wrap_expr(_rbexpr.extend_constant(value, n))
6667
7461
  end
6668
7462
 
6669
7463
  # Count all unique values and create a struct mapping value to count.
@@ -6717,7 +7511,7 @@ module Polars
6717
7511
  name = "count"
6718
7512
  end
6719
7513
  end
6720
- _from_rbexpr(
7514
+ wrap_expr(
6721
7515
  _rbexpr.value_counts(sort, parallel, name, normalize)
6722
7516
  )
6723
7517
  end
@@ -6752,7 +7546,7 @@ module Polars
6752
7546
  # # │ 3 │
6753
7547
  # # └─────┘
6754
7548
  def unique_counts
6755
- _from_rbexpr(_rbexpr.unique_counts)
7549
+ wrap_expr(_rbexpr.unique_counts)
6756
7550
  end
6757
7551
 
6758
7552
  # Compute the logarithm to a given base.
@@ -6777,7 +7571,31 @@ module Polars
6777
7571
  # # │ 1.584963 │
6778
7572
  # # └──────────┘
6779
7573
  def log(base = Math::E)
6780
- _from_rbexpr(_rbexpr.log(base))
7574
+ wrap_expr(_rbexpr.log(base))
7575
+ end
7576
+
7577
+ # Compute the natural logarithm of each element plus one.
7578
+ #
7579
+ # This computes `log(1 + x)` but is more numerically stable for `x` close to zero.
7580
+ #
7581
+ # @return [Expr]
7582
+ #
7583
+ # @example
7584
+ # df = Polars::DataFrame.new({"a" => [1, 2, 3]})
7585
+ # df.select(Polars.col("a").log1p)
7586
+ # # =>
7587
+ # # shape: (3, 1)
7588
+ # # ┌──────────┐
7589
+ # # │ a │
7590
+ # # │ --- │
7591
+ # # │ f64 │
7592
+ # # ╞══════════╡
7593
+ # # │ 0.693147 │
7594
+ # # │ 1.098612 │
7595
+ # # │ 1.386294 │
7596
+ # # └──────────┘
7597
+ def log1p
7598
+ wrap_expr(_rbexpr.log1p)
6781
7599
  end
6782
7600
 
6783
7601
  # Computes the entropy.
@@ -6816,7 +7634,7 @@ module Polars
6816
7634
  # # │ -6.754888 │
6817
7635
  # # └───────────┘
6818
7636
  def entropy(base: 2, normalize: true)
6819
- _from_rbexpr(_rbexpr.entropy(base, normalize))
7637
+ wrap_expr(_rbexpr.entropy(base, normalize))
6820
7638
  end
6821
7639
 
6822
7640
  # Run an expression over a sliding window that increases `1` slot every iteration.
@@ -6860,7 +7678,7 @@ module Polars
6860
7678
  # # │ -24 │
6861
7679
  # # └────────┘
6862
7680
  def cumulative_eval(expr, min_periods: 1)
6863
- _from_rbexpr(
7681
+ wrap_expr(
6864
7682
  _rbexpr.cumulative_eval(expr._rbexpr, min_periods)
6865
7683
  )
6866
7684
  end
@@ -6891,7 +7709,7 @@ module Polars
6891
7709
  # # │ 3 │
6892
7710
  # # └────────┘
6893
7711
  def set_sorted(descending: false)
6894
- _from_rbexpr(_rbexpr.set_sorted_flag(descending))
7712
+ wrap_expr(_rbexpr.set_sorted_flag(descending))
6895
7713
  end
6896
7714
 
6897
7715
  # Aggregate to list.
@@ -6916,7 +7734,7 @@ module Polars
6916
7734
  # # │ [1, 2, 3] ┆ [4, 5, 6] │
6917
7735
  # # └───────────┴───────────┘
6918
7736
  def implode
6919
- _from_rbexpr(_rbexpr.implode)
7737
+ wrap_expr(_rbexpr.implode)
6920
7738
  end
6921
7739
 
6922
7740
  # Shrink numeric columns to the minimal required datatype.
@@ -6951,7 +7769,72 @@ module Polars
6951
7769
  # # │ 3 ┆ 8589934592 ┆ 1073741824 ┆ 112 ┆ 129 ┆ c ┆ 0.12 ┆ false │
6952
7770
  # # └─────┴────────────┴────────────┴──────┴──────┴─────┴──────┴───────┘
6953
7771
  def shrink_dtype
6954
- _from_rbexpr(_rbexpr.shrink_dtype)
7772
+ wrap_expr(_rbexpr.shrink_dtype)
7773
+ end
7774
+
7775
+ # Bin values into buckets and count their occurrences.
7776
+ #
7777
+ # @note
7778
+ # This functionality is considered **unstable**. It may be changed
7779
+ # at any point without it being considered a breaking change.
7780
+ #
7781
+ # @param bins [Object]
7782
+ # Bin edges. If nil given, we determine the edges based on the data.
7783
+ # @param bin_count [Integer]
7784
+ # If `bins` is not provided, `bin_count` uniform bins are created that fully
7785
+ # encompass the data.
7786
+ # @param include_category [Boolean]
7787
+ # Include a column that shows the intervals as categories.
7788
+ # @param include_breakpoint [Boolean]
7789
+ # Include a column that indicates the upper breakpoint.
7790
+ #
7791
+ # @return [Expr]
7792
+ #
7793
+ # @example
7794
+ # df = Polars::DataFrame.new({"a" => [1, 3, 8, 8, 2, 1, 3]})
7795
+ # df.select(Polars.col("a").hist(bins: [1, 2, 3]))
7796
+ # # =>
7797
+ # # shape: (2, 1)
7798
+ # # ┌─────┐
7799
+ # # │ a │
7800
+ # # │ --- │
7801
+ # # │ u32 │
7802
+ # # ╞═════╡
7803
+ # # │ 3 │
7804
+ # # │ 2 │
7805
+ # # └─────┘
7806
+ #
7807
+ # @example
7808
+ # df.select(
7809
+ # Polars.col("a").hist(
7810
+ # bins: [1, 2, 3], include_breakpoint: true, include_category: true
7811
+ # )
7812
+ # )
7813
+ # # =>
7814
+ # # shape: (2, 1)
7815
+ # # ┌──────────────────────┐
7816
+ # # │ a │
7817
+ # # │ --- │
7818
+ # # │ struct[3] │
7819
+ # # ╞══════════════════════╡
7820
+ # # │ {2.0,"[1.0, 2.0]",3} │
7821
+ # # │ {3.0,"(2.0, 3.0]",2} │
7822
+ # # └──────────────────────┘
7823
+ def hist(
7824
+ bins: nil,
7825
+ bin_count: nil,
7826
+ include_category: false,
7827
+ include_breakpoint: false
7828
+ )
7829
+ if !bins.nil?
7830
+ if bins.is_a?(::Array)
7831
+ bins = Polars::Series.new(bins)
7832
+ end
7833
+ bins = Utils.parse_into_expression(bins)
7834
+ end
7835
+ wrap_expr(
7836
+ _rbexpr.hist(bins, bin_count, include_category, include_breakpoint)
7837
+ )
6955
7838
  end
6956
7839
 
6957
7840
  # Replace values by different values.
@@ -7110,7 +7993,7 @@ module Polars
7110
7993
  old = Utils.parse_into_expression(old, str_as_lit: true)
7111
7994
  new = Utils.parse_into_expression(new, str_as_lit: true)
7112
7995
 
7113
- result = _from_rbexpr(_rbexpr.replace(old, new))
7996
+ result = wrap_expr(_rbexpr.replace(old, new))
7114
7997
 
7115
7998
  if !return_dtype.nil?
7116
7999
  result = result.cast(return_dtype)
@@ -7262,11 +8145,161 @@ module Polars
7262
8145
 
7263
8146
  default = default.eql?(NO_DEFAULT) ? nil : Utils.parse_into_expression(default, str_as_lit: true)
7264
8147
 
7265
- _from_rbexpr(
8148
+ wrap_expr(
7266
8149
  _rbexpr.replace_strict(old, new, default, return_dtype)
7267
8150
  )
7268
8151
  end
7269
8152
 
8153
+ # Evaluate the number of set bits.
8154
+ #
8155
+ # @return [Expr]
8156
+ def bitwise_count_ones
8157
+ wrap_expr(_rbexpr.bitwise_count_ones)
8158
+ end
8159
+
8160
+ # Evaluate the number of unset bits.
8161
+ #
8162
+ # @return [Expr]
8163
+ def bitwise_count_zeros
8164
+ wrap_expr(_rbexpr.bitwise_count_zeros)
8165
+ end
8166
+
8167
+ # Evaluate the number most-significant set bits before seeing an unset bit.
8168
+ #
8169
+ # @return [Expr]
8170
+ def bitwise_leading_ones
8171
+ wrap_expr(_rbexpr.bitwise_leading_ones)
8172
+ end
8173
+
8174
+ # Evaluate the number most-significant unset bits before seeing a set bit.
8175
+ #
8176
+ # @return [Expr]
8177
+ def bitwise_leading_zeros
8178
+ wrap_expr(_rbexpr.bitwise_leading_zeros)
8179
+ end
8180
+
8181
+ # Evaluate the number least-significant set bits before seeing an unset bit.
8182
+ #
8183
+ # @return [Expr]
8184
+ def bitwise_trailing_ones
8185
+ wrap_expr(_rbexpr.bitwise_trailing_ones)
8186
+ end
8187
+
8188
+ # Evaluate the number least-significant unset bits before seeing a set bit.
8189
+ #
8190
+ # @return [Expr]
8191
+ def bitwise_trailing_zeros
8192
+ wrap_expr(_rbexpr.bitwise_trailing_zeros)
8193
+ end
8194
+
8195
+ # Perform an aggregation of bitwise ANDs.
8196
+ #
8197
+ # @return [Expr]
8198
+ #
8199
+ # @example
8200
+ # df = Polars::DataFrame.new({"n" => [-1, 0, 1]})
8201
+ # df.select(Polars.col("n").bitwise_and)
8202
+ # # =>
8203
+ # # shape: (1, 1)
8204
+ # # ┌─────┐
8205
+ # # │ n │
8206
+ # # │ --- │
8207
+ # # │ i64 │
8208
+ # # ╞═════╡
8209
+ # # │ 0 │
8210
+ # # └─────┘
8211
+ #
8212
+ # @example
8213
+ # df = Polars::DataFrame.new(
8214
+ # {"grouper" => ["a", "a", "a", "b", "b"], "n" => [-1, 0, 1, -1, 1]}
8215
+ # )
8216
+ # df.group_by("grouper", maintain_order: true).agg(Polars.col("n").bitwise_and)
8217
+ # # =>
8218
+ # # shape: (2, 2)
8219
+ # # ┌─────────┬─────┐
8220
+ # # │ grouper ┆ n │
8221
+ # # │ --- ┆ --- │
8222
+ # # │ str ┆ i64 │
8223
+ # # ╞═════════╪═════╡
8224
+ # # │ a ┆ 0 │
8225
+ # # │ b ┆ 1 │
8226
+ # # └─────────┴─────┘
8227
+ def bitwise_and
8228
+ wrap_expr(_rbexpr.bitwise_and)
8229
+ end
8230
+
8231
+ # Perform an aggregation of bitwise ORs.
8232
+ #
8233
+ # @return [Expr]
8234
+ #
8235
+ # @example
8236
+ # df = Polars::DataFrame.new({"n" => [-1, 0, 1]})
8237
+ # df.select(Polars.col("n").bitwise_or)
8238
+ # # =>
8239
+ # # shape: (1, 1)
8240
+ # # ┌─────┐
8241
+ # # │ n │
8242
+ # # │ --- │
8243
+ # # │ i64 │
8244
+ # # ╞═════╡
8245
+ # # │ -1 │
8246
+ # # └─────┘
8247
+ #
8248
+ # @example
8249
+ # df = Polars::DataFrame.new(
8250
+ # {"grouper" => ["a", "a", "a", "b", "b"], "n" => [-1, 0, 1, -1, 1]}
8251
+ # )
8252
+ # df.group_by("grouper", maintain_order: true).agg(Polars.col("n").bitwise_or)
8253
+ # # =>
8254
+ # # shape: (2, 2)
8255
+ # # ┌─────────┬─────┐
8256
+ # # │ grouper ┆ n │
8257
+ # # │ --- ┆ --- │
8258
+ # # │ str ┆ i64 │
8259
+ # # ╞═════════╪═════╡
8260
+ # # │ a ┆ -1 │
8261
+ # # │ b ┆ -1 │
8262
+ # # └─────────┴─────┘
8263
+ def bitwise_or
8264
+ wrap_expr(_rbexpr.bitwise_or)
8265
+ end
8266
+
8267
+ # Perform an aggregation of bitwise XORs.
8268
+ #
8269
+ # @return [Expr]
8270
+ #
8271
+ # @example
8272
+ # df = Polars::DataFrame.new({"n" => [-1, 0, 1]})
8273
+ # df.select(Polars.col("n").bitwise_xor)
8274
+ # # =>
8275
+ # # shape: (1, 1)
8276
+ # # ┌─────┐
8277
+ # # │ n │
8278
+ # # │ --- │
8279
+ # # │ i64 │
8280
+ # # ╞═════╡
8281
+ # # │ -2 │
8282
+ # # └─────┘
8283
+ #
8284
+ # @example
8285
+ # df = Polars::DataFrame.new(
8286
+ # {"grouper" => ["a", "a", "a", "b", "b"], "n" => [-1, 0, 1, -1, 1]}
8287
+ # )
8288
+ # df.group_by("grouper", maintain_order: true).agg(Polars.col("n").bitwise_xor)
8289
+ # # =>
8290
+ # # shape: (2, 2)
8291
+ # # ┌─────────┬─────┐
8292
+ # # │ grouper ┆ n │
8293
+ # # │ --- ┆ --- │
8294
+ # # │ str ┆ i64 │
8295
+ # # ╞═════════╪═════╡
8296
+ # # │ a ┆ -2 │
8297
+ # # │ b ┆ -2 │
8298
+ # # └─────────┴─────┘
8299
+ def bitwise_xor
8300
+ wrap_expr(_rbexpr.bitwise_xor)
8301
+ end
8302
+
7270
8303
  # Create an object namespace of all list related methods.
7271
8304
  #
7272
8305
  # @return [ListExpr]
@@ -7332,7 +8365,7 @@ module Polars
7332
8365
 
7333
8366
  private
7334
8367
 
7335
- def _from_rbexpr(expr)
8368
+ def wrap_expr(expr)
7336
8369
  Utils.wrap_expr(expr)
7337
8370
  end
7338
8371