polars-df 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/Cargo.lock +107 -59
  4. data/Cargo.toml +0 -3
  5. data/LICENSE.txt +1 -1
  6. data/README.md +2 -2
  7. data/ext/polars/Cargo.toml +15 -7
  8. data/ext/polars/src/batched_csv.rs +4 -4
  9. data/ext/polars/src/conversion/anyvalue.rs +185 -0
  10. data/ext/polars/src/conversion/chunked_array.rs +140 -0
  11. data/ext/polars/src/{conversion.rs → conversion/mod.rs} +260 -340
  12. data/ext/polars/src/dataframe.rs +69 -53
  13. data/ext/polars/src/expr/array.rs +74 -0
  14. data/ext/polars/src/expr/datetime.rs +22 -56
  15. data/ext/polars/src/expr/general.rs +61 -33
  16. data/ext/polars/src/expr/list.rs +52 -4
  17. data/ext/polars/src/expr/meta.rs +48 -0
  18. data/ext/polars/src/expr/rolling.rs +1 -0
  19. data/ext/polars/src/expr/string.rs +59 -8
  20. data/ext/polars/src/expr/struct.rs +8 -4
  21. data/ext/polars/src/functions/aggregation.rs +6 -0
  22. data/ext/polars/src/functions/lazy.rs +103 -48
  23. data/ext/polars/src/functions/meta.rs +45 -1
  24. data/ext/polars/src/functions/string_cache.rs +14 -0
  25. data/ext/polars/src/{lazyframe.rs → lazyframe/mod.rs} +138 -22
  26. data/ext/polars/src/lib.rs +226 -168
  27. data/ext/polars/src/series/aggregation.rs +20 -0
  28. data/ext/polars/src/series/mod.rs +25 -4
  29. data/lib/polars/array_expr.rb +449 -0
  30. data/lib/polars/array_name_space.rb +346 -0
  31. data/lib/polars/cat_expr.rb +24 -0
  32. data/lib/polars/cat_name_space.rb +75 -0
  33. data/lib/polars/config.rb +2 -2
  34. data/lib/polars/data_frame.rb +179 -43
  35. data/lib/polars/data_types.rb +191 -28
  36. data/lib/polars/date_time_expr.rb +31 -14
  37. data/lib/polars/exceptions.rb +12 -1
  38. data/lib/polars/expr.rb +866 -186
  39. data/lib/polars/functions/aggregation/horizontal.rb +246 -0
  40. data/lib/polars/functions/aggregation/vertical.rb +282 -0
  41. data/lib/polars/functions/as_datatype.rb +248 -0
  42. data/lib/polars/functions/col.rb +47 -0
  43. data/lib/polars/functions/eager.rb +182 -0
  44. data/lib/polars/functions/lazy.rb +1280 -0
  45. data/lib/polars/functions/len.rb +49 -0
  46. data/lib/polars/functions/lit.rb +35 -0
  47. data/lib/polars/functions/random.rb +16 -0
  48. data/lib/polars/functions/range/date_range.rb +103 -0
  49. data/lib/polars/functions/range/int_range.rb +51 -0
  50. data/lib/polars/functions/repeat.rb +144 -0
  51. data/lib/polars/functions/whenthen.rb +27 -0
  52. data/lib/polars/functions.rb +29 -416
  53. data/lib/polars/group_by.rb +2 -2
  54. data/lib/polars/io.rb +18 -25
  55. data/lib/polars/lazy_frame.rb +367 -53
  56. data/lib/polars/list_expr.rb +152 -6
  57. data/lib/polars/list_name_space.rb +102 -0
  58. data/lib/polars/meta_expr.rb +175 -7
  59. data/lib/polars/series.rb +273 -34
  60. data/lib/polars/string_cache.rb +75 -0
  61. data/lib/polars/string_expr.rb +412 -96
  62. data/lib/polars/string_name_space.rb +4 -4
  63. data/lib/polars/testing.rb +507 -0
  64. data/lib/polars/utils.rb +52 -8
  65. data/lib/polars/version.rb +1 -1
  66. data/lib/polars.rb +15 -2
  67. metadata +35 -5
  68. data/lib/polars/lazy_functions.rb +0 -1181
