polars-df 0.15.0 → 0.26.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +274 -0
- data/Cargo.lock +1465 -867
- data/Cargo.toml +3 -0
- data/LICENSE.txt +2 -2
- data/README.md +87 -37
- data/ext/polars/Cargo.toml +47 -16
- data/ext/polars/src/c_api/allocator.rs +7 -0
- data/ext/polars/src/c_api/mod.rs +1 -0
- data/ext/polars/src/catalog/mod.rs +1 -0
- data/ext/polars/src/catalog/unity.rs +470 -0
- data/ext/polars/src/conversion/any_value.rs +99 -84
- data/ext/polars/src/conversion/categorical.rs +30 -0
- data/ext/polars/src/conversion/chunked_array.rs +71 -62
- data/ext/polars/src/conversion/datetime.rs +63 -0
- data/ext/polars/src/conversion/mod.rs +796 -312
- data/ext/polars/src/dataframe/construction.rs +6 -18
- data/ext/polars/src/dataframe/export.rs +30 -39
- data/ext/polars/src/dataframe/general.rs +294 -362
- data/ext/polars/src/dataframe/io.rs +33 -150
- data/ext/polars/src/dataframe/map.rs +175 -0
- data/ext/polars/src/dataframe/mod.rs +37 -5
- data/ext/polars/src/dataframe/serde.rs +23 -8
- data/ext/polars/src/error.rs +44 -7
- data/ext/polars/src/exceptions.rs +21 -8
- data/ext/polars/src/expr/array.rs +86 -22
- data/ext/polars/src/expr/binary.rs +50 -1
- data/ext/polars/src/expr/bitwise.rs +39 -0
- data/ext/polars/src/expr/categorical.rs +20 -0
- data/ext/polars/src/expr/datatype.rs +51 -0
- data/ext/polars/src/expr/datetime.rs +99 -41
- data/ext/polars/src/expr/extension.rs +12 -0
- data/ext/polars/src/expr/general.rs +252 -128
- data/ext/polars/src/expr/list.rs +56 -60
- data/ext/polars/src/expr/meta.rs +30 -35
- data/ext/polars/src/expr/mod.rs +28 -6
- data/ext/polars/src/expr/name.rs +29 -14
- data/ext/polars/src/expr/rolling.rs +111 -3
- data/ext/polars/src/expr/selector.rs +219 -0
- data/ext/polars/src/expr/serde.rs +28 -0
- data/ext/polars/src/expr/string.rs +118 -20
- data/ext/polars/src/expr/struct.rs +14 -1
- data/ext/polars/src/file.rs +194 -86
- data/ext/polars/src/functions/aggregation.rs +13 -12
- data/ext/polars/src/functions/business.rs +2 -3
- data/ext/polars/src/functions/eager.rs +3 -2
- data/ext/polars/src/functions/io.rs +90 -18
- data/ext/polars/src/functions/lazy.rs +267 -118
- data/ext/polars/src/functions/meta.rs +8 -7
- data/ext/polars/src/functions/misc.rs +1 -1
- data/ext/polars/src/functions/mod.rs +2 -1
- data/ext/polars/src/functions/range.rs +88 -31
- data/ext/polars/src/functions/strings.rs +6 -0
- data/ext/polars/src/functions/utils.rs +8 -0
- data/ext/polars/src/interop/arrow/mod.rs +52 -1
- data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +37 -7
- data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
- data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
- data/ext/polars/src/interop/numo/to_numo_series.rs +72 -50
- data/ext/polars/src/io/cloud_options.rs +107 -0
- data/ext/polars/src/io/mod.rs +4 -0
- data/ext/polars/src/io/scan_options.rs +113 -0
- data/ext/polars/src/io/sink_options.rs +46 -0
- data/ext/polars/src/io/sink_output.rs +21 -0
- data/ext/polars/src/lazyframe/exitable.rs +39 -0
- data/ext/polars/src/lazyframe/general.rs +846 -368
- data/ext/polars/src/lazyframe/mod.rs +58 -5
- data/ext/polars/src/lazyframe/optflags.rs +59 -0
- data/ext/polars/src/lazyframe/serde.rs +36 -4
- data/ext/polars/src/lazyframe/sink.rs +46 -0
- data/ext/polars/src/lazygroupby.rs +38 -9
- data/ext/polars/src/lib.rs +574 -165
- data/ext/polars/src/map/lazy.rs +44 -74
- data/ext/polars/src/map/mod.rs +18 -254
- data/ext/polars/src/map/series.rs +241 -1087
- data/ext/polars/src/on_startup.rs +192 -9
- data/ext/polars/src/prelude.rs +1 -0
- data/ext/polars/src/rb_modules.rs +10 -57
- data/ext/polars/src/ruby/exceptions.rs +26 -0
- data/ext/polars/src/ruby/gvl.rs +104 -0
- data/ext/polars/src/ruby/lazy.rs +46 -0
- data/ext/polars/src/ruby/mod.rs +11 -0
- data/ext/polars/src/ruby/numo.rs +52 -0
- data/ext/polars/src/ruby/plan_callback.rs +198 -0
- data/ext/polars/src/ruby/rb_modules.rs +16 -0
- data/ext/polars/src/ruby/ruby_convert_registry.rs +51 -0
- data/ext/polars/src/ruby/ruby_function.rs +11 -0
- data/ext/polars/src/ruby/ruby_udf.rs +164 -0
- data/ext/polars/src/ruby/thread.rs +65 -0
- data/ext/polars/src/ruby/utils.rs +39 -0
- data/ext/polars/src/series/aggregation.rs +116 -91
- data/ext/polars/src/series/arithmetic.rs +16 -22
- data/ext/polars/src/series/comparison.rs +101 -222
- data/ext/polars/src/series/construction.rs +80 -70
- data/ext/polars/src/series/export.rs +98 -56
- data/ext/polars/src/series/general.rs +323 -440
- data/ext/polars/src/series/import.rs +22 -5
- data/ext/polars/src/series/map.rs +103 -0
- data/ext/polars/src/series/mod.rs +57 -15
- data/ext/polars/src/series/scatter.rs +139 -82
- data/ext/polars/src/sql.rs +16 -9
- data/ext/polars/src/testing/frame.rs +31 -0
- data/ext/polars/src/testing/mod.rs +5 -0
- data/ext/polars/src/testing/series.rs +31 -0
- data/ext/polars/src/timeout.rs +105 -0
- data/ext/polars/src/utils.rs +105 -4
- data/lib/polars/array_expr.rb +500 -22
- data/lib/polars/array_name_space.rb +384 -10
- data/lib/polars/batched_csv_reader.rb +48 -66
- data/lib/polars/binary_expr.rb +217 -0
- data/lib/polars/binary_name_space.rb +155 -1
- data/lib/polars/cat_expr.rb +224 -0
- data/lib/polars/cat_name_space.rb +132 -32
- data/lib/polars/catalog/unity/catalog_info.rb +20 -0
- data/lib/polars/catalog/unity/column_info.rb +31 -0
- data/lib/polars/catalog/unity/namespace_info.rb +21 -0
- data/lib/polars/catalog/unity/table_info.rb +50 -0
- data/lib/polars/catalog.rb +448 -0
- data/lib/polars/collect_batches.rb +22 -0
- data/lib/polars/config.rb +3 -3
- data/lib/polars/convert.rb +201 -36
- data/lib/polars/data_frame.rb +2851 -1017
- data/lib/polars/data_frame_plot.rb +173 -0
- data/lib/polars/data_type_expr.rb +52 -0
- data/lib/polars/data_type_group.rb +6 -0
- data/lib/polars/data_types.rb +118 -18
- data/lib/polars/date_time_expr.rb +426 -84
- data/lib/polars/date_time_name_space.rb +384 -111
- data/lib/polars/dynamic_group_by.rb +102 -10
- data/lib/polars/exceptions.rb +50 -5
- data/lib/polars/expr.rb +2159 -915
- data/lib/polars/extension_expr.rb +39 -0
- data/lib/polars/extension_name_space.rb +39 -0
- data/lib/polars/functions/aggregation/horizontal.rb +11 -6
- data/lib/polars/functions/aggregation/vertical.rb +2 -3
- data/lib/polars/functions/as_datatype.rb +290 -8
- data/lib/polars/functions/business.rb +95 -0
- data/lib/polars/functions/col.rb +6 -5
- data/lib/polars/functions/datatype.rb +62 -0
- data/lib/polars/functions/eager.rb +426 -24
- data/lib/polars/functions/escape_regex.rb +21 -0
- data/lib/polars/functions/lazy.rb +813 -195
- data/lib/polars/functions/lit.rb +21 -10
- data/lib/polars/functions/range/int_range.rb +74 -2
- data/lib/polars/functions/range/linear_space.rb +195 -0
- data/lib/polars/functions/range/time_range.rb +1 -1
- data/lib/polars/functions/repeat.rb +7 -12
- data/lib/polars/functions/whenthen.rb +2 -2
- data/lib/polars/group_by.rb +188 -58
- data/lib/polars/iceberg_dataset.rb +108 -0
- data/lib/polars/in_process_query.rb +37 -0
- data/lib/polars/io/cloud.rb +18 -0
- data/lib/polars/io/csv.rb +336 -128
- data/lib/polars/io/database.rb +19 -4
- data/lib/polars/io/delta.rb +134 -0
- data/lib/polars/io/iceberg.rb +34 -0
- data/lib/polars/io/ipc.rb +63 -63
- data/lib/polars/io/json.rb +16 -0
- data/lib/polars/io/lines.rb +172 -0
- data/lib/polars/io/ndjson.rb +176 -20
- data/lib/polars/io/parquet.rb +173 -95
- data/lib/polars/io/scan_options.rb +55 -0
- data/lib/polars/io/sink_options.rb +27 -0
- data/lib/polars/io/utils.rb +17 -0
- data/lib/polars/lazy_frame.rb +3017 -622
- data/lib/polars/lazy_group_by.rb +436 -2
- data/lib/polars/list_expr.rb +551 -59
- data/lib/polars/list_name_space.rb +465 -51
- data/lib/polars/meta_expr.rb +146 -24
- data/lib/polars/name_expr.rb +87 -2
- data/lib/polars/query_opt_flags.rb +264 -0
- data/lib/polars/rolling_group_by.rb +90 -5
- data/lib/polars/scan_cast_options.rb +86 -0
- data/lib/polars/schema.rb +128 -0
- data/lib/polars/selector.rb +245 -0
- data/lib/polars/selectors.rb +1048 -201
- data/lib/polars/series.rb +2522 -774
- data/lib/polars/series_plot.rb +72 -0
- data/lib/polars/slice.rb +1 -1
- data/lib/polars/sql_context.rb +13 -6
- data/lib/polars/string_cache.rb +19 -72
- data/lib/polars/string_expr.rb +561 -107
- data/lib/polars/string_name_space.rb +781 -109
- data/lib/polars/struct_expr.rb +139 -18
- data/lib/polars/struct_name_space.rb +19 -1
- data/lib/polars/testing.rb +24 -273
- data/lib/polars/utils/constants.rb +2 -0
- data/lib/polars/utils/construction/data_frame.rb +410 -0
- data/lib/polars/utils/construction/series.rb +350 -0
- data/lib/polars/utils/construction/utils.rb +9 -0
- data/lib/polars/utils/convert.rb +18 -8
- data/lib/polars/utils/deprecation.rb +11 -0
- data/lib/polars/utils/parse.rb +62 -9
- data/lib/polars/utils/reduce_balanced.rb +43 -0
- data/lib/polars/utils/serde.rb +22 -0
- data/lib/polars/utils/unstable.rb +19 -0
- data/lib/polars/utils/various.rb +86 -1
- data/lib/polars/utils.rb +63 -48
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +85 -2
- metadata +80 -28
- data/ext/polars/src/allocator.rs +0 -13
- data/ext/polars/src/batched_csv.rs +0 -138
- data/ext/polars/src/functions/string_cache.rs +0 -25
- data/ext/polars/src/map/dataframe.rs +0 -338
- data/lib/polars/plot.rb +0 -109
data/lib/polars/binary_expr.rb
CHANGED
|
@@ -197,5 +197,222 @@ module Polars
|
|
|
197
197
|
raise ArgumentError, "encoding must be one of {{'hex', 'base64'}}, got #{encoding}"
|
|
198
198
|
end
|
|
199
199
|
end
|
|
200
|
+
|
|
201
|
+
# Get the size of binary values in the given unit.
|
|
202
|
+
#
|
|
203
|
+
# @param unit ['b', 'kb', 'mb', 'gb', 'tb']
|
|
204
|
+
# Scale the returned size to the given unit.
|
|
205
|
+
#
|
|
206
|
+
# @return [Expr]
|
|
207
|
+
#
|
|
208
|
+
# @example
|
|
209
|
+
# df = Polars::DataFrame.new({"data" => [512, 256, 1024].map { |n| "\x00".b * n }})
|
|
210
|
+
# df.with_columns(
|
|
211
|
+
# n_bytes: Polars.col("data").bin.size,
|
|
212
|
+
# n_kilobytes: Polars.col("data").bin.size("kb")
|
|
213
|
+
# )
|
|
214
|
+
# # =>
|
|
215
|
+
# # shape: (3, 3)
|
|
216
|
+
# # ┌─────────────────────────────────┬─────────┬─────────────┐
|
|
217
|
+
# # │ data ┆ n_bytes ┆ n_kilobytes │
|
|
218
|
+
# # │ --- ┆ --- ┆ --- │
|
|
219
|
+
# # │ binary ┆ u32 ┆ f64 │
|
|
220
|
+
# # ╞═════════════════════════════════╪═════════╪═════════════╡
|
|
221
|
+
# # │ b"\x00\x00\x00\x00\x00\x00\x00… ┆ 512 ┆ 0.5 │
|
|
222
|
+
# # │ b"\x00\x00\x00\x00\x00\x00\x00… ┆ 256 ┆ 0.25 │
|
|
223
|
+
# # │ b"\x00\x00\x00\x00\x00\x00\x00… ┆ 1024 ┆ 1.0 │
|
|
224
|
+
# # └─────────────────────────────────┴─────────┴─────────────┘
|
|
225
|
+
def size(unit = "b")
|
|
226
|
+
sz = Utils.wrap_expr(_rbexpr.bin_size_bytes)
|
|
227
|
+
sz = Utils.scale_bytes(sz, to: unit)
|
|
228
|
+
sz
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Interpret a buffer as a numerical Polars type.
|
|
232
|
+
#
|
|
233
|
+
# @param dtype [Object]
|
|
234
|
+
# Which type to interpret binary column into.
|
|
235
|
+
# @param endianness : ["big", "little"]
|
|
236
|
+
# Which endianness to use when interpreting bytes, by default "little".
|
|
237
|
+
#
|
|
238
|
+
# @return [Expr]
|
|
239
|
+
#
|
|
240
|
+
# @example
|
|
241
|
+
# df = Polars::DataFrame.new({"data" => ["\x05\x00\x00\x00".b, "\x10\x00\x01\x00".b]})
|
|
242
|
+
# df.with_columns(
|
|
243
|
+
# bin2int: Polars.col("data").bin.reinterpret(
|
|
244
|
+
# dtype: Polars::Int32, endianness: "little"
|
|
245
|
+
# )
|
|
246
|
+
# )
|
|
247
|
+
# # =>
|
|
248
|
+
# # shape: (2, 2)
|
|
249
|
+
# # ┌─────────────────────┬─────────┐
|
|
250
|
+
# # │ data ┆ bin2int │
|
|
251
|
+
# # │ --- ┆ --- │
|
|
252
|
+
# # │ binary ┆ i32 │
|
|
253
|
+
# # ╞═════════════════════╪═════════╡
|
|
254
|
+
# # │ b"\x05\x00\x00\x00" ┆ 5 │
|
|
255
|
+
# # │ b"\x10\x00\x01\x00" ┆ 65552 │
|
|
256
|
+
# # └─────────────────────┴─────────┘
|
|
257
|
+
def reinterpret(
|
|
258
|
+
dtype:,
|
|
259
|
+
endianness: "little"
|
|
260
|
+
)
|
|
261
|
+
dtype = Utils.parse_into_datatype_expr(dtype)
|
|
262
|
+
|
|
263
|
+
Utils.wrap_expr(
|
|
264
|
+
_rbexpr.bin_reinterpret(dtype._rbdatatype_expr, endianness)
|
|
265
|
+
)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Slice the binary values.
|
|
269
|
+
#
|
|
270
|
+
# @param offset [Object]
|
|
271
|
+
# Start index. Negative indexing is supported.
|
|
272
|
+
# @param length [Object]
|
|
273
|
+
# Length of the slice. If set to `nil` (default), the slice is taken to the
|
|
274
|
+
# end of the value.
|
|
275
|
+
#
|
|
276
|
+
# @return [Expr]
|
|
277
|
+
#
|
|
278
|
+
# @example
|
|
279
|
+
# colors = Polars::DataFrame.new(
|
|
280
|
+
# {
|
|
281
|
+
# "name" => ["black", "yellow", "blue"],
|
|
282
|
+
# "code" => ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b]
|
|
283
|
+
# }
|
|
284
|
+
# )
|
|
285
|
+
# colors.with_columns(
|
|
286
|
+
# Polars.col("code").bin.slice(1, 2).alias("sliced")
|
|
287
|
+
# )
|
|
288
|
+
# # =>
|
|
289
|
+
# # shape: (3, 3)
|
|
290
|
+
# # ┌────────┬─────────────────┬─────────────┐
|
|
291
|
+
# # │ name ┆ code ┆ sliced │
|
|
292
|
+
# # │ --- ┆ --- ┆ --- │
|
|
293
|
+
# # │ str ┆ binary ┆ binary │
|
|
294
|
+
# # ╞════════╪═════════════════╪═════════════╡
|
|
295
|
+
# # │ black ┆ b"\x00\x00\x00" ┆ b"\x00\x00" │
|
|
296
|
+
# # │ yellow ┆ b"\xff\xff\x00" ┆ b"\xff\x00" │
|
|
297
|
+
# # │ blue ┆ b"\x00\x00\xff" ┆ b"\x00\xff" │
|
|
298
|
+
# # └────────┴─────────────────┴─────────────┘
|
|
299
|
+
def slice(offset, length = nil)
|
|
300
|
+
offset_rbexpr = Utils.parse_into_expression(offset)
|
|
301
|
+
length_rbexpr = Utils.parse_into_expression(length)
|
|
302
|
+
Utils.wrap_expr(_rbexpr.bin_slice(offset_rbexpr, length_rbexpr))
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Take the first `n` bytes of the binary values.
|
|
306
|
+
#
|
|
307
|
+
# @param n [Object]
|
|
308
|
+
# Length of the slice (integer or expression). Negative indexing is supported;
|
|
309
|
+
# see note (2) below.
|
|
310
|
+
#
|
|
311
|
+
# @return [Expr]
|
|
312
|
+
#
|
|
313
|
+
# @note
|
|
314
|
+
# (1) A similar method exists for taking the last `n` bytes: :func:`tail`.
|
|
315
|
+
# (2) If `n` is negative, it is interpreted as "until the nth byte from the end",
|
|
316
|
+
# e.g., ``head(-3)`` returns all but the last three bytes.
|
|
317
|
+
#
|
|
318
|
+
# @example
|
|
319
|
+
# colors = Polars::DataFrame.new(
|
|
320
|
+
# {
|
|
321
|
+
# "name" => ["black", "yellow", "blue"],
|
|
322
|
+
# "code" => ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b]
|
|
323
|
+
# }
|
|
324
|
+
# )
|
|
325
|
+
# colors.with_columns(
|
|
326
|
+
# Polars.col("code").bin.head(2).alias("head")
|
|
327
|
+
# )
|
|
328
|
+
# # =>
|
|
329
|
+
# # shape: (3, 3)
|
|
330
|
+
# # ┌────────┬─────────────────┬─────────────┐
|
|
331
|
+
# # │ name ┆ code ┆ head │
|
|
332
|
+
# # │ --- ┆ --- ┆ --- │
|
|
333
|
+
# # │ str ┆ binary ┆ binary │
|
|
334
|
+
# # ╞════════╪═════════════════╪═════════════╡
|
|
335
|
+
# # │ black ┆ b"\x00\x00\x00" ┆ b"\x00\x00" │
|
|
336
|
+
# # │ yellow ┆ b"\xff\xff\x00" ┆ b"\xff\xff" │
|
|
337
|
+
# # │ blue ┆ b"\x00\x00\xff" ┆ b"\x00\x00" │
|
|
338
|
+
# # └────────┴─────────────────┴─────────────┘
|
|
339
|
+
def head(n = 5)
|
|
340
|
+
n_rbexpr = Utils.parse_into_expression(n, str_as_lit: false)
|
|
341
|
+
Utils.wrap_expr(_rbexpr.bin_head(n_rbexpr))
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Take the last `n` bytes of the binary values.
|
|
345
|
+
#
|
|
346
|
+
# @param n [Object]
|
|
347
|
+
# Length of the slice (integer or expression). Negative indexing is supported;
|
|
348
|
+
# see note (2) below.
|
|
349
|
+
#
|
|
350
|
+
# @return [Expr]
|
|
351
|
+
#
|
|
352
|
+
# @note
|
|
353
|
+
# (1) A similar method exists for taking the first `n` bytes: `head`.
|
|
354
|
+
# (2) If `n` is negative, it is interpreted as "starting at the nth byte",
|
|
355
|
+
# e.g., ``tail(-3)`` returns all but the first three bytes.
|
|
356
|
+
#
|
|
357
|
+
# @example
|
|
358
|
+
# colors = Polars::DataFrame.new(
|
|
359
|
+
# {
|
|
360
|
+
# "name" => ["black", "yellow", "blue"],
|
|
361
|
+
# "code" => ["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b]
|
|
362
|
+
# }
|
|
363
|
+
# )
|
|
364
|
+
# colors.with_columns(
|
|
365
|
+
# Polars.col("code").bin.tail(2).alias("tail")
|
|
366
|
+
# )
|
|
367
|
+
# # =>
|
|
368
|
+
# # shape: (3, 3)
|
|
369
|
+
# # ┌────────┬─────────────────┬─────────────┐
|
|
370
|
+
# # │ name ┆ code ┆ tail │
|
|
371
|
+
# # │ --- ┆ --- ┆ --- │
|
|
372
|
+
# # │ str ┆ binary ┆ binary │
|
|
373
|
+
# # ╞════════╪═════════════════╪═════════════╡
|
|
374
|
+
# # │ black ┆ b"\x00\x00\x00" ┆ b"\x00\x00" │
|
|
375
|
+
# # │ yellow ┆ b"\xff\xff\x00" ┆ b"\xff\x00" │
|
|
376
|
+
# # │ blue ┆ b"\x00\x00\xff" ┆ b"\x00\xff" │
|
|
377
|
+
# # └────────┴─────────────────┴─────────────┘
|
|
378
|
+
def tail(n = 5)
|
|
379
|
+
n_rbexpr = Utils.parse_into_expression(n, str_as_lit: false)
|
|
380
|
+
Utils.wrap_expr(_rbexpr.bin_tail(n_rbexpr))
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# Get the byte value at the given index.
|
|
384
|
+
#
|
|
385
|
+
# For example, index `0` would return the first byte of every binary value
|
|
386
|
+
# and index `-1` would return the last byte of every binary value.
|
|
387
|
+
# If an index is out of bounds, it will return a `None`.
|
|
388
|
+
#
|
|
389
|
+
# @param index [Object]
|
|
390
|
+
# Index to return per binary value
|
|
391
|
+
# @param null_on_oob [Boolean]
|
|
392
|
+
# Behavior if an index is out of bounds:
|
|
393
|
+
#
|
|
394
|
+
# * true -> set as null
|
|
395
|
+
# * false -> raise an error
|
|
396
|
+
#
|
|
397
|
+
# @return [Expr]
|
|
398
|
+
#
|
|
399
|
+
# @example
|
|
400
|
+
# df = Polars::DataFrame.new({"a" => ["\x01\x02\x03".b, "".b, "\x04\x05".b]})
|
|
401
|
+
# df.with_columns(get: Polars.col("a").bin.get(0, null_on_oob: true))
|
|
402
|
+
# # =>
|
|
403
|
+
# # shape: (3, 2)
|
|
404
|
+
# # ┌─────────────────┬──────┐
|
|
405
|
+
# # │ a ┆ get │
|
|
406
|
+
# # │ --- ┆ --- │
|
|
407
|
+
# # │ binary ┆ u8 │
|
|
408
|
+
# # ╞═════════════════╪══════╡
|
|
409
|
+
# # │ b"\x01\x02\x03" ┆ 1 │
|
|
410
|
+
# # │ b"" ┆ null │
|
|
411
|
+
# # │ b"\x04\x05" ┆ 4 │
|
|
412
|
+
# # └─────────────────┴──────┘
|
|
413
|
+
def get(index, null_on_oob: false)
|
|
414
|
+
index_rbexpr = Utils.parse_into_expression(index)
|
|
415
|
+
Utils.wrap_expr(_rbexpr.bin_get(index_rbexpr, null_on_oob))
|
|
416
|
+
end
|
|
200
417
|
end
|
|
201
418
|
end
|
|
@@ -110,7 +110,7 @@ module Polars
|
|
|
110
110
|
# # b"\x00\x00\xff"
|
|
111
111
|
# # ]
|
|
112
112
|
#
|
|
113
|
-
# @example Set `strict
|
|
113
|
+
# @example Set `strict: false` to set invalid values to null instead of raising an error.
|
|
114
114
|
# s = Polars::Series.new("colors", ["000000".b, "ffff00".b, "invalid_value".b])
|
|
115
115
|
# s.bin.decode("hex", strict: false)
|
|
116
116
|
# # =>
|
|
@@ -157,5 +157,159 @@ module Polars
|
|
|
157
157
|
def encode(encoding)
|
|
158
158
|
super
|
|
159
159
|
end
|
|
160
|
+
|
|
161
|
+
# Get the size of the binary values in a Series in the given unit.
|
|
162
|
+
#
|
|
163
|
+
# @return [Series]
|
|
164
|
+
#
|
|
165
|
+
# @example
|
|
166
|
+
# s = Polars::Series.new("data", [512, 256, 2560, 1024].map { |n| "\x00".b * n })
|
|
167
|
+
# s.bin.size("kb")
|
|
168
|
+
# # =>
|
|
169
|
+
# # shape: (4,)
|
|
170
|
+
# # Series: 'data' [f64]
|
|
171
|
+
# # [
|
|
172
|
+
# # 0.5
|
|
173
|
+
# # 0.25
|
|
174
|
+
# # 2.5
|
|
175
|
+
# # 1.0
|
|
176
|
+
# # ]
|
|
177
|
+
def size(unit = "b")
|
|
178
|
+
super
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Interpret a buffer as a numerical polars type.
|
|
182
|
+
#
|
|
183
|
+
# @param dtype [Object]
|
|
184
|
+
# Which type to interpret binary column into.
|
|
185
|
+
# @param endianness ["big", "little"]
|
|
186
|
+
# Which endianness to use when interpreting bytes, by default "little".
|
|
187
|
+
#
|
|
188
|
+
# @return [Series]
|
|
189
|
+
#
|
|
190
|
+
# @example
|
|
191
|
+
# s = Polars::Series.new("data", ["\x05\x00\x00\x00".b, "\x10\x00\x01\x00".b])
|
|
192
|
+
# s.bin.reinterpret(dtype: Polars::Int32, endianness: "little")
|
|
193
|
+
# # =>
|
|
194
|
+
# # shape: (2,)
|
|
195
|
+
# # Series: 'data' [i32]
|
|
196
|
+
# # [
|
|
197
|
+
# # 5
|
|
198
|
+
# # 65552
|
|
199
|
+
# # ]
|
|
200
|
+
def reinterpret(dtype:, endianness: "little")
|
|
201
|
+
super
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Slice the binary values.
|
|
205
|
+
#
|
|
206
|
+
# @param offset [Object]
|
|
207
|
+
# Start index. Negative indexing is supported.
|
|
208
|
+
# @param length [Object]
|
|
209
|
+
# Length of the slice. If set to `nil` (default), the slice is taken to the
|
|
210
|
+
# end of the value.
|
|
211
|
+
#
|
|
212
|
+
# @return [Series]
|
|
213
|
+
#
|
|
214
|
+
# @example
|
|
215
|
+
# colors = Polars::Series.new(["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
|
|
216
|
+
# colors.bin.slice(1, 2)
|
|
217
|
+
# # =>
|
|
218
|
+
# # shape: (3,)
|
|
219
|
+
# # Series: '' [binary]
|
|
220
|
+
# # [
|
|
221
|
+
# # b"\x00\x00"
|
|
222
|
+
# # b"\xff\x00"
|
|
223
|
+
# # b"\x00\xff"
|
|
224
|
+
# # ]
|
|
225
|
+
def slice(offset, length = nil)
|
|
226
|
+
super
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Get the byte value at the given index.
|
|
230
|
+
#
|
|
231
|
+
# For example, index `0` would return the first byte of every binary value
|
|
232
|
+
# and index `-1` would return the last byte of every binary value.
|
|
233
|
+
# The behavior if an index is out of bounds is determined by the argument
|
|
234
|
+
# `null_on_oob`.
|
|
235
|
+
#
|
|
236
|
+
# @param index [Object]
|
|
237
|
+
# Index to return per binary value
|
|
238
|
+
# @param null_on_oob [Boolean]
|
|
239
|
+
# Behavior if an index is out of bounds:
|
|
240
|
+
#
|
|
241
|
+
# * true -> set as null
|
|
242
|
+
# * false -> raise an error
|
|
243
|
+
#
|
|
244
|
+
# @return [Series]
|
|
245
|
+
#
|
|
246
|
+
# @example
|
|
247
|
+
# s = Polars::Series.new("a", ["\x01\x02\x03".b, "".b, "\x04\x05".b])
|
|
248
|
+
# s.bin.get(0, null_on_oob: true)
|
|
249
|
+
# # =>
|
|
250
|
+
# # shape: (3,)
|
|
251
|
+
# # Series: 'a' [u8]
|
|
252
|
+
# # [
|
|
253
|
+
# # 1
|
|
254
|
+
# # null
|
|
255
|
+
# # 4
|
|
256
|
+
# # ]
|
|
257
|
+
def get(index, null_on_oob: false)
|
|
258
|
+
super
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Take the first `n` bytes of the binary values.
|
|
262
|
+
#
|
|
263
|
+
# @param n [Object]
|
|
264
|
+
# Length of the slice. Negative indexing is supported; see note (2) below.
|
|
265
|
+
#
|
|
266
|
+
# @return [Series]
|
|
267
|
+
#
|
|
268
|
+
# @note
|
|
269
|
+
# (1) A similar method exists for taking the last `n` bytes: `tail`.
|
|
270
|
+
# (2) If `n` is negative, it is interpreted as "until the nth byte from the end",
|
|
271
|
+
# e.g., `head(-3)` returns all but the last three bytes.
|
|
272
|
+
#
|
|
273
|
+
# @example
|
|
274
|
+
# colors = Polars::Series.new(["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
|
|
275
|
+
# colors.bin.head(2)
|
|
276
|
+
# # =>
|
|
277
|
+
# # shape: (3,)
|
|
278
|
+
# # Series: '' [binary]
|
|
279
|
+
# # [
|
|
280
|
+
# # b"\x00\x00"
|
|
281
|
+
# # b"\xff\xff"
|
|
282
|
+
# # b"\x00\x00"
|
|
283
|
+
# # ]
|
|
284
|
+
def head(n = 5)
|
|
285
|
+
super
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Take the last `n` bytes of the binary values.
|
|
289
|
+
#
|
|
290
|
+
# @param n [Object]
|
|
291
|
+
# Length of the slice. Negative indexing is supported; see note (2) below.
|
|
292
|
+
#
|
|
293
|
+
# @return [Series]
|
|
294
|
+
#
|
|
295
|
+
# @note
|
|
296
|
+
# (1) A similar method exists for taking the first `n` bytes: `head`.
|
|
297
|
+
# (2) If `n` is negative, it is interpreted as "starting at the nth byte",
|
|
298
|
+
# e.g., `tail(-3)` returns all but the first three bytes.
|
|
299
|
+
#
|
|
300
|
+
# @example
|
|
301
|
+
# colors = Polars::Series.new(["\x00\x00\x00".b, "\xff\xff\x00".b, "\x00\x00\xff".b])
|
|
302
|
+
# colors.bin.tail(2)
|
|
303
|
+
# # =>
|
|
304
|
+
# # shape: (3,)
|
|
305
|
+
# # Series: '' [binary]
|
|
306
|
+
# # [
|
|
307
|
+
# # b"\x00\x00"
|
|
308
|
+
# # b"\xff\x00"
|
|
309
|
+
# # b"\x00\xff"
|
|
310
|
+
# # ]
|
|
311
|
+
def tail(n = 5)
|
|
312
|
+
super
|
|
313
|
+
end
|
|
160
314
|
end
|
|
161
315
|
end
|
data/lib/polars/cat_expr.rb
CHANGED
|
@@ -32,5 +32,229 @@ module Polars
|
|
|
32
32
|
def get_categories
|
|
33
33
|
Utils.wrap_expr(_rbexpr.cat_get_categories)
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
# Return the byte-length of the string representation of each value.
|
|
37
|
+
#
|
|
38
|
+
# @return [Expr]
|
|
39
|
+
#
|
|
40
|
+
# @note
|
|
41
|
+
# When working with non-ASCII text, the length in bytes is not the same as the
|
|
42
|
+
# length in characters. You may want to use `len_chars` instead.
|
|
43
|
+
# Note that `len_bytes` is much more performant (_O(1)_) than
|
|
44
|
+
# `len_chars` (_O(n)_).
|
|
45
|
+
#
|
|
46
|
+
# @example
|
|
47
|
+
# df = Polars::DataFrame.new(
|
|
48
|
+
# {"a" => Polars::Series.new(["Café", "345", "東京", nil], dtype: Polars::Categorical)}
|
|
49
|
+
# )
|
|
50
|
+
# df.with_columns(
|
|
51
|
+
# Polars.col("a").cat.len_bytes.alias("n_bytes"),
|
|
52
|
+
# Polars.col("a").cat.len_chars.alias("n_chars")
|
|
53
|
+
# )
|
|
54
|
+
# # =>
|
|
55
|
+
# # shape: (4, 3)
|
|
56
|
+
# # ┌──────┬─────────┬─────────┐
|
|
57
|
+
# # │ a ┆ n_bytes ┆ n_chars │
|
|
58
|
+
# # │ --- ┆ --- ┆ --- │
|
|
59
|
+
# # │ cat ┆ u32 ┆ u32 │
|
|
60
|
+
# # ╞══════╪═════════╪═════════╡
|
|
61
|
+
# # │ Café ┆ 5 ┆ 4 │
|
|
62
|
+
# # │ 345 ┆ 3 ┆ 3 │
|
|
63
|
+
# # │ 東京 ┆ 6 ┆ 2 │
|
|
64
|
+
# # │ null ┆ null ┆ null │
|
|
65
|
+
# # └──────┴─────────┴─────────┘
|
|
66
|
+
def len_bytes
|
|
67
|
+
Utils.wrap_expr(_rbexpr.cat_len_bytes)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Return the number of characters of the string representation of each value.
|
|
71
|
+
#
|
|
72
|
+
# @return [Expr]
|
|
73
|
+
#
|
|
74
|
+
# @note
|
|
75
|
+
# When working with ASCII text, use `len_bytes` instead to achieve
|
|
76
|
+
# equivalent output with much better performance:
|
|
77
|
+
# `len_bytes` runs in _O(1)_, while `len_chars` runs in (_O(n)_).
|
|
78
|
+
#
|
|
79
|
+
# A character is defined as a [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value). A single character is
|
|
80
|
+
# represented by a single byte when working with ASCII text, and a maximum of
|
|
81
|
+
# 4 bytes otherwise.
|
|
82
|
+
#
|
|
83
|
+
# @example
|
|
84
|
+
# df = Polars::DataFrame.new(
|
|
85
|
+
# {"a" => Polars::Series.new(["Café", "345", "東京", nil], dtype: Polars::Categorical)}
|
|
86
|
+
# )
|
|
87
|
+
# df.with_columns(
|
|
88
|
+
# Polars.col("a").cat.len_chars.alias("n_chars"),
|
|
89
|
+
# Polars.col("a").cat.len_bytes.alias("n_bytes")
|
|
90
|
+
# )
|
|
91
|
+
# # =>
|
|
92
|
+
# # shape: (4, 3)
|
|
93
|
+
# # ┌──────┬─────────┬─────────┐
|
|
94
|
+
# # │ a ┆ n_chars ┆ n_bytes │
|
|
95
|
+
# # │ --- ┆ --- ┆ --- │
|
|
96
|
+
# # │ cat ┆ u32 ┆ u32 │
|
|
97
|
+
# # ╞══════╪═════════╪═════════╡
|
|
98
|
+
# # │ Café ┆ 4 ┆ 5 │
|
|
99
|
+
# # │ 345 ┆ 3 ┆ 3 │
|
|
100
|
+
# # │ 東京 ┆ 2 ┆ 6 │
|
|
101
|
+
# # │ null ┆ null ┆ null │
|
|
102
|
+
# # └──────┴─────────┴─────────┘
|
|
103
|
+
def len_chars
|
|
104
|
+
Utils.wrap_expr(_rbexpr.cat_len_chars)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Check if string representations of values start with a substring.
|
|
108
|
+
#
|
|
109
|
+
# @param prefix [String]
|
|
110
|
+
# Prefix substring.
|
|
111
|
+
#
|
|
112
|
+
# @return [Expr]
|
|
113
|
+
#
|
|
114
|
+
# @note
|
|
115
|
+
# Whereas `str.starts_with` allows expression inputs, `cat.starts_with` requires
|
|
116
|
+
# a literal string value.
|
|
117
|
+
#
|
|
118
|
+
# @example
|
|
119
|
+
# df = Polars::DataFrame.new(
|
|
120
|
+
# {"fruits" => Polars::Series.new(["apple", "mango", nil], dtype: Polars::Categorical)}
|
|
121
|
+
# )
|
|
122
|
+
# df.with_columns(
|
|
123
|
+
# Polars.col("fruits").cat.starts_with("app").alias("has_prefix")
|
|
124
|
+
# )
|
|
125
|
+
# # =>
|
|
126
|
+
# # shape: (3, 2)
|
|
127
|
+
# # ┌────────┬────────────┐
|
|
128
|
+
# # │ fruits ┆ has_prefix │
|
|
129
|
+
# # │ --- ┆ --- │
|
|
130
|
+
# # │ cat ┆ bool │
|
|
131
|
+
# # ╞════════╪════════════╡
|
|
132
|
+
# # │ apple ┆ true │
|
|
133
|
+
# # │ mango ┆ false │
|
|
134
|
+
# # │ null ┆ null │
|
|
135
|
+
# # └────────┴────────────┘
|
|
136
|
+
#
|
|
137
|
+
# @example Using `starts_with` as a filter condition:
|
|
138
|
+
# df.filter(Polars.col("fruits").cat.starts_with("app"))
|
|
139
|
+
# # =>
|
|
140
|
+
# # shape: (1, 1)
|
|
141
|
+
# # ┌────────┐
|
|
142
|
+
# # │ fruits │
|
|
143
|
+
# # │ --- │
|
|
144
|
+
# # │ cat │
|
|
145
|
+
# # ╞════════╡
|
|
146
|
+
# # │ apple │
|
|
147
|
+
# # └────────┘
|
|
148
|
+
def starts_with(prefix)
|
|
149
|
+
if !prefix.is_a?(::String)
|
|
150
|
+
msg = "'prefix' must be a string; found #{prefix.inspect}"
|
|
151
|
+
raise TypeError, msg
|
|
152
|
+
end
|
|
153
|
+
Utils.wrap_expr(_rbexpr.cat_starts_with(prefix))
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Check if string representations of values end with a substring.
|
|
157
|
+
#
|
|
158
|
+
# @param suffix [String]
|
|
159
|
+
# Suffix substring.
|
|
160
|
+
#
|
|
161
|
+
# @return [Expr]
|
|
162
|
+
#
|
|
163
|
+
# @note
|
|
164
|
+
# Whereas `str.ends_with` allows expression inputs, `cat.ends_with` requires a
|
|
165
|
+
# literal string value.
|
|
166
|
+
#
|
|
167
|
+
# @example
|
|
168
|
+
# df = Polars::DataFrame.new(
|
|
169
|
+
# {"fruits" => Polars::Series.new(["apple", "mango", nil], dtype: Polars::Categorical)}
|
|
170
|
+
# )
|
|
171
|
+
# df.with_columns(Polars.col("fruits").cat.ends_with("go").alias("has_suffix"))
|
|
172
|
+
# # =>
|
|
173
|
+
# # shape: (3, 2)
|
|
174
|
+
# # ┌────────┬────────────┐
|
|
175
|
+
# # │ fruits ┆ has_suffix │
|
|
176
|
+
# # │ --- ┆ --- │
|
|
177
|
+
# # │ cat ┆ bool │
|
|
178
|
+
# # ╞════════╪════════════╡
|
|
179
|
+
# # │ apple ┆ false │
|
|
180
|
+
# # │ mango ┆ true │
|
|
181
|
+
# # │ null ┆ null │
|
|
182
|
+
# # └────────┴────────────┘
|
|
183
|
+
#
|
|
184
|
+
# @example Using `ends_with` as a filter condition:
|
|
185
|
+
# df.filter(Polars.col("fruits").cat.ends_with("go"))
|
|
186
|
+
# # =>
|
|
187
|
+
# # shape: (1, 1)
|
|
188
|
+
# # ┌────────┐
|
|
189
|
+
# # │ fruits │
|
|
190
|
+
# # │ --- │
|
|
191
|
+
# # │ cat │
|
|
192
|
+
# # ╞════════╡
|
|
193
|
+
# # │ mango │
|
|
194
|
+
# # └────────┘
|
|
195
|
+
def ends_with(suffix)
|
|
196
|
+
if !suffix.is_a?(::String)
|
|
197
|
+
msg = "'suffix' must be a string; found #{suffix.inspect}"
|
|
198
|
+
raise TypeError, msg
|
|
199
|
+
end
|
|
200
|
+
Utils.wrap_expr(_rbexpr.cat_ends_with(suffix))
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Extract a substring from the string representation of each value.
|
|
204
|
+
#
|
|
205
|
+
# @param offset [Integer]
|
|
206
|
+
# Start index. Negative indexing is supported.
|
|
207
|
+
# @param length [Integer]
|
|
208
|
+
# Length of the slice. If set to `nil` (default), the slice is taken to the
|
|
209
|
+
# end of the string.
|
|
210
|
+
#
|
|
211
|
+
# @return [Expr]
|
|
212
|
+
#
|
|
213
|
+
# @note
|
|
214
|
+
# Both the `offset` and `length` inputs are defined in terms of the number
|
|
215
|
+
# of characters in the (UTF8) string. A character is defined as a
|
|
216
|
+
# [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value). A single character is represented by a single byte
|
|
217
|
+
# when working with ASCII text, and a maximum of 4 bytes otherwise.
|
|
218
|
+
#
|
|
219
|
+
# @example
|
|
220
|
+
# df = Polars::DataFrame.new(
|
|
221
|
+
# {
|
|
222
|
+
# "s" => Polars::Series.new(
|
|
223
|
+
# ["pear", nil, "papaya", "dragonfruit"],
|
|
224
|
+
# dtype: Polars::Categorical
|
|
225
|
+
# )
|
|
226
|
+
# }
|
|
227
|
+
# )
|
|
228
|
+
# df.with_columns(Polars.col("s").cat.slice(-3).alias("slice"))
|
|
229
|
+
# # =>
|
|
230
|
+
# # shape: (4, 2)
|
|
231
|
+
# # ┌─────────────┬───────┐
|
|
232
|
+
# # │ s ┆ slice │
|
|
233
|
+
# # │ --- ┆ --- │
|
|
234
|
+
# # │ cat ┆ str │
|
|
235
|
+
# # ╞═════════════╪═══════╡
|
|
236
|
+
# # │ pear ┆ ear │
|
|
237
|
+
# # │ null ┆ null │
|
|
238
|
+
# # │ papaya ┆ aya │
|
|
239
|
+
# # │ dragonfruit ┆ uit │
|
|
240
|
+
# # └─────────────┴───────┘
|
|
241
|
+
#
|
|
242
|
+
# @example Using the optional `length` parameter
|
|
243
|
+
# df.with_columns(Polars.col("s").cat.slice(4, 3).alias("slice"))
|
|
244
|
+
# # =>
|
|
245
|
+
# # shape: (4, 2)
|
|
246
|
+
# # ┌─────────────┬───────┐
|
|
247
|
+
# # │ s ┆ slice │
|
|
248
|
+
# # │ --- ┆ --- │
|
|
249
|
+
# # │ cat ┆ str │
|
|
250
|
+
# # ╞═════════════╪═══════╡
|
|
251
|
+
# # │ pear ┆ │
|
|
252
|
+
# # │ null ┆ null │
|
|
253
|
+
# # │ papaya ┆ ya │
|
|
254
|
+
# # │ dragonfruit ┆ onf │
|
|
255
|
+
# # └─────────────┴───────┘
|
|
256
|
+
def slice(offset, length = nil)
|
|
257
|
+
Utils.wrap_expr(_rbexpr.cat_slice(offset, length))
|
|
258
|
+
end
|
|
35
259
|
end
|
|
36
260
|
end
|