polars-df 0.25.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 +33 -0
- data/Cargo.lock +270 -97
- data/LICENSE.txt +1 -1
- data/README.md +1 -3
- data/ext/polars/Cargo.toml +19 -18
- data/ext/polars/src/catalog/unity.rs +15 -20
- data/ext/polars/src/conversion/any_value.rs +53 -29
- data/ext/polars/src/conversion/chunked_array.rs +58 -56
- data/ext/polars/src/conversion/datetime.rs +58 -7
- data/ext/polars/src/conversion/mod.rs +200 -150
- data/ext/polars/src/dataframe/export.rs +15 -12
- data/ext/polars/src/dataframe/general.rs +25 -7
- data/ext/polars/src/dataframe/map.rs +6 -4
- data/ext/polars/src/error.rs +1 -1
- data/ext/polars/src/expr/array.rs +0 -24
- data/ext/polars/src/expr/datatype.rs +13 -3
- data/ext/polars/src/expr/datetime.rs +4 -4
- data/ext/polars/src/expr/general.rs +35 -15
- data/ext/polars/src/expr/list.rs +0 -26
- data/ext/polars/src/expr/rolling.rs +24 -0
- data/ext/polars/src/functions/business.rs +2 -2
- data/ext/polars/src/functions/io.rs +4 -3
- data/ext/polars/src/functions/lazy.rs +65 -46
- data/ext/polars/src/functions/meta.rs +6 -5
- data/ext/polars/src/functions/mod.rs +0 -1
- data/ext/polars/src/functions/range.rs +13 -0
- data/ext/polars/src/functions/utils.rs +4 -2
- data/ext/polars/src/interop/arrow/mod.rs +4 -2
- data/ext/polars/src/interop/arrow/to_rb.rs +1 -1
- data/ext/polars/src/interop/numo/to_numo_series.rs +26 -25
- data/ext/polars/src/io/scan_options.rs +6 -3
- data/ext/polars/src/io/sink_options.rs +2 -0
- data/ext/polars/src/lazyframe/general.rs +243 -17
- data/ext/polars/src/lazyframe/optflags.rs +2 -1
- data/ext/polars/src/lib.rs +39 -35
- data/ext/polars/src/map/lazy.rs +5 -2
- data/ext/polars/src/map/series.rs +19 -18
- data/ext/polars/src/on_startup.rs +25 -6
- data/ext/polars/src/ruby/numo.rs +3 -4
- data/ext/polars/src/ruby/plan_callback.rs +1 -4
- data/ext/polars/src/ruby/rb_modules.rs +2 -4
- data/ext/polars/src/ruby/ruby_udf.rs +7 -9
- data/ext/polars/src/ruby/utils.rs +12 -1
- data/ext/polars/src/series/aggregation.rs +13 -1
- data/ext/polars/src/series/construction.rs +31 -50
- data/ext/polars/src/series/export.rs +33 -38
- data/ext/polars/src/series/general.rs +6 -6
- data/ext/polars/src/series/map.rs +3 -2
- data/ext/polars/src/series/scatter.rs +4 -4
- data/ext/polars/src/utils.rs +31 -7
- data/lib/polars/array_expr.rb +23 -7
- data/lib/polars/array_name_space.rb +16 -2
- data/lib/polars/binary_name_space.rb +32 -0
- data/lib/polars/collect_batches.rb +4 -0
- data/lib/polars/data_frame.rb +144 -11
- data/lib/polars/data_type_group.rb +5 -0
- data/lib/polars/date_time_expr.rb +91 -3
- data/lib/polars/date_time_name_space.rb +7 -1
- data/lib/polars/expr.rb +247 -44
- data/lib/polars/functions/business.rb +2 -2
- data/lib/polars/functions/datatype.rb +30 -0
- data/lib/polars/functions/eager.rb +80 -7
- data/lib/polars/functions/lazy.rb +97 -2
- data/lib/polars/functions/range/linear_space.rb +118 -0
- data/lib/polars/io/csv.rb +27 -5
- data/lib/polars/io/database.rb +2 -3
- data/lib/polars/io/ipc.rb +2 -2
- data/lib/polars/io/lines.rb +172 -0
- data/lib/polars/io/parquet.rb +1 -1
- data/lib/polars/io/sink_options.rb +5 -2
- data/lib/polars/lazy_frame.rb +517 -14
- data/lib/polars/list_expr.rb +21 -7
- data/lib/polars/list_name_space.rb +16 -2
- data/lib/polars/query_opt_flags.rb +23 -5
- data/lib/polars/selectors.rb +2 -2
- data/lib/polars/series.rb +176 -19
- data/lib/polars/sql_context.rb +2 -2
- data/lib/polars/string_cache.rb +19 -72
- data/lib/polars/string_expr.rb +1 -7
- data/lib/polars/string_name_space.rb +1 -7
- data/lib/polars/utils/construction/series.rb +24 -39
- data/lib/polars/utils/convert.rb +16 -6
- data/lib/polars/utils/parse.rb +7 -0
- data/lib/polars/utils/reduce_balanced.rb +43 -0
- data/lib/polars/utils/various.rb +5 -0
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +2 -1
- metadata +4 -17
- data/ext/polars/src/functions/string_cache.rs +0 -24
data/lib/polars/expr.rb
CHANGED
|
@@ -252,6 +252,38 @@ module Polars
|
|
|
252
252
|
wrap_expr(_rbexpr.all(ignore_nulls))
|
|
253
253
|
end
|
|
254
254
|
|
|
255
|
+
# Return whether the column is empty.
|
|
256
|
+
#
|
|
257
|
+
# @note
|
|
258
|
+
# This functionality is considered **unstable**. It may be changed
|
|
259
|
+
# at any point without it being considered a breaking change.
|
|
260
|
+
#
|
|
261
|
+
# @param ignore_nulls [Boolean]
|
|
262
|
+
# If true a column containing only nulls will also be considered empty.
|
|
263
|
+
# The default is false.
|
|
264
|
+
#
|
|
265
|
+
# @return [Expr]
|
|
266
|
+
#
|
|
267
|
+
# @example
|
|
268
|
+
# df = Polars::DataFrame.new({"x" => [nil, nil]})
|
|
269
|
+
# df.select(
|
|
270
|
+
# a: Polars.col("x").is_empty,
|
|
271
|
+
# b: Polars.col("x").drop_nulls.is_empty,
|
|
272
|
+
# c: Polars.col("x").is_empty(ignore_nulls: true)
|
|
273
|
+
# )
|
|
274
|
+
# # =>
|
|
275
|
+
# # shape: (1, 3)
|
|
276
|
+
# # ┌───────┬──────┬──────┐
|
|
277
|
+
# # │ a ┆ b ┆ c │
|
|
278
|
+
# # │ --- ┆ --- ┆ --- │
|
|
279
|
+
# # │ bool ┆ bool ┆ bool │
|
|
280
|
+
# # ╞═══════╪══════╪══════╡
|
|
281
|
+
# # │ false ┆ true ┆ true │
|
|
282
|
+
# # └───────┴──────┴──────┘
|
|
283
|
+
def is_empty(ignore_nulls: false)
|
|
284
|
+
wrap_expr(_rbexpr.is_empty(ignore_nulls))
|
|
285
|
+
end
|
|
286
|
+
|
|
255
287
|
# Return indices where expression evaluates `true`.
|
|
256
288
|
#
|
|
257
289
|
# @return [Expr]
|
|
@@ -1204,6 +1236,49 @@ module Polars
|
|
|
1204
1236
|
wrap_expr(_rbexpr.round_sig_figs(digits))
|
|
1205
1237
|
end
|
|
1206
1238
|
|
|
1239
|
+
# Truncate numeric data toward zero to `decimals` number of decimal places.
|
|
1240
|
+
#
|
|
1241
|
+
# @param decimals [Integer]
|
|
1242
|
+
# Number of decimal places to truncate to.
|
|
1243
|
+
#
|
|
1244
|
+
# @return [Expr]
|
|
1245
|
+
#
|
|
1246
|
+
# @note
|
|
1247
|
+
# Truncation discards the fractional part beyond the given number of decimals.
|
|
1248
|
+
# For example, when rounding to 0 decimals 0.25, -0.25, 0.99, and -0.99 will
|
|
1249
|
+
# all round to 0. When rounding to 1 decimal 1.9999 rounds to 1.9 and -1.9999
|
|
1250
|
+
# rounds to -1.9. There is no tiebreak behaviour at midpoint values as there
|
|
1251
|
+
# is with :meth:`round` so 0.5 and -0.5 will also round to 0 when decimals=1.
|
|
1252
|
+
#
|
|
1253
|
+
# @note
|
|
1254
|
+
# This method performs numeric truncation. For truncating temporal
|
|
1255
|
+
# data (dates/datetimes), use :func:`Expr.dt.truncate` instead.
|
|
1256
|
+
#
|
|
1257
|
+
# @example
|
|
1258
|
+
# df = Polars::DataFrame.new({"n" => [-9.9999, 0.12345, 1.0251, 8.8765]})
|
|
1259
|
+
# df.with_columns(
|
|
1260
|
+
# t0: Polars.col("n").truncate(0),
|
|
1261
|
+
# t1: Polars.col("n").truncate(1),
|
|
1262
|
+
# t2: Polars.col("n").truncate(2),
|
|
1263
|
+
# t3: Polars.col("n").truncate(3),
|
|
1264
|
+
# t4: Polars.col("n").truncate(4)
|
|
1265
|
+
# )
|
|
1266
|
+
# # =>
|
|
1267
|
+
# # shape: (4, 6)
|
|
1268
|
+
# # ┌─────────┬──────┬──────┬───────┬────────┬─────────┐
|
|
1269
|
+
# # │ n ┆ t0 ┆ t1 ┆ t2 ┆ t3 ┆ t4 │
|
|
1270
|
+
# # │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
1271
|
+
# # │ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
|
|
1272
|
+
# # ╞═════════╪══════╪══════╪═══════╪════════╪═════════╡
|
|
1273
|
+
# # │ -9.9999 ┆ -9.0 ┆ -9.9 ┆ -9.99 ┆ -9.999 ┆ -9.9999 │
|
|
1274
|
+
# # │ 0.12345 ┆ 0.0 ┆ 0.1 ┆ 0.12 ┆ 0.123 ┆ 0.1234 │
|
|
1275
|
+
# # │ 1.0251 ┆ 1.0 ┆ 1.0 ┆ 1.02 ┆ 1.025 ┆ 1.025 │
|
|
1276
|
+
# # │ 8.8765 ┆ 8.0 ┆ 8.8 ┆ 8.87 ┆ 8.876 ┆ 8.8765 │
|
|
1277
|
+
# # └─────────┴──────┴──────┴───────┴────────┴─────────┘
|
|
1278
|
+
def truncate(decimals = 0)
|
|
1279
|
+
Utils.wrap_expr(_rbexpr.truncate(decimals))
|
|
1280
|
+
end
|
|
1281
|
+
|
|
1207
1282
|
# Compute the dot/inner product between two Expressions.
|
|
1208
1283
|
#
|
|
1209
1284
|
# @param other [Expr]
|
|
@@ -1887,6 +1962,11 @@ module Polars
|
|
|
1887
1962
|
#
|
|
1888
1963
|
# @param indices [Expr]
|
|
1889
1964
|
# An expression that leads to a `:u32` dtyped Series.
|
|
1965
|
+
# @param null_on_oob [Boolean]
|
|
1966
|
+
# Behavior if an index is out of bounds:
|
|
1967
|
+
#
|
|
1968
|
+
# - true -> set the result to null
|
|
1969
|
+
# - false -> raise an error
|
|
1890
1970
|
#
|
|
1891
1971
|
# @return [Expr]
|
|
1892
1972
|
#
|
|
@@ -1915,13 +1995,13 @@ module Polars
|
|
|
1915
1995
|
# # │ one ┆ [2, 98] │
|
|
1916
1996
|
# # │ two ┆ [4, 99] │
|
|
1917
1997
|
# # └───────┴───────────┘
|
|
1918
|
-
def gather(indices)
|
|
1998
|
+
def gather(indices, null_on_oob: false)
|
|
1919
1999
|
if indices.is_a?(::Array)
|
|
1920
2000
|
indices_lit_rbexpr = Polars.lit(Series.new("", indices, dtype: Int64))._rbexpr
|
|
1921
2001
|
else
|
|
1922
2002
|
indices_lit_rbexpr = Utils.parse_into_expression(indices)
|
|
1923
2003
|
end
|
|
1924
|
-
wrap_expr(_rbexpr.gather(indices_lit_rbexpr))
|
|
2004
|
+
wrap_expr(_rbexpr.gather(indices_lit_rbexpr, null_on_oob))
|
|
1925
2005
|
end
|
|
1926
2006
|
|
|
1927
2007
|
# Return a single value by index.
|
|
@@ -2266,6 +2346,38 @@ module Polars
|
|
|
2266
2346
|
wrap_expr(_rbexpr.max)
|
|
2267
2347
|
end
|
|
2268
2348
|
|
|
2349
|
+
# Get maximum value, ordered by another expression.
|
|
2350
|
+
#
|
|
2351
|
+
# If the by expression has multiple values equal to the maximum it is not
|
|
2352
|
+
# defined which value will be chosen.
|
|
2353
|
+
#
|
|
2354
|
+
# @note
|
|
2355
|
+
# This functionality is considered **unstable**. It may be changed
|
|
2356
|
+
# at any point without it being considered a breaking change.
|
|
2357
|
+
#
|
|
2358
|
+
# @param by [Object]
|
|
2359
|
+
# Column used to determine the largest element.
|
|
2360
|
+
# Accepts expression input. Strings are parsed as column names.
|
|
2361
|
+
#
|
|
2362
|
+
# @return [Expr]
|
|
2363
|
+
#
|
|
2364
|
+
# @example
|
|
2365
|
+
# df = Polars::DataFrame.new({"a" => [-1.0, Float::NAN, 1.0], "b" => ["x", "y", "z"]})
|
|
2366
|
+
# df.select(Polars.col("b").max_by("a"))
|
|
2367
|
+
# # =>
|
|
2368
|
+
# # shape: (1, 1)
|
|
2369
|
+
# # ┌─────┐
|
|
2370
|
+
# # │ b │
|
|
2371
|
+
# # │ --- │
|
|
2372
|
+
# # │ str │
|
|
2373
|
+
# # ╞═════╡
|
|
2374
|
+
# # │ z │
|
|
2375
|
+
# # └─────┘
|
|
2376
|
+
def max_by(by)
|
|
2377
|
+
by_rbexpr = Utils.parse_into_expression(by)
|
|
2378
|
+
wrap_expr(_rbexpr.max_by(by_rbexpr))
|
|
2379
|
+
end
|
|
2380
|
+
|
|
2269
2381
|
# Get minimum value.
|
|
2270
2382
|
#
|
|
2271
2383
|
# @return [Expr]
|
|
@@ -2286,6 +2398,38 @@ module Polars
|
|
|
2286
2398
|
wrap_expr(_rbexpr.min)
|
|
2287
2399
|
end
|
|
2288
2400
|
|
|
2401
|
+
# Get minimum value, ordered by another expression.
|
|
2402
|
+
#
|
|
2403
|
+
# If the by expression has multiple values equal to the minimum it is not
|
|
2404
|
+
# defined which value will be chosen.
|
|
2405
|
+
#
|
|
2406
|
+
# @note
|
|
2407
|
+
# This functionality is considered **unstable**. It may be changed
|
|
2408
|
+
# at any point without it being considered a breaking change.
|
|
2409
|
+
#
|
|
2410
|
+
# @param by [Object]
|
|
2411
|
+
# Column used to determine the smallest element.
|
|
2412
|
+
# Accepts expression input. Strings are parsed as column names.
|
|
2413
|
+
#
|
|
2414
|
+
# @return [Expr]
|
|
2415
|
+
#
|
|
2416
|
+
# @example
|
|
2417
|
+
# df = Polars::DataFrame.new({"a" => [-1.0, Float::NAN, 1.0], "b" => ["x", "y", "z"]})
|
|
2418
|
+
# df.select(Polars.col("b").min_by("a"))
|
|
2419
|
+
# # =>
|
|
2420
|
+
# # shape: (1, 1)
|
|
2421
|
+
# # ┌─────┐
|
|
2422
|
+
# # │ b │
|
|
2423
|
+
# # │ --- │
|
|
2424
|
+
# # │ str │
|
|
2425
|
+
# # ╞═════╡
|
|
2426
|
+
# # │ x │
|
|
2427
|
+
# # └─────┘
|
|
2428
|
+
def min_by(by)
|
|
2429
|
+
by_rbexpr = Utils.parse_into_expression(by)
|
|
2430
|
+
wrap_expr(_rbexpr.min_by(by_rbexpr))
|
|
2431
|
+
end
|
|
2432
|
+
|
|
2289
2433
|
# Get maximum value, but propagate/poison encountered NaN values.
|
|
2290
2434
|
#
|
|
2291
2435
|
# @return [Expr]
|
|
@@ -3131,17 +3275,17 @@ module Polars
|
|
|
3131
3275
|
# )
|
|
3132
3276
|
# # =>
|
|
3133
3277
|
# # shape: (5, 2)
|
|
3134
|
-
# #
|
|
3135
|
-
# # │ foo ┆ cut
|
|
3136
|
-
# # │ --- ┆ ---
|
|
3137
|
-
# # │ i64 ┆
|
|
3138
|
-
# #
|
|
3139
|
-
# # │ -2 ┆ a
|
|
3140
|
-
# # │ -1 ┆ a
|
|
3141
|
-
# # │ 0 ┆ b
|
|
3142
|
-
# # │ 1 ┆ b
|
|
3143
|
-
# # │ 2 ┆ c
|
|
3144
|
-
# #
|
|
3278
|
+
# # ┌─────┬──────┐
|
|
3279
|
+
# # │ foo ┆ cut │
|
|
3280
|
+
# # │ --- ┆ --- │
|
|
3281
|
+
# # │ i64 ┆ enum │
|
|
3282
|
+
# # ╞═════╪══════╡
|
|
3283
|
+
# # │ -2 ┆ a │
|
|
3284
|
+
# # │ -1 ┆ a │
|
|
3285
|
+
# # │ 0 ┆ b │
|
|
3286
|
+
# # │ 1 ┆ b │
|
|
3287
|
+
# # │ 2 ┆ c │
|
|
3288
|
+
# # └─────┴──────┘
|
|
3145
3289
|
#
|
|
3146
3290
|
# @example Add both the category and the breakpoint.
|
|
3147
3291
|
# df.with_columns(
|
|
@@ -3152,7 +3296,7 @@ module Polars
|
|
|
3152
3296
|
# # ┌─────┬────────────┬────────────┐
|
|
3153
3297
|
# # │ foo ┆ breakpoint ┆ category │
|
|
3154
3298
|
# # │ --- ┆ --- ┆ --- │
|
|
3155
|
-
# # │ i64 ┆ f64 ┆
|
|
3299
|
+
# # │ i64 ┆ f64 ┆ enum │
|
|
3156
3300
|
# # ╞═════╪════════════╪════════════╡
|
|
3157
3301
|
# # │ -2 ┆ -1.0 ┆ (-inf, -1] │
|
|
3158
3302
|
# # │ -1 ┆ -1.0 ┆ (-inf, -1] │
|
|
@@ -4502,13 +4646,18 @@ module Polars
|
|
|
4502
4646
|
wrap_expr(_rbexpr._hash(k0, k1, k2, k3))
|
|
4503
4647
|
end
|
|
4504
4648
|
|
|
4505
|
-
# Reinterpret the underlying bits as a signed/unsigned integer.
|
|
4649
|
+
# Reinterpret the underlying bits as a signed/unsigned integer or float.
|
|
4650
|
+
#
|
|
4651
|
+
# This operation is only allowed for numeric types of the same size.
|
|
4652
|
+
# For lower bits numbers, you can safely use the cast operation.
|
|
4506
4653
|
#
|
|
4507
|
-
#
|
|
4508
|
-
# you can safely use that cast operation.
|
|
4654
|
+
# Either `signed` or `dtype` can be specified.
|
|
4509
4655
|
#
|
|
4510
4656
|
# @param signed [Boolean]
|
|
4511
|
-
# If true, reinterpret as
|
|
4657
|
+
# If true, reinterpret as signed integer. Otherwise, reinterpret
|
|
4658
|
+
# as unsigned integer.
|
|
4659
|
+
# @param dtype [Object]
|
|
4660
|
+
# DataType to reinterpret to.
|
|
4512
4661
|
#
|
|
4513
4662
|
# @return [Expr]
|
|
4514
4663
|
#
|
|
@@ -4517,7 +4666,7 @@ module Polars
|
|
|
4517
4666
|
# df = Polars::DataFrame.new([s])
|
|
4518
4667
|
# df.select(
|
|
4519
4668
|
# [
|
|
4520
|
-
# Polars.col("a").reinterpret(
|
|
4669
|
+
# Polars.col("a").reinterpret(dtype: Polars::Int64).alias("reinterpreted"),
|
|
4521
4670
|
# Polars.col("a").alias("original")
|
|
4522
4671
|
# ]
|
|
4523
4672
|
# )
|
|
@@ -4532,14 +4681,13 @@ module Polars
|
|
|
4532
4681
|
# # │ 1 ┆ 1 │
|
|
4533
4682
|
# # │ 2 ┆ 2 │
|
|
4534
4683
|
# # └───────────────┴──────────┘
|
|
4535
|
-
def reinterpret(signed: nil)
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
signed = false
|
|
4684
|
+
def reinterpret(signed: nil, dtype: nil)
|
|
4685
|
+
if signed.nil? == dtype.nil?
|
|
4686
|
+
msg = "reinterpret requires exactly one of `signed` or `dtype` to be specified"
|
|
4687
|
+
raise ArgumentError, msg
|
|
4540
4688
|
end
|
|
4541
4689
|
|
|
4542
|
-
wrap_expr(_rbexpr.reinterpret(signed))
|
|
4690
|
+
wrap_expr(_rbexpr.reinterpret(signed, dtype))
|
|
4543
4691
|
end
|
|
4544
4692
|
|
|
4545
4693
|
# Print the value that this expression evaluates to and pass on the value.
|
|
@@ -5111,7 +5259,7 @@ module Polars
|
|
|
5111
5259
|
def rolling_sum_by(
|
|
5112
5260
|
by,
|
|
5113
5261
|
window_size,
|
|
5114
|
-
min_samples:
|
|
5262
|
+
min_samples: 0,
|
|
5115
5263
|
closed: "right"
|
|
5116
5264
|
)
|
|
5117
5265
|
window_size = _prepare_rolling_by_window_args(window_size)
|
|
@@ -6486,6 +6634,67 @@ module Polars
|
|
|
6486
6634
|
)
|
|
6487
6635
|
end
|
|
6488
6636
|
|
|
6637
|
+
# Compute a custom rolling window function.
|
|
6638
|
+
#
|
|
6639
|
+
# @note
|
|
6640
|
+
# This functionality is considered **unstable**. It may be changed
|
|
6641
|
+
# at any point without it being considered a breaking change.
|
|
6642
|
+
#
|
|
6643
|
+
# @param window_size [Integer]
|
|
6644
|
+
# The length of the window in number of elements.
|
|
6645
|
+
# @param weights [Object]
|
|
6646
|
+
# An optional slice with the same length as the window that will be multiplied
|
|
6647
|
+
# elementwise with the values in the window.
|
|
6648
|
+
# @param min_samples [Integer]
|
|
6649
|
+
# The number of values in the window that should be non-null before computing
|
|
6650
|
+
# a result. If set to `nil` (default), it will be set equal to `window_size`.
|
|
6651
|
+
# @param center [Boolean]
|
|
6652
|
+
# Set the labels at the center of the window.
|
|
6653
|
+
#
|
|
6654
|
+
# @return [Expr]
|
|
6655
|
+
#
|
|
6656
|
+
# @example
|
|
6657
|
+
# df = Polars::DataFrame.new({"a" => [11.0, 2.0, 9.0, Float::NAN, 8.0]})
|
|
6658
|
+
# df.select(Polars.col("a").rolling_map(3) { |v| v.drop_nans.sum })
|
|
6659
|
+
# # =>
|
|
6660
|
+
# # shape: (5, 1)
|
|
6661
|
+
# # ┌──────┐
|
|
6662
|
+
# # │ a │
|
|
6663
|
+
# # │ --- │
|
|
6664
|
+
# # │ f64 │
|
|
6665
|
+
# # ╞══════╡
|
|
6666
|
+
# # │ null │
|
|
6667
|
+
# # │ null │
|
|
6668
|
+
# # │ 22.0 │
|
|
6669
|
+
# # │ 11.0 │
|
|
6670
|
+
# # │ 17.0 │
|
|
6671
|
+
# # └──────┘
|
|
6672
|
+
def rolling_map(
|
|
6673
|
+
window_size,
|
|
6674
|
+
weights: nil,
|
|
6675
|
+
min_samples: nil,
|
|
6676
|
+
center: false,
|
|
6677
|
+
&function
|
|
6678
|
+
)
|
|
6679
|
+
if min_samples.nil?
|
|
6680
|
+
min_samples = window_size
|
|
6681
|
+
end
|
|
6682
|
+
|
|
6683
|
+
_wrap = lambda do |rbs|
|
|
6684
|
+
s = Utils.wrap_s(rbs)
|
|
6685
|
+
rv = function.(s)
|
|
6686
|
+
if rv.is_a?(Series)
|
|
6687
|
+
rv._s
|
|
6688
|
+
else
|
|
6689
|
+
Series.new([rv])._s
|
|
6690
|
+
end
|
|
6691
|
+
end
|
|
6692
|
+
|
|
6693
|
+
wrap_expr(
|
|
6694
|
+
_rbexpr.rolling_map(_wrap, window_size, weights, min_samples, center)
|
|
6695
|
+
)
|
|
6696
|
+
end
|
|
6697
|
+
|
|
6489
6698
|
# Compute absolute values.
|
|
6490
6699
|
#
|
|
6491
6700
|
# @return [Expr]
|
|
@@ -7237,17 +7446,11 @@ module Polars
|
|
|
7237
7446
|
# # └─────┘
|
|
7238
7447
|
def sample(
|
|
7239
7448
|
fraction: nil,
|
|
7240
|
-
with_replacement:
|
|
7449
|
+
with_replacement: false,
|
|
7241
7450
|
shuffle: false,
|
|
7242
7451
|
seed: nil,
|
|
7243
7452
|
n: nil
|
|
7244
7453
|
)
|
|
7245
|
-
# TODO update
|
|
7246
|
-
if with_replacement.nil?
|
|
7247
|
-
warn "The default `with_replacement` for `sample` method will change from `true` to `false` in a future version"
|
|
7248
|
-
with_replacement = true
|
|
7249
|
-
end
|
|
7250
|
-
|
|
7251
7454
|
if !n.nil? && !fraction.nil?
|
|
7252
7455
|
raise ArgumentError, "cannot specify both `n` and `fraction`"
|
|
7253
7456
|
end
|
|
@@ -7636,13 +7839,7 @@ module Polars
|
|
|
7636
7839
|
# # ╞═══════════╡
|
|
7637
7840
|
# # │ -6.754888 │
|
|
7638
7841
|
# # └───────────┘
|
|
7639
|
-
def entropy(base:
|
|
7640
|
-
# TODO update (including param docs)
|
|
7641
|
-
if base.nil?
|
|
7642
|
-
warn "The default `base` for `entropy` method will change from `2` to `Math::E` in a future version"
|
|
7643
|
-
base = 2
|
|
7644
|
-
end
|
|
7645
|
-
|
|
7842
|
+
def entropy(base: Math::E, normalize: true)
|
|
7646
7843
|
wrap_expr(_rbexpr.entropy(base, normalize))
|
|
7647
7844
|
end
|
|
7648
7845
|
|
|
@@ -7698,6 +7895,8 @@ module Polars
|
|
|
7698
7895
|
#
|
|
7699
7896
|
# @param descending [Boolean]
|
|
7700
7897
|
# Whether the `Series` order is descending.
|
|
7898
|
+
# @param nulls_last [Boolean]
|
|
7899
|
+
# Whether the nulls are at the end.
|
|
7701
7900
|
#
|
|
7702
7901
|
# @return [Expr]
|
|
7703
7902
|
#
|
|
@@ -7717,12 +7916,16 @@ module Polars
|
|
|
7717
7916
|
# # ╞════════╡
|
|
7718
7917
|
# # │ 3 │
|
|
7719
7918
|
# # └────────┘
|
|
7720
|
-
def set_sorted(descending: false)
|
|
7721
|
-
wrap_expr(_rbexpr.set_sorted_flag(descending))
|
|
7919
|
+
def set_sorted(descending: false, nulls_last: false)
|
|
7920
|
+
wrap_expr(_rbexpr.set_sorted_flag(descending, nulls_last))
|
|
7722
7921
|
end
|
|
7723
7922
|
|
|
7724
7923
|
# Aggregate to list.
|
|
7725
7924
|
#
|
|
7925
|
+
# @param maintain_order [Boolean]
|
|
7926
|
+
# Whether to preserve the order of elements in the list. Setting this
|
|
7927
|
+
# to `false` can improve performance, especially within `group_by`.
|
|
7928
|
+
#
|
|
7726
7929
|
# @return [Expr]
|
|
7727
7930
|
#
|
|
7728
7931
|
# @example
|
|
@@ -7742,8 +7945,8 @@ module Polars
|
|
|
7742
7945
|
# # ╞═══════════╪═══════════╡
|
|
7743
7946
|
# # │ [1, 2, 3] ┆ [4, 5, 6] │
|
|
7744
7947
|
# # └───────────┴───────────┘
|
|
7745
|
-
def implode
|
|
7746
|
-
wrap_expr(_rbexpr.implode)
|
|
7948
|
+
def implode(maintain_order: true)
|
|
7949
|
+
wrap_expr(_rbexpr.implode(maintain_order))
|
|
7747
7950
|
end
|
|
7748
7951
|
|
|
7749
7952
|
# Bin values into buckets and count their occurrences.
|
|
@@ -81,13 +81,13 @@ module Polars
|
|
|
81
81
|
)
|
|
82
82
|
start_rbexpr = Utils.parse_into_expression(start)
|
|
83
83
|
end_rbexpr = Utils.parse_into_expression(stop)
|
|
84
|
-
|
|
84
|
+
holidays_rbexpr = Utils._holidays_to_expr(holidays)
|
|
85
85
|
Utils.wrap_expr(
|
|
86
86
|
Plr.business_day_count(
|
|
87
87
|
start_rbexpr,
|
|
88
88
|
end_rbexpr,
|
|
89
89
|
week_mask,
|
|
90
|
-
|
|
90
|
+
holidays_rbexpr
|
|
91
91
|
)
|
|
92
92
|
)
|
|
93
93
|
end
|
|
@@ -28,5 +28,35 @@ module Polars
|
|
|
28
28
|
def self_dtype
|
|
29
29
|
DataTypeExpr._from_rbdatatype_expr(RbDataTypeExpr.self_dtype)
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
# Create a new datatype expression that represents a Struct datatype.
|
|
33
|
+
#
|
|
34
|
+
# @note
|
|
35
|
+
# This functionality is considered **unstable**. It may be changed
|
|
36
|
+
# at any point without it being considered a breaking change.
|
|
37
|
+
#
|
|
38
|
+
# @return [DataTypeExpr]
|
|
39
|
+
def struct_with_fields(
|
|
40
|
+
mapping
|
|
41
|
+
)
|
|
42
|
+
preprocess = lambda do |dtype_expr|
|
|
43
|
+
if dtype_expr.is_a?(DataType)
|
|
44
|
+
dtype_expr.to_dtype_expr._rbdatatype_expr
|
|
45
|
+
elsif dtype_expr < DataType
|
|
46
|
+
dtype_expr.to_dtype_expr._rbdatatype_expr
|
|
47
|
+
elsif dtype_expr.is_a?(DataTypeExpr)
|
|
48
|
+
dtype_expr._rbdatatype_expr
|
|
49
|
+
else
|
|
50
|
+
msg = "mapping item must be a datatype or datatype expression; found #{dtype_expr.inspect}"
|
|
51
|
+
raise TypeError, msg
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
fields = mapping.map { |name, dtype_expr| [name.to_s, preprocess.(dtype_expr)] }
|
|
56
|
+
|
|
57
|
+
DataTypeExpr._from_rbdatatype_expr(
|
|
58
|
+
RbDataTypeExpr.struct_with_fields(fields)
|
|
59
|
+
)
|
|
60
|
+
end
|
|
31
61
|
end
|
|
32
62
|
end
|
|
@@ -399,6 +399,85 @@ module Polars
|
|
|
399
399
|
out
|
|
400
400
|
end
|
|
401
401
|
|
|
402
|
+
# Merge multiple sorted DataFrames or LazyFrames by the sorted key.
|
|
403
|
+
#
|
|
404
|
+
# The output of this operation will also be sorted.
|
|
405
|
+
# It is the callers responsibility that the frames
|
|
406
|
+
# are sorted in ascending order by that key otherwise
|
|
407
|
+
# the output will not make sense.
|
|
408
|
+
#
|
|
409
|
+
# @note
|
|
410
|
+
# This functionality is considered **unstable**. It may be changed
|
|
411
|
+
# at any point without it being considered a breaking change.
|
|
412
|
+
#
|
|
413
|
+
# @param items [Array]
|
|
414
|
+
# DataFrames or LazyFrames to merge.
|
|
415
|
+
# @param key [String]
|
|
416
|
+
# Key that is sorted.
|
|
417
|
+
# @param maintain_order [Boolean]
|
|
418
|
+
# If `true`, the output is guaranteed to have left-biased ordering
|
|
419
|
+
# for equal keys: rows from the left frame appear before rows from
|
|
420
|
+
# the right frame when their keys are equal.
|
|
421
|
+
#
|
|
422
|
+
# @return [Object]
|
|
423
|
+
#
|
|
424
|
+
# @example
|
|
425
|
+
# df0 = Polars::DataFrame.new(
|
|
426
|
+
# {"name" => ["steve", "elise", "bob"], "age" => [42, 44, 18]}
|
|
427
|
+
# ).sort("age")
|
|
428
|
+
# df1 = Polars::DataFrame.new(
|
|
429
|
+
# {"name" => ["anna", "megan", "steve", "thomas"], "age" => [21, 33, 17, 20]}
|
|
430
|
+
# ).sort("age")
|
|
431
|
+
# df2 = Polars::DataFrame.new({"name" => ["ida", "maya"], "age" => [37, 27]}).sort("age")
|
|
432
|
+
# Polars.merge_sorted([df0, df1, df2], "age")
|
|
433
|
+
# # =>
|
|
434
|
+
# # shape: (9, 2)
|
|
435
|
+
# # ┌────────┬─────┐
|
|
436
|
+
# # │ name ┆ age │
|
|
437
|
+
# # │ --- ┆ --- │
|
|
438
|
+
# # │ str ┆ i64 │
|
|
439
|
+
# # ╞════════╪═════╡
|
|
440
|
+
# # │ steve ┆ 17 │
|
|
441
|
+
# # │ bob ┆ 18 │
|
|
442
|
+
# # │ thomas ┆ 20 │
|
|
443
|
+
# # │ anna ┆ 21 │
|
|
444
|
+
# # │ maya ┆ 27 │
|
|
445
|
+
# # │ megan ┆ 33 │
|
|
446
|
+
# # │ ida ┆ 37 │
|
|
447
|
+
# # │ steve ┆ 42 │
|
|
448
|
+
# # │ elise ┆ 44 │
|
|
449
|
+
# # └────────┴─────┘
|
|
450
|
+
def merge_sorted(
|
|
451
|
+
items,
|
|
452
|
+
key,
|
|
453
|
+
maintain_order: false
|
|
454
|
+
)
|
|
455
|
+
elems = items.to_a
|
|
456
|
+
|
|
457
|
+
if elems.empty?
|
|
458
|
+
msg = "cannot merge_sort empty list"
|
|
459
|
+
raise ArgumentError, msg
|
|
460
|
+
end
|
|
461
|
+
if elems.length == 1 && (elems[0].is_a?(DataFrame) || elems[0].is_a?(LazyFrame))
|
|
462
|
+
return elems[0]
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
if !Utils.is_non_empty_sequence_of(elems, DataFrame) && !Utils.is_non_empty_sequence_of(elems, LazyFrame)
|
|
466
|
+
msg = "merge_sorted is not supported for #{elems[0].inspect}"
|
|
467
|
+
raise TypeError, msg
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
frames = elems.map { |df| df.lazy }
|
|
471
|
+
|
|
472
|
+
reduce_fn = lambda do |x, y|
|
|
473
|
+
x.merge_sorted(y, key, maintain_order: maintain_order)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
lf = Utils.reduce_balanced(reduce_fn, frames)
|
|
477
|
+
eager = elems[0].is_a?(DataFrame)
|
|
478
|
+
eager ? lf.collect : lf
|
|
479
|
+
end
|
|
480
|
+
|
|
402
481
|
# Align an array of frames using the unique values from one or more columns as a key.
|
|
403
482
|
#
|
|
404
483
|
# Frames that do not contain the given key values have rows injected (with nulls
|
|
@@ -464,16 +543,10 @@ module Polars
|
|
|
464
543
|
def align_frames(
|
|
465
544
|
*frames,
|
|
466
545
|
on:,
|
|
467
|
-
how:
|
|
546
|
+
how: "full",
|
|
468
547
|
select: nil,
|
|
469
548
|
descending: false
|
|
470
549
|
)
|
|
471
|
-
# TODO update
|
|
472
|
-
if how.nil?
|
|
473
|
-
warn "The default `how` for `align_frames` method will change from `left` to `full` in a future version"
|
|
474
|
-
how = "left"
|
|
475
|
-
end
|
|
476
|
-
|
|
477
550
|
if frames.empty?
|
|
478
551
|
return []
|
|
479
552
|
elsif frames.map(&:class).uniq.length != 1
|