data/lib/polars/series.rb CHANGED
@@ -214,6 +214,126 @@ module Polars
214
214
  _comp(other, :lt_eq)
215
215
  end
216
216
 
217
+ # Method equivalent of operator expression `series <= other`.
218
+ #
219
+ # @return [Series]
220
+ def le(other)
221
+ self <= other
222
+ end
223
+
224
+ # Method equivalent of operator expression `series < other`.
225
+ #
226
+ # @return [Series]
227
+ def lt(other)
228
+ self < other
229
+ end
230
+
231
+ # Method equivalent of operator expression `series == other`.
232
+ #
233
+ # @return [Series]
234
+ def eq(other)
235
+ self == other
236
+ end
237
+
238
+ # Method equivalent of equality operator `series == other` where `nil == nil`.
239
+ #
240
+ # This differs from the standard `ne` where null values are propagated.
241
+ #
242
+ # @param other [Object]
243
+ # A literal or expression value to compare with.
244
+ #
245
+ # @return [Object]
246
+ #
247
+ # @example
248
+ # s1 = Polars::Series.new("a", [333, 200, nil])
249
+ # s2 = Polars::Series.new("a", [100, 200, nil])
250
+ # s1.eq(s2)
251
+ # # =>
252
+ # # shape: (3,)
253
+ # # Series: 'a' [bool]
254
+ # # [
255
+ # # false
256
+ # # true
257
+ # # null
258
+ # # ]
259
+ #
260
+ # @example
261
+ # s1.eq_missing(s2)
262
+ # # =>
263
+ # # shape: (3,)
264
+ # # Series: 'a' [bool]
265
+ # # [
266
+ # # false
267
+ # # true
268
+ # # true
269
+ # # ]
270
+ def eq_missing(other)
271
+ if other.is_a?(Expr)
272
+ return Polars.lit(self).eq_missing(other)
273
+ end
274
+ to_frame.select(Polars.col(name).eq_missing(other)).to_series
275
+ end
276
+
277
+ # Method equivalent of operator expression `series != other`.
278
+ #
279
+ # @return [Series]
280
+ def ne(other)
281
+ self != other
282
+ end
283
+
284
+ # Method equivalent of equality operator `series != other` where `None == None`.
285
+ #
286
+ # This differs from the standard `ne` where null values are propagated.
287
+ #
288
+ # @param other [Object]
289
+ # A literal or expression value to compare with.
290
+ #
291
+ # @return [Object]
292
+ #
293
+ # @example
294
+ # s1 = Polars::Series.new("a", [333, 200, nil])
295
+ # s2 = Polars::Series.new("a", [100, 200, nil])
296
+ # s1.ne(s2)
297
+ # # =>
298
+ # # shape: (3,)
299
+ # # Series: 'a' [bool]
300
+ # # [
301
+ # # true
302
+ # # false
303
+ # # null
304
+ # # ]
305
+ #
306
+ # @example
307
+ # s1.ne_missing(s2)
308
+ # # =>
309
+ # # shape: (3,)
310
+ # # Series: 'a' [bool]
311
+ # # [
312
+ # # true
313
+ # # false
314
+ # # false
315
+ # # ]
316
+ def ne_missing(other)
317
+ if other.is_a?(Expr)
318
+ return Polars.lit(self).ne_missing(other)
319
+ end
320
+ to_frame.select(Polars.col(name).ne_missing(other)).to_series
321
+ end
322
+
323
+ # Method equivalent of operator expression `series >= other`.
324
+ #
325
+ # @return [Series]
326
+ def ge(other)
327
+ self >= other
328
+ end
329
+
330
+ # Method equivalent of operator expression `series > other`.
331
+ #
332
+ # @return [Series]
333
+ def gt(other)
334
+ self > other
335
+ end
336
+
217
337
  # Performs addition.
