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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -1
- data/Cargo.lock +107 -59
- data/Cargo.toml +0 -3
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/ext/polars/Cargo.toml +15 -7
- data/ext/polars/src/batched_csv.rs +4 -4
- data/ext/polars/src/conversion/anyvalue.rs +185 -0
- data/ext/polars/src/conversion/chunked_array.rs +140 -0
- data/ext/polars/src/{conversion.rs → conversion/mod.rs} +260 -340
- data/ext/polars/src/dataframe.rs +69 -53
- data/ext/polars/src/expr/array.rs +74 -0
- data/ext/polars/src/expr/datetime.rs +22 -56
- data/ext/polars/src/expr/general.rs +61 -33
- data/ext/polars/src/expr/list.rs +52 -4
- data/ext/polars/src/expr/meta.rs +48 -0
- data/ext/polars/src/expr/rolling.rs +1 -0
- data/ext/polars/src/expr/string.rs +59 -8
- data/ext/polars/src/expr/struct.rs +8 -4
- data/ext/polars/src/functions/aggregation.rs +6 -0
- data/ext/polars/src/functions/lazy.rs +103 -48
- data/ext/polars/src/functions/meta.rs +45 -1
- data/ext/polars/src/functions/string_cache.rs +14 -0
- data/ext/polars/src/{lazyframe.rs → lazyframe/mod.rs} +138 -22
- data/ext/polars/src/lib.rs +226 -168
- data/ext/polars/src/series/aggregation.rs +20 -0
- data/ext/polars/src/series/mod.rs +25 -4
- data/lib/polars/array_expr.rb +449 -0
- data/lib/polars/array_name_space.rb +346 -0
- data/lib/polars/cat_expr.rb +24 -0
- data/lib/polars/cat_name_space.rb +75 -0
- data/lib/polars/config.rb +2 -2
- data/lib/polars/data_frame.rb +179 -43
- data/lib/polars/data_types.rb +191 -28
- data/lib/polars/date_time_expr.rb +31 -14
- data/lib/polars/exceptions.rb +12 -1
- data/lib/polars/expr.rb +866 -186
- data/lib/polars/functions/aggregation/horizontal.rb +246 -0
- data/lib/polars/functions/aggregation/vertical.rb +282 -0
- data/lib/polars/functions/as_datatype.rb +248 -0
- data/lib/polars/functions/col.rb +47 -0
- data/lib/polars/functions/eager.rb +182 -0
- data/lib/polars/functions/lazy.rb +1280 -0
- data/lib/polars/functions/len.rb +49 -0
- data/lib/polars/functions/lit.rb +35 -0
- data/lib/polars/functions/random.rb +16 -0
- data/lib/polars/functions/range/date_range.rb +103 -0
- data/lib/polars/functions/range/int_range.rb +51 -0
- data/lib/polars/functions/repeat.rb +144 -0
- data/lib/polars/functions/whenthen.rb +27 -0
- data/lib/polars/functions.rb +29 -416
- data/lib/polars/group_by.rb +2 -2
- data/lib/polars/io.rb +18 -25
- data/lib/polars/lazy_frame.rb +367 -53
- data/lib/polars/list_expr.rb +152 -6
- data/lib/polars/list_name_space.rb +102 -0
- data/lib/polars/meta_expr.rb +175 -7
- data/lib/polars/series.rb +273 -34
- data/lib/polars/string_cache.rb +75 -0
- data/lib/polars/string_expr.rb +412 -96
- data/lib/polars/string_name_space.rb +4 -4
- data/lib/polars/testing.rb +507 -0
- data/lib/polars/utils.rb +52 -8
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +15 -2
- metadata +35 -5
- 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
|
-
|
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
|
-
|
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.
|
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
|
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.
|
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
|
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.
|
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
|
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.
|
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
|
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
|
-
# # =>
|
2084
|
+
# # => 2
|
1961
2085
|
def count
|
1962
|
-
|
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.
|
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
|
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, :
|
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
|
-
# #
|
3339
|
-
# #
|
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 =
|
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
|