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/string_expr.rb
CHANGED
|
@@ -63,6 +63,13 @@ module Polars
|
|
|
63
63
|
# in the target string.
|
|
64
64
|
# @param cache [Boolean]
|
|
65
65
|
# Use a cache of unique, converted datetimes to apply the conversion.
|
|
66
|
+
# @param ambiguous ['raise', 'earliest', 'latest', 'null']
|
|
67
|
+
# Determine how to deal with ambiguous datetimes:
|
|
68
|
+
#
|
|
69
|
+
# - `'raise'` (default): raise
|
|
70
|
+
# - `'earliest'`: use the earliest datetime
|
|
71
|
+
# - `'latest'`: use the latest datetime
|
|
72
|
+
# - `'null'`: set to null
|
|
66
73
|
#
|
|
67
74
|
# @return [Expr]
|
|
68
75
|
#
|
|
@@ -145,9 +152,15 @@ module Polars
|
|
|
145
152
|
# @param exact [Boolean]
|
|
146
153
|
# - If true, require an exact format match.
|
|
147
154
|
# - If false, allow the format to match anywhere in the target string.
|
|
148
|
-
# @param
|
|
149
|
-
#
|
|
150
|
-
#
|
|
155
|
+
# @param cache [Boolean]
|
|
156
|
+
# Use a cache of unique, converted dates to apply the datetime conversion.
|
|
157
|
+
# @param ambiguous ['raise', 'earliest', 'latest', 'null']
|
|
158
|
+
# Determine how to deal with ambiguous datetimes:
|
|
159
|
+
#
|
|
160
|
+
# - `'raise'` (default): raise
|
|
161
|
+
# - `'earliest'`: use the earliest datetime
|
|
162
|
+
# - `'latest'`: use the latest datetime
|
|
163
|
+
# - `'null'`: set to null
|
|
151
164
|
#
|
|
152
165
|
# @return [Expr]
|
|
153
166
|
#
|
|
@@ -194,7 +207,14 @@ module Polars
|
|
|
194
207
|
# # 2022-01-31
|
|
195
208
|
# # 2001-07-08
|
|
196
209
|
# # ]
|
|
197
|
-
def strptime(
|
|
210
|
+
def strptime(
|
|
211
|
+
dtype,
|
|
212
|
+
format = nil,
|
|
213
|
+
strict: true,
|
|
214
|
+
exact: true,
|
|
215
|
+
cache: true,
|
|
216
|
+
ambiguous: "raise"
|
|
217
|
+
)
|
|
198
218
|
_validate_format_argument(format)
|
|
199
219
|
|
|
200
220
|
if dtype == Date
|
|
@@ -203,7 +223,15 @@ module Polars
|
|
|
203
223
|
dtype = Datetime.new if dtype == Datetime
|
|
204
224
|
time_unit = dtype.time_unit
|
|
205
225
|
time_zone = dtype.time_zone
|
|
206
|
-
to_datetime(
|
|
226
|
+
to_datetime(
|
|
227
|
+
format,
|
|
228
|
+
time_unit: time_unit,
|
|
229
|
+
time_zone: time_zone,
|
|
230
|
+
strict: strict,
|
|
231
|
+
exact: exact,
|
|
232
|
+
cache: cache,
|
|
233
|
+
ambiguous: ambiguous
|
|
234
|
+
)
|
|
207
235
|
elsif dtype == Time
|
|
208
236
|
to_time(format, strict: strict, cache: cache)
|
|
209
237
|
else
|
|
@@ -213,10 +241,8 @@ module Polars
|
|
|
213
241
|
|
|
214
242
|
# Convert a String column into a Decimal column.
|
|
215
243
|
#
|
|
216
|
-
#
|
|
217
|
-
#
|
|
218
|
-
# @param inference_length [Integer]
|
|
219
|
-
# Number of elements to parse to determine the `precision` and `scale`.
|
|
244
|
+
# @param scale [Integer]
|
|
245
|
+
# Number of digits after the comma to use for the decimals.
|
|
220
246
|
#
|
|
221
247
|
# @return [Expr]
|
|
222
248
|
#
|
|
@@ -234,13 +260,13 @@ module Polars
|
|
|
234
260
|
# ]
|
|
235
261
|
# }
|
|
236
262
|
# )
|
|
237
|
-
# df.with_columns(numbers_decimal: Polars.col("numbers").str.to_decimal)
|
|
263
|
+
# df.with_columns(numbers_decimal: Polars.col("numbers").str.to_decimal(scale: 2))
|
|
238
264
|
# # =>
|
|
239
265
|
# # shape: (7, 2)
|
|
240
266
|
# # ┌───────────┬─────────────────┐
|
|
241
267
|
# # │ numbers ┆ numbers_decimal │
|
|
242
268
|
# # │ --- ┆ --- │
|
|
243
|
-
# # │ str ┆ decimal[
|
|
269
|
+
# # │ str ┆ decimal[38,2] │
|
|
244
270
|
# # ╞═══════════╪═════════════════╡
|
|
245
271
|
# # │ 40.12 ┆ 40.12 │
|
|
246
272
|
# # │ 3420.13 ┆ 3420.13 │
|
|
@@ -250,8 +276,8 @@ module Polars
|
|
|
250
276
|
# # │ 143.09 ┆ 143.09 │
|
|
251
277
|
# # │ 143.9 ┆ 143.90 │
|
|
252
278
|
# # └───────────┴─────────────────┘
|
|
253
|
-
def to_decimal(
|
|
254
|
-
Utils.wrap_expr(_rbexpr.str_to_decimal(
|
|
279
|
+
def to_decimal(scale:)
|
|
280
|
+
Utils.wrap_expr(_rbexpr.str_to_decimal(scale))
|
|
255
281
|
end
|
|
256
282
|
|
|
257
283
|
# Get length of the strings as `:u32` (as number of bytes).
|
|
@@ -285,7 +311,6 @@ module Polars
|
|
|
285
311
|
def len_bytes
|
|
286
312
|
Utils.wrap_expr(_rbexpr.str_len_bytes)
|
|
287
313
|
end
|
|
288
|
-
alias_method :lengths, :len_bytes
|
|
289
314
|
|
|
290
315
|
# Get length of the strings as `:u32` (as number of chars).
|
|
291
316
|
#
|
|
@@ -318,7 +343,6 @@ module Polars
|
|
|
318
343
|
def len_chars
|
|
319
344
|
Utils.wrap_expr(_rbexpr.str_len_chars)
|
|
320
345
|
end
|
|
321
|
-
alias_method :n_chars, :len_chars
|
|
322
346
|
|
|
323
347
|
# Vertically concat the values in the Series to a single string value.
|
|
324
348
|
#
|
|
@@ -354,10 +378,74 @@ module Polars
|
|
|
354
378
|
# # ╞══════╡
|
|
355
379
|
# # │ null │
|
|
356
380
|
# # └──────┘
|
|
357
|
-
def join(delimiter = "
|
|
381
|
+
def join(delimiter = "", ignore_nulls: true)
|
|
358
382
|
Utils.wrap_expr(_rbexpr.str_join(delimiter, ignore_nulls))
|
|
359
383
|
end
|
|
360
|
-
|
|
384
|
+
|
|
385
|
+
# Returns string values with all regular expression meta characters escaped.
|
|
386
|
+
#
|
|
387
|
+
# @return [Expr]
|
|
388
|
+
#
|
|
389
|
+
# @example
|
|
390
|
+
# df = Polars::DataFrame.new({"text" => ["abc", "def", nil, "abc(\\w+)"]})
|
|
391
|
+
# df.with_columns(Polars.col("text").str.escape_regex.alias("escaped"))
|
|
392
|
+
# # =>
|
|
393
|
+
# # shape: (4, 2)
|
|
394
|
+
# # ┌──────────┬──────────────┐
|
|
395
|
+
# # │ text ┆ escaped │
|
|
396
|
+
# # │ --- ┆ --- │
|
|
397
|
+
# # │ str ┆ str │
|
|
398
|
+
# # ╞══════════╪══════════════╡
|
|
399
|
+
# # │ abc ┆ abc │
|
|
400
|
+
# # │ def ┆ def │
|
|
401
|
+
# # │ null ┆ null │
|
|
402
|
+
# # │ abc(\w+) ┆ abc\(\\w\+\) │
|
|
403
|
+
# # └──────────┴──────────────┘
|
|
404
|
+
def escape_regex
|
|
405
|
+
Utils.wrap_expr(_rbexpr.str_escape_regex)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Returns the Unicode normal form of the string values.
|
|
409
|
+
#
|
|
410
|
+
# This uses the forms described in Unicode Standard Annex 15: <https://www.unicode.org/reports/tr15/>.
|
|
411
|
+
#
|
|
412
|
+
# @param form ['NFC', 'NFKC', 'NFD', 'NFKD']
|
|
413
|
+
# Unicode form to use.
|
|
414
|
+
#
|
|
415
|
+
# @return [Expr]
|
|
416
|
+
#
|
|
417
|
+
# @example
|
|
418
|
+
# df = Polars::DataFrame.new({"text" => ["01²", "KADOKAWA"]})
|
|
419
|
+
# new = df.with_columns(
|
|
420
|
+
# nfc: Polars.col("text").str.normalize("NFC"),
|
|
421
|
+
# nfkc: Polars.col("text").str.normalize("NFKC")
|
|
422
|
+
# )
|
|
423
|
+
# # =>
|
|
424
|
+
# # shape: (2, 3)
|
|
425
|
+
# # ┌──────────────────┬──────────────────┬──────────┐
|
|
426
|
+
# # │ text ┆ nfc ┆ nfkc │
|
|
427
|
+
# # │ --- ┆ --- ┆ --- │
|
|
428
|
+
# # │ str ┆ str ┆ str │
|
|
429
|
+
# # ╞══════════════════╪══════════════════╪══════════╡
|
|
430
|
+
# # │ 01² ┆ 01² ┆ 012 │
|
|
431
|
+
# # │ KADOKAWA ┆ KADOKAWA ┆ KADOKAWA │
|
|
432
|
+
# # └──────────────────┴──────────────────┴──────────┘
|
|
433
|
+
#
|
|
434
|
+
# @example
|
|
435
|
+
# new.select(Polars.all.str.len_bytes)
|
|
436
|
+
# # =>
|
|
437
|
+
# # shape: (2, 3)
|
|
438
|
+
# # ┌──────┬─────┬──────┐
|
|
439
|
+
# # │ text ┆ nfc ┆ nfkc │
|
|
440
|
+
# # │ --- ┆ --- ┆ --- │
|
|
441
|
+
# # │ u32 ┆ u32 ┆ u32 │
|
|
442
|
+
# # ╞══════╪═════╪══════╡
|
|
443
|
+
# # │ 4 ┆ 4 ┆ 3 │
|
|
444
|
+
# # │ 24 ┆ 24 ┆ 8 │
|
|
445
|
+
# # └──────┴─────┴──────┘
|
|
446
|
+
def normalize(form = "NFC")
|
|
447
|
+
Utils.wrap_expr(_rbexpr.str_normalize(form))
|
|
448
|
+
end
|
|
361
449
|
|
|
362
450
|
# Transform to uppercase variant.
|
|
363
451
|
#
|
|
@@ -433,7 +521,7 @@ module Polars
|
|
|
433
521
|
#
|
|
434
522
|
# @example
|
|
435
523
|
# df = Polars::DataFrame.new({"foo" => [" lead", "trail ", " both "]})
|
|
436
|
-
# df.select(Polars.col("foo").str.
|
|
524
|
+
# df.select(Polars.col("foo").str.strip_chars)
|
|
437
525
|
# # =>
|
|
438
526
|
# # shape: (3, 1)
|
|
439
527
|
# # ┌───────┐
|
|
@@ -449,7 +537,6 @@ module Polars
|
|
|
449
537
|
characters = Utils.parse_into_expression(characters, str_as_lit: true)
|
|
450
538
|
Utils.wrap_expr(_rbexpr.str_strip_chars(characters))
|
|
451
539
|
end
|
|
452
|
-
alias_method :strip, :strip_chars
|
|
453
540
|
|
|
454
541
|
# Remove leading whitespace.
|
|
455
542
|
#
|
|
@@ -460,7 +547,7 @@ module Polars
|
|
|
460
547
|
#
|
|
461
548
|
# @example
|
|
462
549
|
# df = Polars::DataFrame.new({"foo" => [" lead", "trail ", " both "]})
|
|
463
|
-
# df.select(Polars.col("foo").str.
|
|
550
|
+
# df.select(Polars.col("foo").str.strip_chars_start)
|
|
464
551
|
# # =>
|
|
465
552
|
# # shape: (3, 1)
|
|
466
553
|
# # ┌────────┐
|
|
@@ -476,7 +563,6 @@ module Polars
|
|
|
476
563
|
characters = Utils.parse_into_expression(characters, str_as_lit: true)
|
|
477
564
|
Utils.wrap_expr(_rbexpr.str_strip_chars_start(characters))
|
|
478
565
|
end
|
|
479
|
-
alias_method :lstrip, :strip_chars_start
|
|
480
566
|
|
|
481
567
|
# Remove trailing whitespace.
|
|
482
568
|
#
|
|
@@ -487,7 +573,7 @@ module Polars
|
|
|
487
573
|
#
|
|
488
574
|
# @example
|
|
489
575
|
# df = Polars::DataFrame.new({"foo" => [" lead", "trail ", " both "]})
|
|
490
|
-
# df.select(Polars.col("foo").str.
|
|
576
|
+
# df.select(Polars.col("foo").str.strip_chars_end)
|
|
491
577
|
# # =>
|
|
492
578
|
# # shape: (3, 1)
|
|
493
579
|
# # ┌───────┐
|
|
@@ -503,7 +589,6 @@ module Polars
|
|
|
503
589
|
characters = Utils.parse_into_expression(characters, str_as_lit: true)
|
|
504
590
|
Utils.wrap_expr(_rbexpr.str_strip_chars_end(characters))
|
|
505
591
|
end
|
|
506
|
-
alias_method :rstrip, :strip_chars_end
|
|
507
592
|
|
|
508
593
|
# Remove prefix.
|
|
509
594
|
#
|
|
@@ -590,9 +675,9 @@ module Polars
|
|
|
590
675
|
# # │ null ┆ null │
|
|
591
676
|
# # └──────────────┴──────────────┘
|
|
592
677
|
def pad_start(length, fill_char = " ")
|
|
678
|
+
length = Utils.parse_into_expression(length)
|
|
593
679
|
Utils.wrap_expr(_rbexpr.str_pad_start(length, fill_char))
|
|
594
680
|
end
|
|
595
|
-
alias_method :rjust, :pad_start
|
|
596
681
|
|
|
597
682
|
# Pad the end of the string until it reaches the given length.
|
|
598
683
|
#
|
|
@@ -620,9 +705,9 @@ module Polars
|
|
|
620
705
|
# # │ null ┆ null │
|
|
621
706
|
# # └──────────────┴──────────────┘
|
|
622
707
|
def pad_end(length, fill_char = " ")
|
|
708
|
+
length = Utils.parse_into_expression(length)
|
|
623
709
|
Utils.wrap_expr(_rbexpr.str_pad_end(length, fill_char))
|
|
624
710
|
end
|
|
625
|
-
alias_method :ljust, :pad_end
|
|
626
711
|
|
|
627
712
|
# Fills the string with zeroes.
|
|
628
713
|
#
|
|
@@ -664,6 +749,9 @@ module Polars
|
|
|
664
749
|
# A valid regex pattern.
|
|
665
750
|
# @param literal [Boolean]
|
|
666
751
|
# Treat pattern as a literal string.
|
|
752
|
+
# @param strict [Boolean]
|
|
753
|
+
# Raise an error if the underlying pattern is not a valid regex,
|
|
754
|
+
# otherwise mask out with a null value.
|
|
667
755
|
#
|
|
668
756
|
# @return [Expr]
|
|
669
757
|
#
|
|
@@ -693,16 +781,78 @@ module Polars
|
|
|
693
781
|
Utils.wrap_expr(_rbexpr.str_contains(pattern, literal, strict))
|
|
694
782
|
end
|
|
695
783
|
|
|
784
|
+
# Return the bytes offset of the first substring matching a pattern.
|
|
785
|
+
#
|
|
786
|
+
# If the pattern is not found, returns nil.
|
|
787
|
+
#
|
|
788
|
+
# @param pattern [String]
|
|
789
|
+
# A valid regular expression pattern, compatible with the [regex crate](https://docs.rs/regex/latest/regex/).
|
|
790
|
+
# @param literal [Boolean]
|
|
791
|
+
# Treat `pattern` as a literal string, not as a regular expression.
|
|
792
|
+
# @param strict [Boolean]
|
|
793
|
+
# Raise an error if the underlying pattern is not a valid regex,
|
|
794
|
+
# otherwise mask out with a null value.
|
|
795
|
+
#
|
|
796
|
+
# @return [Expr]
|
|
797
|
+
#
|
|
798
|
+
# @note
|
|
799
|
+
# To modify regular expression behaviour (such as case-sensitivity) with
|
|
800
|
+
# flags, use the inline `(?iLmsuxU)` syntax.
|
|
801
|
+
#
|
|
802
|
+
# @example Find the index of the first substring matching a regex or literal pattern:
|
|
803
|
+
# df = Polars::DataFrame.new(
|
|
804
|
+
# {
|
|
805
|
+
# "txt" => ["Crab", "Lobster", nil, "Crustacean"],
|
|
806
|
+
# "pat" => ["a[bc]", "b.t", "[aeiuo]", "(?i)A[BC]"]
|
|
807
|
+
# }
|
|
808
|
+
# )
|
|
809
|
+
# df.select(
|
|
810
|
+
# Polars.col("txt"),
|
|
811
|
+
# Polars.col("txt").str.find("a|e").alias("a|e (regex)"),
|
|
812
|
+
# Polars.col("txt").str.find("e", literal: true).alias("e (lit)"),
|
|
813
|
+
# )
|
|
814
|
+
# # =>
|
|
815
|
+
# # shape: (4, 3)
|
|
816
|
+
# # ┌────────────┬─────────────┬─────────┐
|
|
817
|
+
# # │ txt ┆ a|e (regex) ┆ e (lit) │
|
|
818
|
+
# # │ --- ┆ --- ┆ --- │
|
|
819
|
+
# # │ str ┆ u32 ┆ u32 │
|
|
820
|
+
# # ╞════════════╪═════════════╪═════════╡
|
|
821
|
+
# # │ Crab ┆ 2 ┆ null │
|
|
822
|
+
# # │ Lobster ┆ 5 ┆ 5 │
|
|
823
|
+
# # │ null ┆ null ┆ null │
|
|
824
|
+
# # │ Crustacean ┆ 5 ┆ 7 │
|
|
825
|
+
# # └────────────┴─────────────┴─────────┘
|
|
826
|
+
#
|
|
827
|
+
# @example Match against a pattern found in another column or (expression):
|
|
828
|
+
# df.with_columns(Polars.col("txt").str.find(Polars.col("pat")).alias("find_pat"))
|
|
829
|
+
# # =>
|
|
830
|
+
# # shape: (4, 3)
|
|
831
|
+
# # ┌────────────┬───────────┬──────────┐
|
|
832
|
+
# # │ txt ┆ pat ┆ find_pat │
|
|
833
|
+
# # │ --- ┆ --- ┆ --- │
|
|
834
|
+
# # │ str ┆ str ┆ u32 │
|
|
835
|
+
# # ╞════════════╪═══════════╪══════════╡
|
|
836
|
+
# # │ Crab ┆ a[bc] ┆ 2 │
|
|
837
|
+
# # │ Lobster ┆ b.t ┆ 2 │
|
|
838
|
+
# # │ null ┆ [aeiuo] ┆ null │
|
|
839
|
+
# # │ Crustacean ┆ (?i)A[BC] ┆ 5 │
|
|
840
|
+
# # └────────────┴───────────┴──────────┘
|
|
841
|
+
def find(pattern, literal: false, strict: true)
|
|
842
|
+
pattern = Utils.parse_into_expression(pattern, str_as_lit: true)
|
|
843
|
+
Utils.wrap_expr(_rbexpr.str_find(pattern, literal, strict))
|
|
844
|
+
end
|
|
845
|
+
|
|
696
846
|
# Check if string values end with a substring.
|
|
697
847
|
#
|
|
698
|
-
# @param
|
|
848
|
+
# @param suffix [String]
|
|
699
849
|
# Suffix substring.
|
|
700
850
|
#
|
|
701
851
|
# @return [Expr]
|
|
702
852
|
#
|
|
703
853
|
# @example
|
|
704
854
|
# df = Polars::DataFrame.new({"fruits" => ["apple", "mango", nil]})
|
|
705
|
-
# df.
|
|
855
|
+
# df.with_columns(
|
|
706
856
|
# Polars.col("fruits").str.ends_with("go").alias("has_suffix")
|
|
707
857
|
# )
|
|
708
858
|
# # =>
|
|
@@ -728,21 +878,21 @@ module Polars
|
|
|
728
878
|
# # ╞════════╡
|
|
729
879
|
# # │ mango │
|
|
730
880
|
# # └────────┘
|
|
731
|
-
def ends_with(
|
|
732
|
-
|
|
733
|
-
Utils.wrap_expr(_rbexpr.str_ends_with(
|
|
881
|
+
def ends_with(suffix)
|
|
882
|
+
suffix_rbexpr = Utils.parse_into_expression(suffix, str_as_lit: true)
|
|
883
|
+
Utils.wrap_expr(_rbexpr.str_ends_with(suffix_rbexpr))
|
|
734
884
|
end
|
|
735
885
|
|
|
736
886
|
# Check if string values start with a substring.
|
|
737
887
|
#
|
|
738
|
-
# @param
|
|
888
|
+
# @param prefix [String]
|
|
739
889
|
# Prefix substring.
|
|
740
890
|
#
|
|
741
891
|
# @return [Expr]
|
|
742
892
|
#
|
|
743
893
|
# @example
|
|
744
894
|
# df = Polars::DataFrame.new({"fruits" => ["apple", "mango", nil]})
|
|
745
|
-
# df.
|
|
895
|
+
# df.with_columns(
|
|
746
896
|
# Polars.col("fruits").str.starts_with("app").alias("has_prefix")
|
|
747
897
|
# )
|
|
748
898
|
# # =>
|
|
@@ -768,9 +918,9 @@ module Polars
|
|
|
768
918
|
# # ╞════════╡
|
|
769
919
|
# # │ apple │
|
|
770
920
|
# # └────────┘
|
|
771
|
-
def starts_with(
|
|
772
|
-
|
|
773
|
-
Utils.wrap_expr(_rbexpr.str_starts_with(
|
|
921
|
+
def starts_with(prefix)
|
|
922
|
+
prefix_rbexpr = Utils.parse_into_expression(prefix, str_as_lit: true)
|
|
923
|
+
Utils.wrap_expr(_rbexpr.str_starts_with(prefix_rbexpr))
|
|
774
924
|
end
|
|
775
925
|
|
|
776
926
|
# Parse string values as JSON.
|
|
@@ -778,8 +928,9 @@ module Polars
|
|
|
778
928
|
# Throw errors if encounter invalid JSON strings.
|
|
779
929
|
#
|
|
780
930
|
# @param dtype [Object]
|
|
781
|
-
# The dtype to cast the extracted value to.
|
|
782
|
-
#
|
|
931
|
+
# The dtype to cast the extracted value to.
|
|
932
|
+
# @param infer_schema_length [Integer]
|
|
933
|
+
# Deprecated and ignored.
|
|
783
934
|
#
|
|
784
935
|
# @return [Expr]
|
|
785
936
|
#
|
|
@@ -788,25 +939,27 @@ module Polars
|
|
|
788
939
|
# {"json" => ['{"a":1, "b": true}', nil, '{"a":2, "b": false}']}
|
|
789
940
|
# )
|
|
790
941
|
# dtype = Polars::Struct.new([Polars::Field.new("a", Polars::Int64), Polars::Field.new("b", Polars::Boolean)])
|
|
791
|
-
# df.
|
|
942
|
+
# df.with_columns(decoded: Polars.col("json").str.json_decode(dtype))
|
|
792
943
|
# # =>
|
|
793
|
-
# # shape: (3,
|
|
794
|
-
# #
|
|
795
|
-
# # │ json
|
|
796
|
-
# # │ --- │
|
|
797
|
-
# # │ struct[2] │
|
|
798
|
-
# #
|
|
799
|
-
# # │ {1,true} │
|
|
800
|
-
# # │ null │
|
|
801
|
-
# # │ {2,false} │
|
|
802
|
-
# #
|
|
803
|
-
def json_decode(dtype
|
|
804
|
-
if
|
|
805
|
-
|
|
944
|
+
# # shape: (3, 2)
|
|
945
|
+
# # ┌─────────────────────┬───────────┐
|
|
946
|
+
# # │ json ┆ decoded │
|
|
947
|
+
# # │ --- ┆ --- │
|
|
948
|
+
# # │ str ┆ struct[2] │
|
|
949
|
+
# # ╞═════════════════════╪═══════════╡
|
|
950
|
+
# # │ {"a":1, "b": true} ┆ {1,true} │
|
|
951
|
+
# # │ null ┆ null │
|
|
952
|
+
# # │ {"a":2, "b": false} ┆ {2,false} │
|
|
953
|
+
# # └─────────────────────┴───────────┘
|
|
954
|
+
def json_decode(dtype, infer_schema_length: nil)
|
|
955
|
+
if dtype.nil?
|
|
956
|
+
msg = "`Expr.str.json_decode` needs an explicitly given `dtype` otherwise Polars is not able to determine the output type. If you want to eagerly infer datatype you can use `Series.str.json_decode`."
|
|
957
|
+
raise TypeError, msg
|
|
806
958
|
end
|
|
807
|
-
|
|
959
|
+
|
|
960
|
+
dtype_expr = Utils.parse_into_datatype_expr(dtype)._rbdatatype_expr
|
|
961
|
+
Utils.wrap_expr(_rbexpr.str_json_decode(dtype_expr))
|
|
808
962
|
end
|
|
809
|
-
alias_method :json_extract, :json_decode
|
|
810
963
|
|
|
811
964
|
# Extract the first match of json string with provided JSONPath expression.
|
|
812
965
|
#
|
|
@@ -1036,6 +1189,8 @@ module Polars
|
|
|
1036
1189
|
#
|
|
1037
1190
|
# @param pattern [String]
|
|
1038
1191
|
# A valid regex pattern
|
|
1192
|
+
# @param literal [Boolean]
|
|
1193
|
+
# Treat `pattern` as a literal string, not as a regular expression.
|
|
1039
1194
|
#
|
|
1040
1195
|
# @return [Expr]
|
|
1041
1196
|
#
|
|
@@ -1043,7 +1198,7 @@ module Polars
|
|
|
1043
1198
|
# df = Polars::DataFrame.new({"foo" => ["123 bla 45 asd", "xyz 678 910t"]})
|
|
1044
1199
|
# df.select(
|
|
1045
1200
|
# [
|
|
1046
|
-
# Polars.col("foo").str.
|
|
1201
|
+
# Polars.col("foo").str.count_matches('\d').alias("count_digits")
|
|
1047
1202
|
# ]
|
|
1048
1203
|
# )
|
|
1049
1204
|
# # =>
|
|
@@ -1060,7 +1215,6 @@ module Polars
|
|
|
1060
1215
|
pattern = Utils.parse_into_expression(pattern, str_as_lit: true)
|
|
1061
1216
|
Utils.wrap_expr(_rbexpr.str_count_matches(pattern, literal))
|
|
1062
1217
|
end
|
|
1063
|
-
alias_method :count_match, :count_matches
|
|
1064
1218
|
|
|
1065
1219
|
# Split the string by a substring.
|
|
1066
1220
|
#
|
|
@@ -1068,6 +1222,11 @@ module Polars
|
|
|
1068
1222
|
# Substring to split by.
|
|
1069
1223
|
# @param inclusive [Boolean]
|
|
1070
1224
|
# If true, include the split character/string in the results.
|
|
1225
|
+
# @param literal [Boolean]
|
|
1226
|
+
# Treat `by` as a literal string, not as a regular expression.
|
|
1227
|
+
# @param strict [Boolean]
|
|
1228
|
+
# Raise an error if the underlying pattern is not a valid regex,
|
|
1229
|
+
# otherwise mask out with a null value.
|
|
1071
1230
|
#
|
|
1072
1231
|
# @return [Expr]
|
|
1073
1232
|
#
|
|
@@ -1085,12 +1244,22 @@ module Polars
|
|
|
1085
1244
|
# # │ ["foo-bar"] │
|
|
1086
1245
|
# # │ ["foo", "bar", "baz"] │
|
|
1087
1246
|
# # └───────────────────────┘
|
|
1088
|
-
def split(by, inclusive: false)
|
|
1089
|
-
|
|
1247
|
+
def split(by, inclusive: false, literal: true, strict: true)
|
|
1248
|
+
by_rbexpr = Utils.parse_into_expression(by, str_as_lit: true)
|
|
1249
|
+
|
|
1250
|
+
if !literal
|
|
1251
|
+
if inclusive
|
|
1252
|
+
return Utils.wrap_expr(
|
|
1253
|
+
_rbexpr.str_split_regex_inclusive(by_rbexpr, strict)
|
|
1254
|
+
)
|
|
1255
|
+
end
|
|
1256
|
+
return Utils.wrap_expr(_rbexpr.str_split_regex(by_rbexpr, strict))
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1090
1259
|
if inclusive
|
|
1091
|
-
return Utils.wrap_expr(_rbexpr.str_split_inclusive(
|
|
1260
|
+
return Utils.wrap_expr(_rbexpr.str_split_inclusive(by_rbexpr))
|
|
1092
1261
|
end
|
|
1093
|
-
Utils.wrap_expr(_rbexpr.str_split(
|
|
1262
|
+
Utils.wrap_expr(_rbexpr.str_split(by_rbexpr))
|
|
1094
1263
|
end
|
|
1095
1264
|
|
|
1096
1265
|
# Split the string by a substring using `n` splits.
|
|
@@ -1177,12 +1346,14 @@ module Polars
|
|
|
1177
1346
|
# Replacement string.
|
|
1178
1347
|
# @param literal [Boolean]
|
|
1179
1348
|
# Treat pattern as a literal string.
|
|
1349
|
+
# @param n [Integer]
|
|
1350
|
+
# Number of matches to replace.
|
|
1180
1351
|
#
|
|
1181
1352
|
# @return [Expr]
|
|
1182
1353
|
#
|
|
1183
1354
|
# @example
|
|
1184
1355
|
# df = Polars::DataFrame.new({"id" => [1, 2], "text" => ["123abc", "abc456"]})
|
|
1185
|
-
# df.
|
|
1356
|
+
# df.with_columns(
|
|
1186
1357
|
# Polars.col("text").str.replace('abc\b', "ABC")
|
|
1187
1358
|
# )
|
|
1188
1359
|
# # =>
|
|
@@ -1214,7 +1385,7 @@ module Polars
|
|
|
1214
1385
|
#
|
|
1215
1386
|
# @example
|
|
1216
1387
|
# df = Polars::DataFrame.new({"id" => [1, 2], "text" => ["abcabc", "123a123"]})
|
|
1217
|
-
# df.
|
|
1388
|
+
# df.with_columns(Polars.col("text").str.replace_all("a", "-"))
|
|
1218
1389
|
# # =>
|
|
1219
1390
|
# # shape: (2, 2)
|
|
1220
1391
|
# # ┌─────┬─────────┐
|
|
@@ -1265,7 +1436,7 @@ module Polars
|
|
|
1265
1436
|
#
|
|
1266
1437
|
# @example
|
|
1267
1438
|
# df = Polars::DataFrame.new({"s" => ["pear", nil, "papaya", "dragonfruit"]})
|
|
1268
|
-
# df.
|
|
1439
|
+
# df.with_columns(
|
|
1269
1440
|
# Polars.col("s").str.slice(-3).alias("s_sliced")
|
|
1270
1441
|
# )
|
|
1271
1442
|
# # =>
|
|
@@ -1286,6 +1457,130 @@ module Polars
|
|
|
1286
1457
|
Utils.wrap_expr(_rbexpr.str_slice(offset, length))
|
|
1287
1458
|
end
|
|
1288
1459
|
|
|
1460
|
+
# Return the first n characters of each string in a String Series.
|
|
1461
|
+
#
|
|
1462
|
+
# @param n [Integer]
|
|
1463
|
+
# Length of the slice (integer or expression). Negative indexing is supported;
|
|
1464
|
+
# see note (2) below.
|
|
1465
|
+
#
|
|
1466
|
+
# @return [Expr]
|
|
1467
|
+
#
|
|
1468
|
+
# @note
|
|
1469
|
+
# 1) The `n` input is defined in terms of the number of characters in the (UTF8)
|
|
1470
|
+
# string. A character is defined as a [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value). A single
|
|
1471
|
+
# character is represented by a single byte when working with ASCII text, and a
|
|
1472
|
+
# maximum of 4 bytes otherwise.
|
|
1473
|
+
#
|
|
1474
|
+
# 2) When the `n` input is negative, `head` returns characters up to the `n`th
|
|
1475
|
+
# from the end of the string. For example, if `n = -3`, then all characters
|
|
1476
|
+
# except the last three are returned.
|
|
1477
|
+
#
|
|
1478
|
+
# 3) If the length of the string has fewer than `n` characters, the full string is
|
|
1479
|
+
# returned.
|
|
1480
|
+
#
|
|
1481
|
+
# @example Return up to the first 5 characters:
|
|
1482
|
+
# df = Polars::DataFrame.new({"s" => ["pear", nil, "papaya", "dragonfruit"]})
|
|
1483
|
+
# df.with_columns(Polars.col("s").str.head(5).alias("s_head_5"))
|
|
1484
|
+
# # =>
|
|
1485
|
+
# # shape: (4, 2)
|
|
1486
|
+
# # ┌─────────────┬──────────┐
|
|
1487
|
+
# # │ s ┆ s_head_5 │
|
|
1488
|
+
# # │ --- ┆ --- │
|
|
1489
|
+
# # │ str ┆ str │
|
|
1490
|
+
# # ╞═════════════╪══════════╡
|
|
1491
|
+
# # │ pear ┆ pear │
|
|
1492
|
+
# # │ null ┆ null │
|
|
1493
|
+
# # │ papaya ┆ papay │
|
|
1494
|
+
# # │ dragonfruit ┆ drago │
|
|
1495
|
+
# # └─────────────┴──────────┘
|
|
1496
|
+
#
|
|
1497
|
+
# @example Return characters determined by column `n`:
|
|
1498
|
+
# df = Polars::DataFrame.new(
|
|
1499
|
+
# {
|
|
1500
|
+
# "s" => ["pear", nil, "papaya", "dragonfruit"],
|
|
1501
|
+
# "n" => [3, 4, -2, -5]
|
|
1502
|
+
# }
|
|
1503
|
+
# )
|
|
1504
|
+
# df.with_columns(Polars.col("s").str.head("n").alias("s_head_n"))
|
|
1505
|
+
# # =>
|
|
1506
|
+
# # shape: (4, 3)
|
|
1507
|
+
# # ┌─────────────┬─────┬──────────┐
|
|
1508
|
+
# # │ s ┆ n ┆ s_head_n │
|
|
1509
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1510
|
+
# # │ str ┆ i64 ┆ str │
|
|
1511
|
+
# # ╞═════════════╪═════╪══════════╡
|
|
1512
|
+
# # │ pear ┆ 3 ┆ pea │
|
|
1513
|
+
# # │ null ┆ 4 ┆ null │
|
|
1514
|
+
# # │ papaya ┆ -2 ┆ papa │
|
|
1515
|
+
# # │ dragonfruit ┆ -5 ┆ dragon │
|
|
1516
|
+
# # └─────────────┴─────┴──────────┘
|
|
1517
|
+
def head(n)
|
|
1518
|
+
n = Utils.parse_into_expression(n)
|
|
1519
|
+
Utils.wrap_expr(_rbexpr.str_head(n))
|
|
1520
|
+
end
|
|
1521
|
+
|
|
1522
|
+
# Return the last n characters of each string in a String Series.
|
|
1523
|
+
#
|
|
1524
|
+
# @param n [Integer]
|
|
1525
|
+
# Length of the slice (integer or expression). Negative indexing is supported;
|
|
1526
|
+
# see note (2) below.
|
|
1527
|
+
#
|
|
1528
|
+
# @return [Expr]
|
|
1529
|
+
#
|
|
1530
|
+
# @note
|
|
1531
|
+
# 1) The `n` input is defined in terms of the number of characters in the (UTF8)
|
|
1532
|
+
# string. A character is defined as a [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value). A single
|
|
1533
|
+
# character is represented by a single byte when working with ASCII text, and a
|
|
1534
|
+
# maximum of 4 bytes otherwise.
|
|
1535
|
+
#
|
|
1536
|
+
# 2) When the `n` input is negative, `tail` returns characters starting from the
|
|
1537
|
+
# `n`th from the beginning of the string. For example, if `n = -3`, then all
|
|
1538
|
+
# characters except the first three are returned.
|
|
1539
|
+
#
|
|
1540
|
+
# 3) If the length of the string has fewer than `n` characters, the full string is
|
|
1541
|
+
# returned.
|
|
1542
|
+
#
|
|
1543
|
+
# @example Return up to the last 5 characters:
|
|
1544
|
+
# df = Polars::DataFrame.new({"s" => ["pear", nil, "papaya", "dragonfruit"]})
|
|
1545
|
+
# df.with_columns(Polars.col("s").str.tail(5).alias("s_tail_5"))
|
|
1546
|
+
# # =>
|
|
1547
|
+
# # shape: (4, 2)
|
|
1548
|
+
# # ┌─────────────┬──────────┐
|
|
1549
|
+
# # │ s ┆ s_tail_5 │
|
|
1550
|
+
# # │ --- ┆ --- │
|
|
1551
|
+
# # │ str ┆ str │
|
|
1552
|
+
# # ╞═════════════╪══════════╡
|
|
1553
|
+
# # │ pear ┆ pear │
|
|
1554
|
+
# # │ null ┆ null │
|
|
1555
|
+
# # │ papaya ┆ apaya │
|
|
1556
|
+
# # │ dragonfruit ┆ fruit │
|
|
1557
|
+
# # └─────────────┴──────────┘
|
|
1558
|
+
#
|
|
1559
|
+
# @example Return characters determined by column `n`:
|
|
1560
|
+
# df = Polars::DataFrame.new(
|
|
1561
|
+
# {
|
|
1562
|
+
# "s" => ["pear", nil, "papaya", "dragonfruit"],
|
|
1563
|
+
# "n" => [3, 4, -2, -5]
|
|
1564
|
+
# }
|
|
1565
|
+
# )
|
|
1566
|
+
# df.with_columns(Polars.col("s").str.tail("n").alias("s_tail_n"))
|
|
1567
|
+
# # =>
|
|
1568
|
+
# # shape: (4, 3)
|
|
1569
|
+
# # ┌─────────────┬─────┬──────────┐
|
|
1570
|
+
# # │ s ┆ n ┆ s_tail_n │
|
|
1571
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1572
|
+
# # │ str ┆ i64 ┆ str │
|
|
1573
|
+
# # ╞═════════════╪═════╪══════════╡
|
|
1574
|
+
# # │ pear ┆ 3 ┆ ear │
|
|
1575
|
+
# # │ null ┆ 4 ┆ null │
|
|
1576
|
+
# # │ papaya ┆ -2 ┆ paya │
|
|
1577
|
+
# # │ dragonfruit ┆ -5 ┆ nfruit │
|
|
1578
|
+
# # └─────────────┴─────┴──────────┘
|
|
1579
|
+
def tail(n)
|
|
1580
|
+
n = Utils.parse_into_expression(n)
|
|
1581
|
+
Utils.wrap_expr(_rbexpr.str_tail(n))
|
|
1582
|
+
end
|
|
1583
|
+
|
|
1289
1584
|
# Convert an Utf8 column into an Int64 column with base radix.
|
|
1290
1585
|
#
|
|
1291
1586
|
# @param base [Integer]
|
|
@@ -1328,41 +1623,9 @@ module Polars
|
|
|
1328
1623
|
# # │ cafe ┆ 51966 │
|
|
1329
1624
|
# # │ null ┆ null │
|
|
1330
1625
|
# # └──────┴────────┘
|
|
1331
|
-
def to_integer(base: 10, strict: true)
|
|
1626
|
+
def to_integer(base: 10, dtype: Int64, strict: true)
|
|
1332
1627
|
base = Utils.parse_into_expression(base, str_as_lit: false)
|
|
1333
|
-
Utils.wrap_expr(_rbexpr.str_to_integer(base, strict))
|
|
1334
|
-
end
|
|
1335
|
-
|
|
1336
|
-
# Parse integers with base radix from strings.
|
|
1337
|
-
#
|
|
1338
|
-
# By default base 2. ParseError/Overflows become Nulls.
|
|
1339
|
-
#
|
|
1340
|
-
# @param radix [Integer]
|
|
1341
|
-
# Positive integer which is the base of the string we are parsing.
|
|
1342
|
-
# Default: 2.
|
|
1343
|
-
# @param strict [Boolean]
|
|
1344
|
-
# Bool, Default=true will raise any ParseError or overflow as ComputeError.
|
|
1345
|
-
# False silently convert to Null.
|
|
1346
|
-
#
|
|
1347
|
-
# @return [Expr]
|
|
1348
|
-
#
|
|
1349
|
-
# @example
|
|
1350
|
-
# df = Polars::DataFrame.new({"bin" => ["110", "101", "010", "invalid"]})
|
|
1351
|
-
# df.select(Polars.col("bin").str.parse_int(2, strict: false))
|
|
1352
|
-
# # =>
|
|
1353
|
-
# # shape: (4, 1)
|
|
1354
|
-
# # ┌──────┐
|
|
1355
|
-
# # │ bin │
|
|
1356
|
-
# # │ --- │
|
|
1357
|
-
# # │ i32 │
|
|
1358
|
-
# # ╞══════╡
|
|
1359
|
-
# # │ 6 │
|
|
1360
|
-
# # │ 5 │
|
|
1361
|
-
# # │ 2 │
|
|
1362
|
-
# # │ null │
|
|
1363
|
-
# # └──────┘
|
|
1364
|
-
def parse_int(radix = 2, strict: true)
|
|
1365
|
-
to_integer(base: 2, strict: strict).cast(Int32, strict: strict)
|
|
1628
|
+
Utils.wrap_expr(_rbexpr.str_to_integer(base, dtype, strict))
|
|
1366
1629
|
end
|
|
1367
1630
|
|
|
1368
1631
|
# Use the aho-corasick algorithm to find matches.
|
|
@@ -1403,7 +1666,7 @@ module Polars
|
|
|
1403
1666
|
# # │ Can you feel the love tonight ┆ true │
|
|
1404
1667
|
# # └─────────────────────────────────┴──────────────┘
|
|
1405
1668
|
def contains_any(patterns, ascii_case_insensitive: false)
|
|
1406
|
-
patterns = Utils.parse_into_expression(patterns, str_as_lit: false
|
|
1669
|
+
patterns = Utils.parse_into_expression(patterns, str_as_lit: false)
|
|
1407
1670
|
Utils.wrap_expr(
|
|
1408
1671
|
_rbexpr.str_contains_any(patterns, ascii_case_insensitive)
|
|
1409
1672
|
)
|
|
@@ -1411,15 +1674,19 @@ module Polars
|
|
|
1411
1674
|
|
|
1412
1675
|
# Use the aho-corasick algorithm to replace many matches.
|
|
1413
1676
|
#
|
|
1414
|
-
# @param patterns [
|
|
1677
|
+
# @param patterns [Object]
|
|
1415
1678
|
# String patterns to search and replace.
|
|
1416
|
-
# @param replace_with [
|
|
1679
|
+
# @param replace_with [Object]
|
|
1417
1680
|
# Strings to replace where a pattern was a match.
|
|
1418
1681
|
# This can be broadcasted. So it supports many:one and many:many.
|
|
1419
1682
|
# @param ascii_case_insensitive [Boolean]
|
|
1420
1683
|
# Enable ASCII-aware case insensitive matching.
|
|
1421
1684
|
# When this option is enabled, searching will be performed without respect
|
|
1422
1685
|
# to case for ASCII letters (a-z and A-Z) only.
|
|
1686
|
+
# @param leftmost [Boolean]
|
|
1687
|
+
# Guarantees in case there are overlapping matches that the leftmost match
|
|
1688
|
+
# is used. In case there are multiple candidates for the leftmost match
|
|
1689
|
+
# the pattern which comes first in patterns is used.
|
|
1423
1690
|
#
|
|
1424
1691
|
# @return [Expr]
|
|
1425
1692
|
#
|
|
@@ -1437,7 +1704,7 @@ module Polars
|
|
|
1437
1704
|
# Polars.col("lyrics")
|
|
1438
1705
|
# .str.replace_many(
|
|
1439
1706
|
# ["me", "you", "they"],
|
|
1440
|
-
# ""
|
|
1707
|
+
# [""]
|
|
1441
1708
|
# )
|
|
1442
1709
|
# .alias("removes_pronouns")
|
|
1443
1710
|
# )
|
|
@@ -1473,22 +1740,209 @@ module Polars
|
|
|
1473
1740
|
# # │ Tell me what you want, what yo… ┆ Tell you what me want, what me… │
|
|
1474
1741
|
# # │ Can you feel the love tonight ┆ Can me feel the love tonight │
|
|
1475
1742
|
# # └─────────────────────────────────┴─────────────────────────────────┘
|
|
1476
|
-
def replace_many(
|
|
1477
|
-
patterns
|
|
1478
|
-
replace_with =
|
|
1479
|
-
|
|
1480
|
-
|
|
1743
|
+
def replace_many(
|
|
1744
|
+
patterns,
|
|
1745
|
+
replace_with = NO_DEFAULT,
|
|
1746
|
+
ascii_case_insensitive: false,
|
|
1747
|
+
leftmost: false
|
|
1748
|
+
)
|
|
1749
|
+
if replace_with == NO_DEFAULT
|
|
1750
|
+
if !patterns.is_a?(Hash)
|
|
1751
|
+
msg = "`replace_with` argument is required if `patterns` argument is not a Hash type"
|
|
1752
|
+
raise TypeError, msg
|
|
1753
|
+
end
|
|
1754
|
+
# Early return in case of an empty mapping.
|
|
1755
|
+
if patterns.empty?
|
|
1756
|
+
return Utils.wrap_expr(_rbexpr)
|
|
1757
|
+
end
|
|
1758
|
+
replace_with = patterns.values
|
|
1759
|
+
patterns = patterns.keys
|
|
1760
|
+
end
|
|
1761
|
+
|
|
1762
|
+
patterns = Utils.parse_into_expression(patterns, str_as_lit: false)
|
|
1763
|
+
replace_with = Utils.parse_into_expression(replace_with, str_as_lit: true)
|
|
1481
1764
|
Utils.wrap_expr(
|
|
1482
1765
|
_rbexpr.str_replace_many(
|
|
1483
|
-
patterns, replace_with, ascii_case_insensitive
|
|
1766
|
+
patterns, replace_with, ascii_case_insensitive, leftmost
|
|
1484
1767
|
)
|
|
1485
1768
|
)
|
|
1486
1769
|
end
|
|
1487
1770
|
|
|
1771
|
+
# Use the Aho-Corasick algorithm to extract many matches.
|
|
1772
|
+
#
|
|
1773
|
+
# @param patterns [Object]
|
|
1774
|
+
# String patterns to search.
|
|
1775
|
+
# @param ascii_case_insensitive [Boolean]
|
|
1776
|
+
# Enable ASCII-aware case-insensitive matching.
|
|
1777
|
+
# When this option is enabled, searching will be performed without respect
|
|
1778
|
+
# to case for ASCII letters (a-z and A-Z) only.
|
|
1779
|
+
# @param overlapping [Boolean]
|
|
1780
|
+
# Whether matches may overlap.
|
|
1781
|
+
# @param leftmost [Boolean]
|
|
1782
|
+
# Guarantees in case there are overlapping matches that the leftmost match
|
|
1783
|
+
# is used. In case there are multiple candidates for the leftmost match
|
|
1784
|
+
# the pattern which comes first in patterns is used. May not be used
|
|
1785
|
+
# together with overlapping: true.
|
|
1786
|
+
#
|
|
1787
|
+
# @return [Expr]
|
|
1788
|
+
#
|
|
1789
|
+
# @note
|
|
1790
|
+
# This method supports matching on string literals only, and does not support
|
|
1791
|
+
# regular expression matching.
|
|
1792
|
+
#
|
|
1793
|
+
# @example
|
|
1794
|
+
# df = Polars::DataFrame.new({"values" => ["discontent"]})
|
|
1795
|
+
# patterns = ["winter", "disco", "onte", "discontent"]
|
|
1796
|
+
# df.with_columns(
|
|
1797
|
+
# Polars.col("values")
|
|
1798
|
+
# .str.extract_many(patterns, overlapping: false)
|
|
1799
|
+
# .alias("matches"),
|
|
1800
|
+
# Polars.col("values")
|
|
1801
|
+
# .str.extract_many(patterns, overlapping: true)
|
|
1802
|
+
# .alias("matches_overlapping"),
|
|
1803
|
+
# )
|
|
1804
|
+
# # =>
|
|
1805
|
+
# # shape: (1, 3)
|
|
1806
|
+
# # ┌────────────┬───────────┬─────────────────────────────────┐
|
|
1807
|
+
# # │ values ┆ matches ┆ matches_overlapping │
|
|
1808
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1809
|
+
# # │ str ┆ list[str] ┆ list[str] │
|
|
1810
|
+
# # ╞════════════╪═══════════╪═════════════════════════════════╡
|
|
1811
|
+
# # │ discontent ┆ ["disco"] ┆ ["disco", "onte", "discontent"… │
|
|
1812
|
+
# # └────────────┴───────────┴─────────────────────────────────┘
|
|
1813
|
+
#
|
|
1814
|
+
# @example
|
|
1815
|
+
# df = Polars::DataFrame.new(
|
|
1816
|
+
# {
|
|
1817
|
+
# "values" => ["discontent", "rhapsody"],
|
|
1818
|
+
# "patterns" => [
|
|
1819
|
+
# ["winter", "disco", "onte", "discontent"],
|
|
1820
|
+
# ["rhap", "ody", "coalesce"]
|
|
1821
|
+
# ]
|
|
1822
|
+
# }
|
|
1823
|
+
# )
|
|
1824
|
+
# df.select(Polars.col("values").str.extract_many("patterns"))
|
|
1825
|
+
# # =>
|
|
1826
|
+
# # shape: (2, 1)
|
|
1827
|
+
# # ┌─────────────────┐
|
|
1828
|
+
# # │ values │
|
|
1829
|
+
# # │ --- │
|
|
1830
|
+
# # │ list[str] │
|
|
1831
|
+
# # ╞═════════════════╡
|
|
1832
|
+
# # │ ["disco"] │
|
|
1833
|
+
# # │ ["rhap", "ody"] │
|
|
1834
|
+
# # └─────────────────┘
|
|
1835
|
+
def extract_many(
|
|
1836
|
+
patterns,
|
|
1837
|
+
ascii_case_insensitive: false,
|
|
1838
|
+
overlapping: false,
|
|
1839
|
+
leftmost: false
|
|
1840
|
+
)
|
|
1841
|
+
if overlapping && leftmost
|
|
1842
|
+
msg = "can not match overlapping patterns when leftmost == true"
|
|
1843
|
+
raise ArgumentError, msg
|
|
1844
|
+
end
|
|
1845
|
+
patterns = Utils.parse_into_expression(patterns, str_as_lit: false)
|
|
1846
|
+
Utils.wrap_expr(
|
|
1847
|
+
_rbexpr.str_extract_many(patterns, ascii_case_insensitive, overlapping, leftmost)
|
|
1848
|
+
)
|
|
1849
|
+
end
|
|
1850
|
+
|
|
1851
|
+
# Use the Aho-Corasick algorithm to find many matches.
|
|
1852
|
+
#
|
|
1853
|
+
# The function will return the bytes offset of the start of each match.
|
|
1854
|
+
# The return type will be `List<UInt32>`
|
|
1855
|
+
#
|
|
1856
|
+
# @param patterns [Object]
|
|
1857
|
+
# String patterns to search.
|
|
1858
|
+
# @param ascii_case_insensitive [Boolean]
|
|
1859
|
+
# Enable ASCII-aware case-insensitive matching.
|
|
1860
|
+
# When this option is enabled, searching will be performed without respect
|
|
1861
|
+
# to case for ASCII letters (a-z and A-Z) only.
|
|
1862
|
+
# @param overlapping [Boolean]
|
|
1863
|
+
# Whether matches may overlap.
|
|
1864
|
+
# @param leftmost [Boolean]
|
|
1865
|
+
# Guarantees in case there are overlapping matches that the leftmost match
|
|
1866
|
+
# is used. In case there are multiple candidates for the leftmost match
|
|
1867
|
+
# the pattern which comes first in patterns is used. May not be used
|
|
1868
|
+
# together with overlapping: true.
|
|
1869
|
+
#
|
|
1870
|
+
# @return [Expr]
|
|
1871
|
+
#
|
|
1872
|
+
# @note
|
|
1873
|
+
# This method supports matching on string literals only, and does not support
|
|
1874
|
+
# regular expression matching.
|
|
1875
|
+
#
|
|
1876
|
+
# @example
|
|
1877
|
+
# df = Polars::DataFrame.new({"values" => ["discontent"]})
|
|
1878
|
+
# patterns = ["winter", "disco", "onte", "discontent"]
|
|
1879
|
+
# df.with_columns(
|
|
1880
|
+
# Polars.col("values")
|
|
1881
|
+
# .str.extract_many(patterns, overlapping: false)
|
|
1882
|
+
# .alias("matches"),
|
|
1883
|
+
# Polars.col("values")
|
|
1884
|
+
# .str.extract_many(patterns, overlapping: true)
|
|
1885
|
+
# .alias("matches_overlapping"),
|
|
1886
|
+
# )
|
|
1887
|
+
# # =>
|
|
1888
|
+
# # shape: (1, 3)
|
|
1889
|
+
# # ┌────────────┬───────────┬─────────────────────────────────┐
|
|
1890
|
+
# # │ values ┆ matches ┆ matches_overlapping │
|
|
1891
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1892
|
+
# # │ str ┆ list[str] ┆ list[str] │
|
|
1893
|
+
# # ╞════════════╪═══════════╪═════════════════════════════════╡
|
|
1894
|
+
# # │ discontent ┆ ["disco"] ┆ ["disco", "onte", "discontent"… │
|
|
1895
|
+
# # └────────────┴───────────┴─────────────────────────────────┘
|
|
1896
|
+
#
|
|
1897
|
+
# @example
|
|
1898
|
+
# df = Polars::DataFrame.new(
|
|
1899
|
+
# {
|
|
1900
|
+
# "values" => ["discontent", "rhapsody"],
|
|
1901
|
+
# "patterns" => [
|
|
1902
|
+
# ["winter", "disco", "onte", "discontent"],
|
|
1903
|
+
# ["rhap", "ody", "coalesce"]
|
|
1904
|
+
# ]
|
|
1905
|
+
# }
|
|
1906
|
+
# )
|
|
1907
|
+
# df.select(Polars.col("values").str.find_many("patterns"))
|
|
1908
|
+
# # =>
|
|
1909
|
+
# # shape: (2, 1)
|
|
1910
|
+
# # ┌───────────┐
|
|
1911
|
+
# # │ values │
|
|
1912
|
+
# # │ --- │
|
|
1913
|
+
# # │ list[u32] │
|
|
1914
|
+
# # ╞═══════════╡
|
|
1915
|
+
# # │ [0] │
|
|
1916
|
+
# # │ [0, 5] │
|
|
1917
|
+
# # └───────────┘
|
|
1918
|
+
def find_many(
|
|
1919
|
+
patterns,
|
|
1920
|
+
ascii_case_insensitive: false,
|
|
1921
|
+
overlapping: false,
|
|
1922
|
+
leftmost: false
|
|
1923
|
+
)
|
|
1924
|
+
if overlapping && leftmost
|
|
1925
|
+
msg = "can not match overlapping patterns when leftmost == true"
|
|
1926
|
+
raise ArgumentError, msg
|
|
1927
|
+
end
|
|
1928
|
+
patterns = Utils.parse_into_expression(patterns, str_as_lit: false)
|
|
1929
|
+
Utils.wrap_expr(
|
|
1930
|
+
_rbexpr.str_find_many(patterns, ascii_case_insensitive, overlapping, leftmost)
|
|
1931
|
+
)
|
|
1932
|
+
end
|
|
1933
|
+
|
|
1488
1934
|
private
|
|
1489
1935
|
|
|
1490
1936
|
def _validate_format_argument(format)
|
|
1491
|
-
|
|
1937
|
+
if !format.nil? && format.include?(".%f")
|
|
1938
|
+
message = (
|
|
1939
|
+
"Detected the pattern `.%f` in the chrono format string." +
|
|
1940
|
+
" This pattern should not be used to parse values after a decimal point." +
|
|
1941
|
+
" Use `%.f` instead." +
|
|
1942
|
+
" See the full specification: https://docs.rs/chrono/latest/chrono/format/strftime"
|
|
1943
|
+
)
|
|
1944
|
+
warn message
|
|
1945
|
+
end
|
|
1492
1946
|
end
|
|
1493
1947
|
end
|
|
1494
1948
|
end
|