218
338
  #
219
339
  # @return [Series]
@@ -411,11 +531,11 @@ module Polars
411
531
  # Check if any boolean value in the column is `true`.
412
532
  #
413
533
  # @return [Boolean]
414
- def any?(&block)
534
+ def any?(ignore_nulls: true, &block)
415
535
  if block_given?
416
- apply(&block).any?
536
+ apply(skip_nulls: ignore_nulls, &block).any?
417
537
  else
418
- to_frame.select(Polars.col(name).any).to_series[0]
538
+ _s.any(ignore_nulls)
419
539
  end
420
540
  end
421
541
  alias_method :any, :any?
@@ -423,11 +543,11 @@ module Polars
423
543
  # Check if all boolean values in the column are `true`.
424
544
  #
425
545
  # @return [Boolean]
426
- def all?(&block)
546
+ def all?(ignore_nulls: true, &block)
427
547
  if block_given?
428
- apply(&block).all?
548
+ apply(skip_nulls: ignore_nulls, &block).all?
429
549
  else
430
- to_frame.select(Polars.col(name).all).to_series[0]
550
+ _s.all(ignore_nulls)
431
551
  end
432
552
  end
433
553
  alias_method :all, :all?
@@ -923,7 +1043,7 @@ module Polars
923
1043
  #
924
1044
  # @example
925
1045
  # s = Polars::Series.new("s", [1, 1, 2, 1, nil, 1, 3, 3])
926
- # s.rle_id()
1046
+ # s.rle_id
927
1047
  # # =>
928
1048
  # # shape: (8,)
929
1049
  # # Series: 's' [u32]
@@ -1135,7 +1255,7 @@ module Polars
1135
1255
  #
1136
1256
  # @example
1137
1257
  # s = Polars::Series.new("a", [1, 2, 3])
1138
- # s.cumsum
1258
+ # s.cum_sum
1139
1259
  # # =>
1140
1260
  # # shape: (3,)
1141
1261
  # # Series: 'a' [i64]
@@ -1144,9 +1264,10 @@ module Polars
1144
1264
  # # 3
1145
1265
  # # 6
1146
1266
  # # ]
1147
- def cumsum(reverse: false)
1267
+ def cum_sum(reverse: false)
1148
1268
  super
1149
1269
  end
1270
+ alias_method :cumsum, :cum_sum
1150
1271
 
1151
1272
  # Get an array with the cumulative min computed at every element.
1152
1273
  #
@@ -1157,7 +1278,7 @@ module Polars
1157
1278
  #
1158
1279
  # @example
1159
1280
  # s = Polars::Series.new("a", [3, 5, 1])
1160
- # s.cummin
1281
+ # s.cum_min
1161
1282
  # # =>
1162
1283
  # # shape: (3,)
1163
1284
  # # Series: 'a' [i64]
@@ -1166,9 +1287,10 @@ module Polars
1166
1287
  # # 3
1167
1288
  # # 1
1168
1289
  # # ]
1169
- def cummin(reverse: false)
1290
+ def cum_min(reverse: false)
1170
1291
  super
1171
1292
  end
1293
+ alias_method :cummin, :cum_min
1172
1294
 
1173
1295
  # Get an array with the cumulative max computed at every element.
1174
1296
  #
@@ -1179,7 +1301,7 @@ module Polars
1179
1301
  #
1180
1302
  # @example
1181
1303
  # s = Polars::Series.new("a", [3, 5, 1])
1182
- # s.cummax
1304
+ # s.cum_max
1183
1305
  # # =>
1184
1306
  # # shape: (3,)
1185
1307
  # # Series: 'a' [i64]
@@ -1188,9 +1310,10 @@ module Polars
1188
1310
  # # 5
1189
1311
  # # 5
1190
1312
  # # ]
1191
- def cummax(reverse: false)
1313
+ def cum_max(reverse: false)
1192
1314
  super
1193
1315
  end
1316
+ alias_method :cummax, :cum_max
1194
1317
 
1195
1318
  # Get an array with the cumulative product computed at every element.
1196
1319
  #
@@ -1205,7 +1328,7 @@ module Polars
1205
1328
  #
1206
1329
  # @example
1207
1330
  # s = Polars::Series.new("a", [1, 2, 3])
1208
- # s.cumprod
1331
+ # s.cum_prod
1209
1332
  # # =>
1210
1333
  # # shape: (3,)
1211
1334
  # # Series: 'a' [i64]
@@ -1214,9 +1337,10 @@ module Polars
1214
1337
  # # 2
1215
1338
  # # 6
1216
1339
  # # ]
1217
- def cumprod(reverse: false)
1340
+ def cum_prod(reverse: false)
1218
1341
  super
1219
1342
  end
1343
+ alias_method :cumprod, :cum_prod
1220
1344
 
1221
1345
  # Get the first `n` rows.
1222
1346
  #
@@ -1443,12 +1567,12 @@ module Polars
1443
1567
  # # 2
1444
1568
  # # 1
1445
1569
  # # ]
1446
- def sort(reverse: false, in_place: false)
1570
+ def sort(reverse: false, nulls_last: false, in_place: false)
1447
1571
  if in_place
1448
- self._s = _s.sort(reverse)
1572
+ self._s = _s.sort(reverse, nulls_last)
1449
1573
  self
1450
1574
  else
1451
- Utils.wrap_s(_s.sort(reverse))
1575
+ Utils.wrap_s(_s.sort(reverse, nulls_last))
1452
1576
  end
1453
1577
  end
1454
1578
 
@@ -1957,11 +2081,9 @@ module Polars
1957
2081
  # @example
1958
2082
  # s = Polars::Series.new("a", [1, 2, nil])
1959
2083
  # s.count
1960
- # # => 3
2084
+ # # => 2
1961
2085
  def count
1962
- warn "`Series#count` will exclude null values in 0.9.0. Use `Series#length` instead."
1963
- # len - null_count
1964
- len
2086
+ len - null_count
1965
2087
  end
1966
2088
 
1967
2089
  # Return the number of elements in the Series.
@@ -2170,7 +2292,7 @@ module Polars
2170
2292
  Int64 => Numo::Int64,
2171
2293
  Float32 => Numo::SFloat,
2172
2294
  Float64 => Numo::DFloat
2173
- }.fetch(dtype).cast(to_a)
2295
+ }.fetch(dtype.class).cast(to_a)
2174
2296
  elsif is_boolean
2175
2297
  Numo::Bit.cast(to_a)
2176
2298
  else
@@ -2209,7 +2331,7 @@ module Polars
2209
2331
  # # 3
2210
2332
  # # ]
2211
2333
  def set(filter, value)
2212
- Utils.wrap_s(_s.send("set_with_mask_#{DTYPE_TO_FFINAME.fetch(dtype)}", filter._s, value))
2334
+ Utils.wrap_s(_s.send("set_with_mask_#{DTYPE_TO_FFINAME.fetch(dtype.class)}", filter._s, value))
2213
2335
  end
2214
2336
 
2215
2337
  # Set values at the index locations.
@@ -2735,7 +2857,7 @@ module Polars
2735
2857
  #
2736
2858
  # @example
2737
2859
  # s = Polars::Series.new("a", [1, 2, 3])
2738
- # s.apply { |x| x + 10 }
2860
+ # s.map_elements { |x| x + 10 }
2739
2861
  # # =>
2740
2862
  # # shape: (3,)
2741
2863
  # # Series: 'a' [i64]
@@ -2744,7 +2866,7 @@ module Polars
2744
2866
  # # 12
2745
2867
  # # 13
2746
2868
  # # ]
2747
- def apply(return_dtype: nil, skip_nulls: true, &func)
2869
+ def map_elements(return_dtype: nil, skip_nulls: true, &func)
2748
2870
  if return_dtype.nil?
2749
2871
  pl_return_dtype = nil
2750
2872
  else
@@ -2752,7 +2874,8 @@ module Polars
2752
2874
  end
2753
2875
  Utils.wrap_s(_s.apply_lambda(func, pl_return_dtype, skip_nulls))
2754
2876
  end
2755
- alias_method :map, :apply
2877
+ alias_method :map, :map_elements
2878
+ alias_method :apply, :map_elements
2756
2879
 
2757
2880
  # Shift the values by a given period.
2758
2881
  #
@@ -3335,8 +3458,8 @@ module Polars
3335
3458
  # # shape: (2,)
3336
3459
  # # Series: 'a' [i64]
3337
3460
  # # [
3338
- # # 1
3339
- # # 5
3461
+ # # 5
3462
+ # # 3
3340
3463
  # # ]
3341
3464
  def sample(
3342
3465
  n: nil,
@@ -3715,6 +3838,113 @@ module Polars
3715
3838
  super
3716
3839
  end
3717
3840
 
3841
+ # Replace values by different values.
3842
+ #
3843
+ # @param old [Object]
3844
+ # Value or sequence of values to replace.
3845
+ # Also accepts a mapping of values to their replacement.
3846
+ # @param new [Object]
3847
+ # Value or sequence of values to replace by.
3848
+ # Length must match the length of `old` or have length 1.
3849
+ # @param default [Object]
3850
+ # Set values that were not replaced to this value.
3851
+ # Defaults to keeping the original value.
3852
+ # Accepts expression input. Non-expression inputs are parsed as literals.
3853
+ # @param return_dtype [Object]
3854
+ # The data type of the resulting Series. If set to `nil` (default),
3855
+ # the data type is determined automatically based on the other inputs.
3856
+ #
3857
+ # @return [Series]
3858
+ #
3859
+ # @example Replace a single value by another value. Values that were not replaced remain unchanged.
3860
+ # s = Polars::Series.new([1, 2, 2, 3])
3861
+ # s.replace(2, 100)
3862
+ # # =>
3863
+ # # shape: (4,)
3864
+ # # Series: '' [i64]
3865
+ # # [
3866
+ # # 1
3867
+ # # 100
3868
+ # # 100
3869
+ # # 3
3870
+ # # ]
3871
+ #
3872
+ # @example Replace multiple values by passing sequences to the `old` and `new` parameters.
3873
+ # s.replace([2, 3], [100, 200])
3874
+ # # =>
3875
+ # # shape: (4,)
3876
+ # # Series: '' [i64]
3877
+ # # [
3878
+ # # 1
3879
+ # # 100
3880
+ # # 100
3881
+ # # 200
3882
+ # # ]
3883
+ #
3884
+ # @example Passing a mapping with replacements is also supported as syntactic sugar. Specify a default to set all values that were not matched.
3885
+ # mapping = {2 => 100, 3 => 200}
3886
+ # s.replace(mapping, default: -1)
3887
+ # # =>
3888
+ # # shape: (4,)
3889
+ # # Series: '' [i64]
3890
+ # # [
3891
+ # # -1
3892
+ # # 100
3893
+ # # 100
3894
+ # # 200
3895
+ # # ]
3896
+ #
3897
+ # @example The default can be another Series.
3898
+ # default = Polars::Series.new([2.5, 5.0, 7.5, 10.0])
3899
+ # s.replace(2, 100, default: default)
3900
+ # # =>
3901
+ # # shape: (4,)
3902
+ # # Series: '' [f64]
3903
+ # # [
3904
+ # # 2.5
3905
+ # # 100.0
3906
+ # # 100.0
3907
+ # # 10.0
3908
+ # # ]
3909
+ #
3910
+ # @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.
3911
+ # s = Polars::Series.new(["x", "y", "z"])
3912
+ # mapping = {"x" => 1, "y" => 2, "z" => 3}
3913
+ # s.replace(mapping)
3914
+ # # =>
3915
+ # # shape: (3,)
3916
+ # # Series: '' [str]
3917
+ # # [
3918
+ # # "1"
3919
+ # # "2"
3920
+ # # "3"
3921
+ # # ]
3922
+ #
3923
+ # @example
3924
+ # s.replace(mapping, default: nil)
3925
+ # # =>
3926
+ # # shape: (3,)
3927
+ # # Series: '' [i64]
3928
+ # # [
3929
+ # # 1
3930
+ # # 2
3931
+ # # 3
3932
+ # # ]
3933
+ #
3934
+ # @example Set the `return_dtype` parameter to control the resulting data type directly.
3935
+ # s.replace(mapping, return_dtype: Polars::UInt8)
3936
+ # # =>
3937
+ # # shape: (3,)
3938
+ # # Series: '' [u8]
3939
+ # # [
3940
+ # # 1
3941
+ # # 2
3942
+ # # 3
3943
+ # # ]
3944
+ def replace(old, new = Expr::NO_DEFAULT, default: Expr::NO_DEFAULT, return_dtype: nil)
3945
+ super
3946
+ end
3947
+
3718
3948
  # Reshape this Series to a flat Series or a Series of Lists.
3719
3949
  #
3720
3950
  # @param dims [Array]
@@ -3924,7 +4154,7 @@ module Polars
3924
4154
  end
3925
4155
 
3926
4156
  def _pos_idxs(idxs)
3927
- idx_type = Polars._get_idx_type
4157
+ idx_type = Plr.get_index_type
3928
4158
 
3929
4159
  if idxs.is_a?(Series)
3930
4160
  if idxs.dtype == idx_type
@@ -4009,7 +4239,7 @@ module Polars
4009
4239
  end
4010
4240
 
4011
4241
  def ffi_func(name, dtype, _s)
4012
- _s.method(name.sub("<>", DTYPE_TO_FFINAME.fetch(dtype))) if DTYPE_TO_FFINAME.key?(dtype)
4242
+ _s.method(name.sub("<>", DTYPE_TO_FFINAME.fetch(dtype.class))) if DTYPE_TO_FFINAME.key?(dtype.class)
4013
4243
  end
4014
4244
 
4015
4245
  def _arithmetic(other, op)
@@ -4124,21 +4354,29 @@ module Polars
4124
4354
  end
4125
4355
  end
4126
4356
 
4127
- if !dtype.nil? && ![List, Unknown].include?(dtype) && Utils.is_polars_dtype(dtype) && ruby_dtype.nil?
4357
+ if !dtype.nil? && ![List, Struct, Unknown].include?(dtype) && Utils.is_polars_dtype(dtype) && ruby_dtype.nil?
4128
4358
  if dtype == Array && !dtype.is_a?(Array) && value.is_a?(::Array)
4129
- dtype = Array.new(value.size)
4359
+ dtype = Array.new(nil, value.size)
4130
4360
  end
4131
4361
 
4132
4362
  constructor = polars_type_to_constructor(dtype)
4133
4363
  rbseries = constructor.call(name, values, strict)
4134
4364
 
4135
4365
  base_type = dtype.is_a?(DataType) ? dtype.class : dtype
4136
- if [Date, Datetime, Duration, Time, Categorical, Boolean].include?(base_type)
4366
+ if [Date, Datetime, Duration, Time, Categorical, Boolean, Enum].include?(base_type)
4137
4367
  if rbseries.dtype != dtype
4138
4368
  rbseries = rbseries.cast(dtype, true)
4139
4369
  end
4140
4370
  end
4141
4371
  return rbseries
4372
+ elsif dtype == Struct
4373
+ struct_schema = dtype.is_a?(Struct) ? dtype.to_schema : nil
4374
+ empty = {}
4375
+ return DataFrame.sequence_to_rbdf(
4376
+ values.map { |v| v.nil? ? empty : v },
4377
+ schema: struct_schema,
4378
+ orient: "row",
4379
+ ).to_struct(name)
4142
4380
  else
4143
4381
  if ruby_dtype.nil?
4144
4382
  if value.nil?
@@ -4229,6 +4467,7 @@ module Polars
4229
4467
  Utf8 => RbSeries.method(:new_str),
4230
4468
  Object => RbSeries.method(:new_object),
4231
4469
  Categorical => RbSeries.method(:new_str),
4470
+ Enum => RbSeries.method(:new_str),
4232
4471
  Binary => RbSeries.method(:new_binary),
4233
4472
  Null => RbSeries.method(:new_null)
4234
4473
  }
@@ -0,0 +1,75 @@
1
+ module Polars
2
+ # Context manager for enabling and disabling the global string cache.
3
+ class StringCache
4
+ def initialize(&block)
5
+ RbStringCacheHolder.hold(&block)
6
+ end
7
+ end
8
+
9
+ module Functions
10
+ # Enable the global string cache.
11
+ #
12
+ # `Categorical` columns created under the same global string cache have
13
+ # the same underlying physical value when string values are equal. This allows the
14
+ # columns to be concatenated or used in a join operation, for example.
15
+ #
16
+ # @return [nil]
17
+ #
18
+ # @example Construct two Series using the same global string cache.
19
+ # Polars.enable_string_cache
20
+ # s1 = Polars::Series.new("color", ["red", "green", "red"], dtype: Polars::Categorical)
21
+ # s2 = Polars::Series.new("color", ["blue", "red", "green"], dtype: Polars::Categorical)
22
+ # Polars.disable_string_cache
23
+ #
24
+ # @example As both Series are constructed under the same global string cache, they can be concatenated.
25
+ # Polars.concat([s1, s2])
26
+ # # =>
27
+ # # shape: (6,)
28
+ # # Series: 'color' [cat]
29
+ # # [
30
+ # # "red"
31
+ # # "green"
32
+ # # "red"
33
+ # # "blue"
34
+ # # "red"
35
+ # # "green"
36
+ # # ]
37
+ def enable_string_cache
38
+ Plr.enable_string_cache
39
+ end
40
+
41
+ # Disable and clear the global string cache.
42
+ #
43
+ # @return [nil]
44
+ #
45
+ # @example Construct two Series using the same global string cache.
46
+ # Polars.enable_string_cache
47
+ # s1 = Polars::Series.new("color", ["red", "green", "red"], dtype: Polars::Categorical)
48
+ # s2 = Polars::Series.new("color", ["blue", "red", "green"], dtype: Polars::Categorical)
49
+ # Polars.disable_string_cache
50
+ #
51
+ # @example As both Series are constructed under the same global string cache, they can be concatenated.
52
+ # Polars.concat([s1, s2])
53
+ # # =>
54
+ # # shape: (6,)
55
+ # # Series: 'color' [cat]
56
+ # # [
57
+ # # "red"
58
+ # # "green"
59
+ # # "red"
60
+ # # "blue"
61
+ # # "red"
62
+ # # "green"
63
+ # # ]
64
+ def disable_string_cache
65
+ Plr.disable_string_cache
66
+ end
67
+
68
+ # Check whether the global string cache is enabled.
69
+ #
70
+ # @return [Boolean]
71
+ def using_string_cache
72
+ Plr.using_string_cache
73
+ end
74
+ end
75
+ end