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
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
module Polars
|
|
2
2
|
module Functions
|
|
3
|
+
# Select a field in the current `struct.with_fields` scope.
|
|
4
|
+
#
|
|
5
|
+
# @param name [Object]
|
|
6
|
+
# Name of the field(s) to select.
|
|
7
|
+
#
|
|
8
|
+
# @return [Expr]
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# df = Polars::DataFrame.new({"a" => [{"x" => 5, "y" => 2}, {"x" => 3, "y" => 4}]})
|
|
12
|
+
# df.select(Polars.col("a").struct.with_fields(Polars.field("x") ** 2))
|
|
13
|
+
# # =>
|
|
14
|
+
# # shape: (2, 1)
|
|
15
|
+
# # ┌───────────┐
|
|
16
|
+
# # │ a │
|
|
17
|
+
# # │ --- │
|
|
18
|
+
# # │ struct[2] │
|
|
19
|
+
# # ╞═══════════╡
|
|
20
|
+
# # │ {25,2} │
|
|
21
|
+
# # │ {9,4} │
|
|
22
|
+
# # └───────────┘
|
|
23
|
+
def field(name)
|
|
24
|
+
if name.is_a?(::String)
|
|
25
|
+
name = [name]
|
|
26
|
+
end
|
|
27
|
+
Utils.wrap_expr(Plr.field(name))
|
|
28
|
+
end
|
|
29
|
+
|
|
3
30
|
# Alias for an element in evaluated in an `eval` expression.
|
|
4
31
|
#
|
|
5
32
|
# @return [Expr]
|
|
6
33
|
#
|
|
7
34
|
# @example A horizontal rank computation by taking the elements of a list
|
|
8
35
|
# df = Polars::DataFrame.new({"a" => [1, 8, 3], "b" => [4, 5, 2]})
|
|
9
|
-
# df.
|
|
36
|
+
# df.with_columns(
|
|
10
37
|
# Polars.concat_list(["a", "b"]).list.eval(Polars.element.rank).alias("rank")
|
|
11
38
|
# )
|
|
12
39
|
# # =>
|
|
@@ -21,7 +48,7 @@ module Polars
|
|
|
21
48
|
# # │ 3 ┆ 2 ┆ [2.0, 1.0] │
|
|
22
49
|
# # └─────┴─────┴────────────┘
|
|
23
50
|
def element
|
|
24
|
-
|
|
51
|
+
Utils.wrap_expr(Plr.element)
|
|
25
52
|
end
|
|
26
53
|
|
|
27
54
|
# Return the number of non-null values in the column.
|
|
@@ -70,7 +97,7 @@ module Polars
|
|
|
70
97
|
def count(*columns)
|
|
71
98
|
if columns.empty?
|
|
72
99
|
warn "`Polars.count` is deprecated. Use `Polars.length` instead."
|
|
73
|
-
return Utils.wrap_expr(Plr.len.
|
|
100
|
+
return Utils.wrap_expr(Plr.len.alias("count"))
|
|
74
101
|
end
|
|
75
102
|
|
|
76
103
|
col(*columns).count
|
|
@@ -114,6 +141,9 @@ module Polars
|
|
|
114
141
|
#
|
|
115
142
|
# @param columns [Array]
|
|
116
143
|
# One or more column names.
|
|
144
|
+
# @param maintain_order [Boolean]
|
|
145
|
+
# Whether to preserve the order of elements in the list. Setting this
|
|
146
|
+
# to `false` can improve performance, especially within `group_by`.
|
|
117
147
|
#
|
|
118
148
|
# @return [Expr]
|
|
119
149
|
#
|
|
@@ -147,8 +177,8 @@ module Polars
|
|
|
147
177
|
# # ╞═══════════╪═══════════════════════╡
|
|
148
178
|
# # │ [9, 8, 7] ┆ ["foo", "bar", "foo"] │
|
|
149
179
|
# # └───────────┴───────────────────────┘
|
|
150
|
-
def implode(*columns)
|
|
151
|
-
col(*columns).implode
|
|
180
|
+
def implode(*columns, maintain_order: true)
|
|
181
|
+
col(*columns).implode(maintain_order: maintain_order)
|
|
152
182
|
end
|
|
153
183
|
|
|
154
184
|
# Get the standard deviation.
|
|
@@ -272,7 +302,6 @@ module Polars
|
|
|
272
302
|
def mean(*columns)
|
|
273
303
|
col(*columns).mean
|
|
274
304
|
end
|
|
275
|
-
alias_method :avg, :mean
|
|
276
305
|
|
|
277
306
|
# Get the median value.
|
|
278
307
|
#
|
|
@@ -458,7 +487,7 @@ module Polars
|
|
|
458
487
|
# # └─────┴─────┘
|
|
459
488
|
def first(*columns)
|
|
460
489
|
if columns.empty?
|
|
461
|
-
return
|
|
490
|
+
return cs.first.as_expr
|
|
462
491
|
end
|
|
463
492
|
|
|
464
493
|
col(*columns).first
|
|
@@ -518,7 +547,7 @@ module Polars
|
|
|
518
547
|
# # └─────┴─────┘
|
|
519
548
|
def last(*columns)
|
|
520
549
|
if columns.empty?
|
|
521
|
-
return
|
|
550
|
+
return cs.last.as_expr
|
|
522
551
|
end
|
|
523
552
|
|
|
524
553
|
col(*columns).last
|
|
@@ -565,12 +594,8 @@ module Polars
|
|
|
565
594
|
# # │ bar ┆ 8 │
|
|
566
595
|
# # │ baz ┆ 3 │
|
|
567
596
|
# # └─────┴─────┘
|
|
568
|
-
def nth(*indices)
|
|
569
|
-
|
|
570
|
-
indices = indices[0]
|
|
571
|
-
end
|
|
572
|
-
|
|
573
|
-
Utils.wrap_expr(Plr.index_cols(indices))
|
|
597
|
+
def nth(*indices, strict: true)
|
|
598
|
+
cs.by_index(*indices, require_all: strict).as_expr
|
|
574
599
|
end
|
|
575
600
|
|
|
576
601
|
# Get the first `n` rows.
|
|
@@ -675,16 +700,20 @@ module Polars
|
|
|
675
700
|
# Column name or Expression.
|
|
676
701
|
# @param b [Object]
|
|
677
702
|
# Column name or Expression.
|
|
703
|
+
# @param method ["pearson", "spearman"]
|
|
704
|
+
# Correlation method.
|
|
678
705
|
# @param ddof [Integer]
|
|
679
706
|
# "Delta Degrees of Freedom": the divisor used in the calculation is N - ddof,
|
|
680
707
|
# where N represents the number of elements.
|
|
681
708
|
# By default ddof is 1.
|
|
682
|
-
# @param method ["pearson", "spearman"]
|
|
683
|
-
# Correlation method.
|
|
684
709
|
# @param propagate_nans [Boolean]
|
|
685
710
|
# If `true` any `NaN` encountered will lead to `NaN` in the output.
|
|
686
|
-
# Defaults to `
|
|
711
|
+
# Defaults to `false` where `NaN` are regarded as larger than any finite number
|
|
687
712
|
# and thus lead to the highest rank.
|
|
713
|
+
# @param eager [Boolean]
|
|
714
|
+
# Evaluate immediately and return a `Series`; this requires that at least one
|
|
715
|
+
# of the given arguments is a `Series`. If set to `false` (default), return
|
|
716
|
+
# an expression instead.
|
|
688
717
|
#
|
|
689
718
|
# @return [Expr]
|
|
690
719
|
#
|
|
@@ -725,23 +754,63 @@ module Polars
|
|
|
725
754
|
# # ╞═════╡
|
|
726
755
|
# # │ 0.5 │
|
|
727
756
|
# # └─────┘
|
|
757
|
+
#
|
|
758
|
+
# @example Eager evaluation:
|
|
759
|
+
# s1 = Polars::Series.new("a", [1, 8, 3])
|
|
760
|
+
# s2 = Polars::Series.new("b", [4, 5, 2])
|
|
761
|
+
# Polars.corr(s1, s2, eager: true)
|
|
762
|
+
# # =>
|
|
763
|
+
# # shape: (1,)
|
|
764
|
+
# # Series: 'a' [f64]
|
|
765
|
+
# # [
|
|
766
|
+
# # 0.544705
|
|
767
|
+
# # ]
|
|
768
|
+
#
|
|
769
|
+
# @example
|
|
770
|
+
# Polars.corr(s1, s2, method: "spearman", eager: true)
|
|
771
|
+
# # =>
|
|
772
|
+
# # shape: (1,)
|
|
773
|
+
# # Series: 'a' [f64]
|
|
774
|
+
# # [
|
|
775
|
+
# # 0.5
|
|
776
|
+
# # ]
|
|
728
777
|
def corr(
|
|
729
778
|
a,
|
|
730
779
|
b,
|
|
731
780
|
method: "pearson",
|
|
732
|
-
ddof:
|
|
733
|
-
propagate_nans: false
|
|
781
|
+
ddof: nil,
|
|
782
|
+
propagate_nans: false,
|
|
783
|
+
eager: false
|
|
734
784
|
)
|
|
735
|
-
|
|
736
|
-
|
|
785
|
+
if !ddof.nil?
|
|
786
|
+
Utils.issue_deprecation_warning(
|
|
787
|
+
"The `ddof` parameter has no effect. Do not use it."
|
|
788
|
+
)
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
if eager
|
|
792
|
+
if !(a.is_a?(Series) || b.is_a?(Series))
|
|
793
|
+
msg = "expected at least one Series in 'corr' inputs if 'eager: true'"
|
|
794
|
+
raise ArgumentError, msg
|
|
795
|
+
end
|
|
737
796
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
797
|
+
frame = Polars::DataFrame.new([a, b].filter_map { |e| e if e.is_a?(Series) })
|
|
798
|
+
exprs = [a, b].map { |e| e.is_a?(Series) ? e.name : e }
|
|
799
|
+
frame.select(
|
|
800
|
+
corr(*exprs, eager: false, method: method, propagate_nans: propagate_nans)
|
|
801
|
+
).to_series
|
|
742
802
|
else
|
|
743
|
-
|
|
744
|
-
|
|
803
|
+
a = Utils.parse_into_expression(a)
|
|
804
|
+
b = Utils.parse_into_expression(b)
|
|
805
|
+
|
|
806
|
+
if method == "pearson"
|
|
807
|
+
Utils.wrap_expr(Plr.pearson_corr(a, b))
|
|
808
|
+
elsif method == "spearman"
|
|
809
|
+
Utils.wrap_expr(Plr.spearman_rank_corr(a, b, propagate_nans))
|
|
810
|
+
else
|
|
811
|
+
msg = "method must be one of {{'pearson', 'spearman'}}, got #{method}"
|
|
812
|
+
raise ArgumentError, msg
|
|
813
|
+
end
|
|
745
814
|
end
|
|
746
815
|
end
|
|
747
816
|
|
|
@@ -755,6 +824,10 @@ module Polars
|
|
|
755
824
|
# "Delta Degrees of Freedom": the divisor used in the calculation is N - ddof,
|
|
756
825
|
# where N represents the number of elements.
|
|
757
826
|
# By default ddof is 1.
|
|
827
|
+
# @param eager [Boolean]
|
|
828
|
+
# Evaluate immediately and return a `Series`; this requires that at least one
|
|
829
|
+
# of the given arguments is a `Series`. If set to `false` (default), return
|
|
830
|
+
# an expression instead.
|
|
758
831
|
#
|
|
759
832
|
# @return [Expr]
|
|
760
833
|
#
|
|
@@ -776,33 +849,324 @@ module Polars
|
|
|
776
849
|
# # ╞═════╡
|
|
777
850
|
# # │ 3.0 │
|
|
778
851
|
# # └─────┘
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
852
|
+
#
|
|
853
|
+
# @example Eager evaluation:
|
|
854
|
+
# s1 = Polars::Series.new("a", [1, 8, 3])
|
|
855
|
+
# s2 = Polars::Series.new("b", [4, 5, 2])
|
|
856
|
+
# Polars.cov(s1, s2, eager: true)
|
|
857
|
+
# # =>
|
|
858
|
+
# # shape: (1,)
|
|
859
|
+
# # Series: 'a' [f64]
|
|
860
|
+
# # [
|
|
861
|
+
# # 3.0
|
|
862
|
+
# # ]
|
|
863
|
+
def cov(a, b, ddof: 1, eager: false)
|
|
864
|
+
if eager
|
|
865
|
+
if !(a.is_a?(Series) || b.is_a?(Series))
|
|
866
|
+
msg = "expected at least one Series in 'cov' inputs if 'eager: true'"
|
|
867
|
+
raise ArgumentError, msg
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
frame = Polars::DataFrame.new([a, b].filter_map { |e| e if e.is_a?(Series) })
|
|
871
|
+
exprs = [a, b].map { |e| e.is_a?(Series) ? e.name : e }
|
|
872
|
+
frame.select(cov(*exprs, eager: false, ddof: ddof)).to_series
|
|
873
|
+
else
|
|
874
|
+
a_rbexpr = Utils.parse_into_expression(a)
|
|
875
|
+
b_rbexpr = Utils.parse_into_expression(b)
|
|
876
|
+
Utils.wrap_expr(Plr.cov(a_rbexpr, b_rbexpr, ddof))
|
|
877
|
+
end
|
|
783
878
|
end
|
|
784
879
|
|
|
785
|
-
#
|
|
786
|
-
#
|
|
880
|
+
# Map a custom function over multiple columns/expressions.
|
|
881
|
+
#
|
|
882
|
+
# Produces a single Series result.
|
|
883
|
+
#
|
|
884
|
+
# @note
|
|
885
|
+
# This method is much slower than the native expressions API.
|
|
886
|
+
# Only use it if you cannot implement your logic otherwise.
|
|
887
|
+
#
|
|
888
|
+
# @param exprs [Array]
|
|
889
|
+
# Expression(s) representing the input Series to the function.
|
|
890
|
+
# @param return_dtype [Object]
|
|
891
|
+
# Datatype of the output Series.
|
|
892
|
+
#
|
|
893
|
+
# It is recommended to set this whenever possible. If this is `nil`, it tries
|
|
894
|
+
# to infer the datatype by calling the function with dummy data and looking at
|
|
895
|
+
# the output.
|
|
896
|
+
# @param is_elementwise [Boolean]
|
|
897
|
+
# Set to true if the operations is elementwise for better performance
|
|
898
|
+
# and optimization.
|
|
899
|
+
#
|
|
900
|
+
# An elementwise operations has unit or equal length for all inputs
|
|
901
|
+
# and can be ran sequentially on slices without results being affected.
|
|
902
|
+
# @param returns_scalar [Boolean]
|
|
903
|
+
# If the function returns a scalar, by default it will be wrapped in
|
|
904
|
+
# a list in the output, since the assumption is that the function
|
|
905
|
+
# always returns something Series-like. If you want to keep the
|
|
906
|
+
# result as a scalar, set this argument to True.
|
|
907
|
+
#
|
|
908
|
+
# @return [Expr]
|
|
909
|
+
#
|
|
910
|
+
# @note
|
|
911
|
+
# A UDF passed to `map_batches` must be pure, meaning that it cannot modify
|
|
912
|
+
# or depend on state other than its arguments. We may call the function
|
|
913
|
+
# with arbitrary input data.
|
|
914
|
+
#
|
|
915
|
+
# @example
|
|
916
|
+
# test_func = lambda do |a, b, c|
|
|
917
|
+
# a + b + c
|
|
918
|
+
# end
|
|
919
|
+
# df = Polars::DataFrame.new(
|
|
920
|
+
# {
|
|
921
|
+
# "a" => [1, 2, 3, 4],
|
|
922
|
+
# "b" => [4, 5, 6, 7]
|
|
923
|
+
# }
|
|
924
|
+
# )
|
|
925
|
+
#
|
|
926
|
+
# df.with_columns(
|
|
927
|
+
# (
|
|
928
|
+
# Polars.struct(["a", "b"]).map_batches { |x| test_func.(x.struct.field("a"), x.struct.field("b"), 1) }
|
|
929
|
+
# ).alias("a+b+c")
|
|
930
|
+
# )
|
|
931
|
+
# # =>
|
|
932
|
+
# # shape: (4, 3)
|
|
933
|
+
# # ┌─────┬─────┬───────┐
|
|
934
|
+
# # │ a ┆ b ┆ a+b+c │
|
|
935
|
+
# # │ --- ┆ --- ┆ --- │
|
|
936
|
+
# # │ i64 ┆ i64 ┆ i64 │
|
|
937
|
+
# # ╞═════╪═════╪═══════╡
|
|
938
|
+
# # │ 1 ┆ 4 ┆ 6 │
|
|
939
|
+
# # │ 2 ┆ 5 ┆ 8 │
|
|
940
|
+
# # │ 3 ┆ 6 ┆ 10 │
|
|
941
|
+
# # │ 4 ┆ 7 ┆ 12 │
|
|
942
|
+
# # └─────┴─────┴───────┘
|
|
943
|
+
def map_batches(
|
|
944
|
+
exprs,
|
|
945
|
+
return_dtype: nil,
|
|
946
|
+
is_elementwise: false,
|
|
947
|
+
returns_scalar: false,
|
|
948
|
+
&function
|
|
949
|
+
)
|
|
950
|
+
rbexprs = Utils.parse_into_list_of_expressions(exprs)
|
|
951
|
+
|
|
952
|
+
return_dtype_expr =
|
|
953
|
+
if !return_dtype.nil?
|
|
954
|
+
Utils.parse_into_datatype_expr(return_dtype)._rbdatatype_expr
|
|
955
|
+
else
|
|
956
|
+
nil
|
|
957
|
+
end
|
|
787
958
|
|
|
788
|
-
|
|
789
|
-
|
|
959
|
+
Utils.wrap_expr(
|
|
960
|
+
Plr.map_expr(
|
|
961
|
+
rbexprs,
|
|
962
|
+
_map_batches_wrapper(function, returns_scalar: returns_scalar),
|
|
963
|
+
return_dtype_expr,
|
|
964
|
+
is_elementwise,
|
|
965
|
+
returns_scalar
|
|
966
|
+
)
|
|
967
|
+
)
|
|
968
|
+
end
|
|
969
|
+
|
|
970
|
+
# Apply a custom/user-defined function (UDF) in a GroupBy context.
|
|
971
|
+
#
|
|
972
|
+
# @note
|
|
973
|
+
# This method is much slower than the native expressions API.
|
|
974
|
+
# Only use it if you cannot implement your logic otherwise.
|
|
975
|
+
#
|
|
976
|
+
# @param exprs [Object]
|
|
977
|
+
# Expression(s) representing the input Series to the function.
|
|
978
|
+
# @param return_dtype [Object]
|
|
979
|
+
# Datatype of the output Series.
|
|
980
|
+
#
|
|
981
|
+
# It is recommended to set this whenever possible. If this is `nil`, it tries
|
|
982
|
+
# to infer the datatype by calling the function with dummy data and looking at
|
|
983
|
+
# the output.
|
|
984
|
+
# @param is_elementwise [Boolean]
|
|
985
|
+
# Set to true if the operations is elementwise for better performance
|
|
986
|
+
# and optimization.
|
|
987
|
+
#
|
|
988
|
+
# An elementwise operations has unit or equal length for all inputs
|
|
989
|
+
# and can be ran sequentially on slices without results being affected.
|
|
990
|
+
# @param returns_scalar [Boolean]
|
|
991
|
+
# If the function returns a single scalar as output.
|
|
992
|
+
#
|
|
993
|
+
# @return [Expr]
|
|
994
|
+
#
|
|
995
|
+
# @example
|
|
996
|
+
# df = Polars::DataFrame.new(
|
|
997
|
+
# {
|
|
998
|
+
# "group" => [1, 1, 2],
|
|
999
|
+
# "a" => [1, 3, 3],
|
|
1000
|
+
# "b" => [5, 6, 7]
|
|
1001
|
+
# }
|
|
1002
|
+
# )
|
|
1003
|
+
# (
|
|
1004
|
+
# df.group_by("group").agg(
|
|
1005
|
+
# Polars.map_groups(["a", "b"], return_dtype: Polars::Float64) { |list_of_series| list_of_series[0] / list_of_series[0].sum + list_of_series[1] }
|
|
1006
|
+
# .alias("my_custom_aggregation")
|
|
1007
|
+
# )
|
|
1008
|
+
# ).sort("group")
|
|
1009
|
+
# # =>
|
|
1010
|
+
# # shape: (2, 2)
|
|
1011
|
+
# # ┌───────┬───────────────────────┐
|
|
1012
|
+
# # │ group ┆ my_custom_aggregation │
|
|
1013
|
+
# # │ --- ┆ --- │
|
|
1014
|
+
# # │ i64 ┆ list[f64] │
|
|
1015
|
+
# # ╞═══════╪═══════════════════════╡
|
|
1016
|
+
# # │ 1 ┆ [5.25, 6.75] │
|
|
1017
|
+
# # │ 2 ┆ [8.0] │
|
|
1018
|
+
# # └───────┴───────────────────────┘
|
|
1019
|
+
def map_groups(
|
|
1020
|
+
exprs,
|
|
1021
|
+
return_dtype: nil,
|
|
1022
|
+
is_elementwise: false,
|
|
1023
|
+
returns_scalar: false,
|
|
1024
|
+
&function
|
|
1025
|
+
)
|
|
1026
|
+
map_batches(
|
|
1027
|
+
exprs,
|
|
1028
|
+
return_dtype: return_dtype,
|
|
1029
|
+
is_elementwise: is_elementwise,
|
|
1030
|
+
returns_scalar: returns_scalar,
|
|
1031
|
+
&function
|
|
1032
|
+
)
|
|
1033
|
+
end
|
|
790
1034
|
|
|
791
1035
|
# Accumulate over multiple columns horizontally/row wise with a left fold.
|
|
792
1036
|
#
|
|
793
1037
|
# @return [Expr]
|
|
794
|
-
|
|
1038
|
+
#
|
|
1039
|
+
# @example Horizontally sum over all columns and add 1.
|
|
1040
|
+
# df = Polars::DataFrame.new(
|
|
1041
|
+
# {
|
|
1042
|
+
# "a" => [1, 2, 3],
|
|
1043
|
+
# "b" => [3, 4, 5],
|
|
1044
|
+
# "c" => [5, 6, 7]
|
|
1045
|
+
# }
|
|
1046
|
+
# )
|
|
1047
|
+
# df.select(
|
|
1048
|
+
# Polars.fold(Polars.lit(1), Polars.col("*")) { |acc, x| acc + x }.alias("sum")
|
|
1049
|
+
# )
|
|
1050
|
+
# # =>
|
|
1051
|
+
# # shape: (3, 1)
|
|
1052
|
+
# # ┌─────┐
|
|
1053
|
+
# # │ sum │
|
|
1054
|
+
# # │ --- │
|
|
1055
|
+
# # │ i32 │
|
|
1056
|
+
# # ╞═════╡
|
|
1057
|
+
# # │ 10 │
|
|
1058
|
+
# # │ 13 │
|
|
1059
|
+
# # │ 16 │
|
|
1060
|
+
# # └─────┘
|
|
1061
|
+
#
|
|
1062
|
+
# @example You can also apply a condition/predicate on all columns:
|
|
1063
|
+
# df = Polars::DataFrame.new(
|
|
1064
|
+
# {
|
|
1065
|
+
# "a" => [1, 2, 3],
|
|
1066
|
+
# "b" => [0, 1, 2]
|
|
1067
|
+
# }
|
|
1068
|
+
# )
|
|
1069
|
+
# df.filter(
|
|
1070
|
+
# Polars.fold(Polars.lit(true), Polars.col("*") > 1) { |acc, x| acc & x }
|
|
1071
|
+
# )
|
|
1072
|
+
# # =>
|
|
1073
|
+
# # shape: (1, 2)
|
|
1074
|
+
# # ┌─────┬─────┐
|
|
1075
|
+
# # │ a ┆ b │
|
|
1076
|
+
# # │ --- ┆ --- │
|
|
1077
|
+
# # │ i64 ┆ i64 │
|
|
1078
|
+
# # ╞═════╪═════╡
|
|
1079
|
+
# # │ 3 ┆ 2 │
|
|
1080
|
+
# # └─────┴─────┘
|
|
1081
|
+
def fold(
|
|
1082
|
+
acc,
|
|
1083
|
+
exprs,
|
|
1084
|
+
returns_scalar: false,
|
|
1085
|
+
return_dtype: nil,
|
|
1086
|
+
&function
|
|
1087
|
+
)
|
|
795
1088
|
acc = Utils.parse_into_expression(acc, str_as_lit: true)
|
|
796
1089
|
if exprs.is_a?(Expr)
|
|
797
1090
|
exprs = [exprs]
|
|
798
1091
|
end
|
|
799
1092
|
|
|
1093
|
+
rt = nil
|
|
1094
|
+
if !return_dtype.nil?
|
|
1095
|
+
rt = Utils.parse_into_datatype_expr(return_dtype)._rbdatatype_expr
|
|
1096
|
+
end
|
|
1097
|
+
|
|
800
1098
|
exprs = Utils.parse_into_list_of_expressions(exprs)
|
|
801
|
-
Utils.wrap_expr(
|
|
1099
|
+
Utils.wrap_expr(
|
|
1100
|
+
Plr.fold(
|
|
1101
|
+
acc,
|
|
1102
|
+
_wrap_acc_lambda(function),
|
|
1103
|
+
exprs,
|
|
1104
|
+
returns_scalar,
|
|
1105
|
+
rt
|
|
1106
|
+
)
|
|
1107
|
+
)
|
|
802
1108
|
end
|
|
803
1109
|
|
|
804
|
-
#
|
|
805
|
-
#
|
|
1110
|
+
# Accumulate over multiple columns horizontally/ row wise with a left fold.
|
|
1111
|
+
#
|
|
1112
|
+
# @param exprs [Object]
|
|
1113
|
+
# Expressions to aggregate over. May also be a wildcard expression.
|
|
1114
|
+
# @param returns_scalar [Boolean]
|
|
1115
|
+
# Whether or not `function` applied returns a scalar. This must be set correctly
|
|
1116
|
+
# by the user.
|
|
1117
|
+
# @param return_dtype [Object]
|
|
1118
|
+
# Output datatype.
|
|
1119
|
+
# If not set, the dtype will be inferred based on the dtype of the input
|
|
1120
|
+
# expressions.
|
|
1121
|
+
#
|
|
1122
|
+
# @return [Expr]
|
|
1123
|
+
#
|
|
1124
|
+
# @example Horizontally sum over all columns.
|
|
1125
|
+
# df = Polars::DataFrame.new(
|
|
1126
|
+
# {
|
|
1127
|
+
# "a" => [1, 2, 3],
|
|
1128
|
+
# "b" => [0, 1, 2]
|
|
1129
|
+
# }
|
|
1130
|
+
# )
|
|
1131
|
+
# df.select(
|
|
1132
|
+
# Polars.reduce(Polars.col("*")) { |acc, x| acc + x }.alias("sum")
|
|
1133
|
+
# )
|
|
1134
|
+
# # =>
|
|
1135
|
+
# # shape: (3, 1)
|
|
1136
|
+
# # ┌─────┐
|
|
1137
|
+
# # │ sum │
|
|
1138
|
+
# # │ --- │
|
|
1139
|
+
# # │ i64 │
|
|
1140
|
+
# # ╞═════╡
|
|
1141
|
+
# # │ 1 │
|
|
1142
|
+
# # │ 3 │
|
|
1143
|
+
# # │ 5 │
|
|
1144
|
+
# # └─────┘
|
|
1145
|
+
def reduce(
|
|
1146
|
+
exprs,
|
|
1147
|
+
returns_scalar: false,
|
|
1148
|
+
return_dtype: nil,
|
|
1149
|
+
&function
|
|
1150
|
+
)
|
|
1151
|
+
if exprs.is_a?(Expr)
|
|
1152
|
+
exprs = [exprs]
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1155
|
+
rt = nil
|
|
1156
|
+
if !return_dtype.nil?
|
|
1157
|
+
rt = Utils.parse_into_datatype_expr(return_dtype)._rbdatatype_expr
|
|
1158
|
+
end
|
|
1159
|
+
|
|
1160
|
+
rbexprs = Utils.parse_into_list_of_expressions(exprs)
|
|
1161
|
+
Utils.wrap_expr(
|
|
1162
|
+
Plr.reduce(
|
|
1163
|
+
_wrap_acc_lambda(function),
|
|
1164
|
+
rbexprs,
|
|
1165
|
+
returns_scalar,
|
|
1166
|
+
rt
|
|
1167
|
+
)
|
|
1168
|
+
)
|
|
1169
|
+
end
|
|
806
1170
|
|
|
807
1171
|
# Cumulatively accumulate over multiple columns horizontally/row wise with a left fold.
|
|
808
1172
|
#
|
|
@@ -811,11 +1175,14 @@ module Polars
|
|
|
811
1175
|
# @param acc [Object]
|
|
812
1176
|
# Accumulator Expression. This is the value that will be initialized when the fold
|
|
813
1177
|
# starts. For a sum this could for instance be lit(0).
|
|
814
|
-
# @param f [Object]
|
|
815
|
-
# Function to apply over the accumulator and the value.
|
|
816
|
-
# Fn(acc, value) -> new_value
|
|
817
1178
|
# @param exprs [Object]
|
|
818
1179
|
# Expressions to aggregate over. May also be a wildcard expression.
|
|
1180
|
+
# @param returns_scalar [Boolean]
|
|
1181
|
+
# Whether or not `function` applied returns a scalar. This must be set correctly
|
|
1182
|
+
# by the user.
|
|
1183
|
+
# @param return_dtype [Object]
|
|
1184
|
+
# Output datatype.
|
|
1185
|
+
# If not set, the dtype will be inferred based on the dtype of the accumulator.
|
|
819
1186
|
# @param include_init [Boolean]
|
|
820
1187
|
# Include the initial accumulator state as struct field.
|
|
821
1188
|
#
|
|
@@ -823,7 +1190,7 @@ module Polars
|
|
|
823
1190
|
#
|
|
824
1191
|
# @note
|
|
825
1192
|
# If you simply want the first encountered expression as accumulator,
|
|
826
|
-
# consider using `
|
|
1193
|
+
# consider using `cum_reduce`.
|
|
827
1194
|
#
|
|
828
1195
|
# @example
|
|
829
1196
|
# df = Polars::DataFrame.new(
|
|
@@ -834,7 +1201,7 @@ module Polars
|
|
|
834
1201
|
# }
|
|
835
1202
|
# )
|
|
836
1203
|
# df.with_columns(
|
|
837
|
-
# Polars.cum_fold(Polars.lit(1),
|
|
1204
|
+
# Polars.cum_fold(Polars.lit(1), Polars.all) { |acc, x| acc + x }
|
|
838
1205
|
# )
|
|
839
1206
|
# # =>
|
|
840
1207
|
# # shape: (3, 4)
|
|
@@ -847,69 +1214,103 @@ module Polars
|
|
|
847
1214
|
# # │ 2 ┆ 4 ┆ 6 ┆ {3,7,13} │
|
|
848
1215
|
# # │ 3 ┆ 5 ┆ 7 ┆ {4,9,16} │
|
|
849
1216
|
# # └─────┴─────┴─────┴───────────┘
|
|
850
|
-
def cum_fold(
|
|
1217
|
+
def cum_fold(
|
|
1218
|
+
acc,
|
|
1219
|
+
exprs,
|
|
1220
|
+
returns_scalar: false,
|
|
1221
|
+
return_dtype: nil,
|
|
1222
|
+
include_init: false,
|
|
1223
|
+
&function
|
|
1224
|
+
)
|
|
851
1225
|
acc = Utils.parse_into_expression(acc, str_as_lit: true)
|
|
852
1226
|
if exprs.is_a?(Expr)
|
|
853
1227
|
exprs = [exprs]
|
|
854
1228
|
end
|
|
855
1229
|
|
|
1230
|
+
rt = nil
|
|
1231
|
+
if !return_dtype.nil?
|
|
1232
|
+
rt = Utils.parse_into_datatype_expr(return_dtype)._rbdatatype_expr
|
|
1233
|
+
end
|
|
1234
|
+
|
|
856
1235
|
exprs = Utils.parse_into_list_of_expressions(exprs)
|
|
857
|
-
Utils.wrap_expr(
|
|
1236
|
+
Utils.wrap_expr(
|
|
1237
|
+
Plr.cum_fold(
|
|
1238
|
+
acc,
|
|
1239
|
+
_wrap_acc_lambda(function),
|
|
1240
|
+
exprs,
|
|
1241
|
+
returns_scalar,
|
|
1242
|
+
rt,
|
|
1243
|
+
include_init
|
|
1244
|
+
).alias("cum_fold")
|
|
1245
|
+
)
|
|
858
1246
|
end
|
|
859
|
-
alias_method :cumfold, :cum_fold
|
|
860
1247
|
|
|
861
|
-
#
|
|
862
|
-
# end
|
|
863
|
-
|
|
864
|
-
# Compute two argument arctan in radians.
|
|
1248
|
+
# Cumulatively reduce horizontally across columns with a left fold.
|
|
865
1249
|
#
|
|
866
|
-
#
|
|
867
|
-
# positive x-axis and the ray from the origin to (x,y).
|
|
1250
|
+
# Every cumulative result is added as a separate field in a Struct column.
|
|
868
1251
|
#
|
|
869
|
-
# @param
|
|
870
|
-
#
|
|
871
|
-
# @param
|
|
872
|
-
#
|
|
1252
|
+
# @param exprs [Object]
|
|
1253
|
+
# Expressions to aggregate over. May also be a wildcard expression.
|
|
1254
|
+
# @param returns_scalar [Boolean]
|
|
1255
|
+
# Whether or not `function` applied returns a scalar. This must be set correctly
|
|
1256
|
+
# by the user.
|
|
1257
|
+
# @param return_dtype [Object]
|
|
1258
|
+
# Output datatype.
|
|
1259
|
+
# If not set, the dtype will be inferred based on the dtype of the input
|
|
1260
|
+
# expressions.
|
|
873
1261
|
#
|
|
874
1262
|
# @return [Expr]
|
|
875
1263
|
#
|
|
876
1264
|
# @example
|
|
877
|
-
# twoRootTwo = Math.sqrt(2) / 2
|
|
878
1265
|
# df = Polars::DataFrame.new(
|
|
879
1266
|
# {
|
|
880
|
-
# "
|
|
881
|
-
# "
|
|
1267
|
+
# "a" => [1, 2, 3],
|
|
1268
|
+
# "b" => [3, 4, 5],
|
|
1269
|
+
# "c" => [5, 6, 7]
|
|
882
1270
|
# }
|
|
883
1271
|
# )
|
|
884
|
-
# df.
|
|
885
|
-
# Polars.arctan2d("y", "x").alias("atan2d"), Polars.arctan2("y", "x").alias("atan2")
|
|
886
|
-
# )
|
|
1272
|
+
# df.with_columns(Polars.cum_reduce(Polars.all) { |acc, x| acc + x })
|
|
887
1273
|
# # =>
|
|
888
|
-
# # shape: (
|
|
889
|
-
# #
|
|
890
|
-
# # │
|
|
891
|
-
# # │ ---
|
|
892
|
-
# # │
|
|
893
|
-
# #
|
|
894
|
-
# # │
|
|
895
|
-
# # │
|
|
896
|
-
# # │
|
|
897
|
-
# #
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1274
|
+
# # shape: (3, 4)
|
|
1275
|
+
# # ┌─────┬─────┬─────┬────────────┐
|
|
1276
|
+
# # │ a ┆ b ┆ c ┆ cum_reduce │
|
|
1277
|
+
# # │ --- ┆ --- ┆ --- ┆ --- │
|
|
1278
|
+
# # │ i64 ┆ i64 ┆ i64 ┆ struct[3] │
|
|
1279
|
+
# # ╞═════╪═════╪═════╪════════════╡
|
|
1280
|
+
# # │ 1 ┆ 3 ┆ 5 ┆ {1,4,9} │
|
|
1281
|
+
# # │ 2 ┆ 4 ┆ 6 ┆ {2,6,12} │
|
|
1282
|
+
# # │ 3 ┆ 5 ┆ 7 ┆ {3,8,15} │
|
|
1283
|
+
# # └─────┴─────┴─────┴────────────┘
|
|
1284
|
+
def cum_reduce(
|
|
1285
|
+
exprs,
|
|
1286
|
+
returns_scalar: false,
|
|
1287
|
+
return_dtype: nil,
|
|
1288
|
+
&function
|
|
1289
|
+
)
|
|
1290
|
+
if exprs.is_a?(Expr)
|
|
1291
|
+
exprs = [exprs]
|
|
902
1292
|
end
|
|
903
|
-
|
|
904
|
-
|
|
1293
|
+
|
|
1294
|
+
rt = nil
|
|
1295
|
+
if !return_dtype.nil?
|
|
1296
|
+
rt = Utils.parse_into_datatype_expr(return_dtype)._rbdatatype_expr
|
|
905
1297
|
end
|
|
906
|
-
|
|
1298
|
+
|
|
1299
|
+
rbexprs = Utils.parse_into_list_of_expressions(exprs)
|
|
1300
|
+
Utils.wrap_expr(
|
|
1301
|
+
Plr.cum_reduce(
|
|
1302
|
+
_wrap_acc_lambda(function),
|
|
1303
|
+
rbexprs,
|
|
1304
|
+
returns_scalar,
|
|
1305
|
+
rt
|
|
1306
|
+
).alias("cum_reduce")
|
|
1307
|
+
)
|
|
907
1308
|
end
|
|
908
1309
|
|
|
909
|
-
# Compute two argument arctan in
|
|
1310
|
+
# Compute two argument arctan in radians.
|
|
910
1311
|
#
|
|
911
|
-
# Returns the angle (in
|
|
912
|
-
# and the ray from the origin to (x,y).
|
|
1312
|
+
# Returns the angle (in radians) in the plane between the
|
|
1313
|
+
# positive x-axis and the ray from the origin to (x,y).
|
|
913
1314
|
#
|
|
914
1315
|
# @param y [Object]
|
|
915
1316
|
# Column name or Expression.
|
|
@@ -919,47 +1320,44 @@ module Polars
|
|
|
919
1320
|
# @return [Expr]
|
|
920
1321
|
#
|
|
921
1322
|
# @example
|
|
922
|
-
#
|
|
1323
|
+
# c = Math.sqrt(2) / 2
|
|
923
1324
|
# df = Polars::DataFrame.new(
|
|
924
1325
|
# {
|
|
925
|
-
# "y" => [
|
|
926
|
-
# "x" => [
|
|
1326
|
+
# "y" => [c, -c, c, -c],
|
|
1327
|
+
# "x" => [c, c, -c, -c]
|
|
927
1328
|
# }
|
|
928
1329
|
# )
|
|
929
|
-
# df.
|
|
930
|
-
# Polars.arctan2d("y", "x").alias("atan2d"), Polars.arctan2("y", "x").alias("atan2")
|
|
931
|
-
# )
|
|
1330
|
+
# df.with_columns(Polars.arctan2("y", "x").alias("atan2"))
|
|
932
1331
|
# # =>
|
|
933
|
-
# # shape: (4,
|
|
934
|
-
# #
|
|
935
|
-
# # │
|
|
936
|
-
# # │ ---
|
|
937
|
-
# # │ f64
|
|
938
|
-
# #
|
|
939
|
-
# # │
|
|
940
|
-
# # │ -
|
|
941
|
-
# # │
|
|
942
|
-
# # │ -
|
|
943
|
-
# #
|
|
944
|
-
def
|
|
1332
|
+
# # shape: (4, 3)
|
|
1333
|
+
# # ┌───────────┬───────────┬───────────┐
|
|
1334
|
+
# # │ y ┆ x ┆ atan2 │
|
|
1335
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1336
|
+
# # │ f64 ┆ f64 ┆ f64 │
|
|
1337
|
+
# # ╞═══════════╪═══════════╪═══════════╡
|
|
1338
|
+
# # │ 0.707107 ┆ 0.707107 ┆ 0.785398 │
|
|
1339
|
+
# # │ -0.707107 ┆ 0.707107 ┆ -0.785398 │
|
|
1340
|
+
# # │ 0.707107 ┆ -0.707107 ┆ 2.356194 │
|
|
1341
|
+
# # │ -0.707107 ┆ -0.707107 ┆ -2.356194 │
|
|
1342
|
+
# # └───────────┴───────────┴───────────┘
|
|
1343
|
+
def arctan2(y, x)
|
|
945
1344
|
if Utils.strlike?(y)
|
|
946
1345
|
y = col(y)
|
|
947
1346
|
end
|
|
948
1347
|
if Utils.strlike?(x)
|
|
949
1348
|
x = col(x)
|
|
950
1349
|
end
|
|
951
|
-
Utils.wrap_expr(Plr.
|
|
1350
|
+
Utils.wrap_expr(Plr.arctan2(y._rbexpr, x._rbexpr))
|
|
952
1351
|
end
|
|
953
1352
|
|
|
954
1353
|
# Exclude certain columns from a wildcard/regex selection.
|
|
955
1354
|
#
|
|
956
1355
|
# @param columns [Object]
|
|
957
|
-
#
|
|
958
|
-
#
|
|
959
|
-
#
|
|
960
|
-
#
|
|
961
|
-
#
|
|
962
|
-
# - a dtype or multiple dtypes
|
|
1356
|
+
# The name or datatype of the column(s) to exclude. Accepts regular expression
|
|
1357
|
+
# input. Regular expressions should start with `^` and end with `$`.
|
|
1358
|
+
# @param more_columns [Array]
|
|
1359
|
+
# Additional names or datatypes of columns to exclude, specified as positional
|
|
1360
|
+
# arguments.
|
|
963
1361
|
#
|
|
964
1362
|
# @return [Object]
|
|
965
1363
|
#
|
|
@@ -1010,8 +1408,8 @@ module Polars
|
|
|
1010
1408
|
# # │ 2.5 │
|
|
1011
1409
|
# # │ 1.5 │
|
|
1012
1410
|
# # └──────┘
|
|
1013
|
-
def exclude(columns)
|
|
1014
|
-
col("*").exclude(columns)
|
|
1411
|
+
def exclude(columns, *more_columns)
|
|
1412
|
+
col("*").exclude(columns, *more_columns)
|
|
1015
1413
|
end
|
|
1016
1414
|
|
|
1017
1415
|
# Syntactic sugar for `Polars.col("foo").agg_groups`.
|
|
@@ -1043,8 +1441,16 @@ module Polars
|
|
|
1043
1441
|
#
|
|
1044
1442
|
# @param exprs [Object]
|
|
1045
1443
|
# Columns use to determine the ordering.
|
|
1046
|
-
# @param
|
|
1444
|
+
# @param more_exprs [Array]
|
|
1445
|
+
# Additional columns to arg sort by, specified as positional arguments.
|
|
1446
|
+
# @param descending [Boolean]
|
|
1047
1447
|
# Default is ascending.
|
|
1448
|
+
# @param nulls_last [Boolean]
|
|
1449
|
+
# Place null values last.
|
|
1450
|
+
# @param multithreaded [Boolean]
|
|
1451
|
+
# Sort using multiple threads.
|
|
1452
|
+
# @param maintain_order [Boolean]
|
|
1453
|
+
# Whether the order should be maintained if elements are equal.
|
|
1048
1454
|
#
|
|
1049
1455
|
# @return [Expr]
|
|
1050
1456
|
#
|
|
@@ -1071,7 +1477,7 @@ module Polars
|
|
|
1071
1477
|
# # └─────┘
|
|
1072
1478
|
#
|
|
1073
1479
|
# @example Compute the arg sort by multiple columns by either passing a list of columns, or by specifying each column as a positional argument.
|
|
1074
|
-
# df.select(Polars.arg_sort_by(["a", "b"],
|
|
1480
|
+
# df.select(Polars.arg_sort_by(["a", "b"], descending: true))
|
|
1075
1481
|
# # =>
|
|
1076
1482
|
# # shape: (4, 1)
|
|
1077
1483
|
# # ┌─────┐
|
|
@@ -1102,17 +1508,16 @@ module Polars
|
|
|
1102
1508
|
def arg_sort_by(
|
|
1103
1509
|
exprs,
|
|
1104
1510
|
*more_exprs,
|
|
1105
|
-
|
|
1511
|
+
descending: false,
|
|
1106
1512
|
nulls_last: false,
|
|
1107
1513
|
multithreaded: true,
|
|
1108
1514
|
maintain_order: false
|
|
1109
1515
|
)
|
|
1110
1516
|
exprs = Utils.parse_into_list_of_expressions(exprs, *more_exprs)
|
|
1111
|
-
|
|
1517
|
+
descending = Utils.extend_bool(descending, exprs.length, "descending", "exprs")
|
|
1112
1518
|
nulls_last = Utils.extend_bool(nulls_last, exprs.length, "nulls_last", "exprs")
|
|
1113
|
-
Utils.wrap_expr(Plr.arg_sort_by(exprs,
|
|
1519
|
+
Utils.wrap_expr(Plr.arg_sort_by(exprs, descending, nulls_last, multithreaded, maintain_order))
|
|
1114
1520
|
end
|
|
1115
|
-
alias_method :argsort_by, :arg_sort_by
|
|
1116
1521
|
|
|
1117
1522
|
# Collect multiple LazyFrames at the same time.
|
|
1118
1523
|
#
|
|
@@ -1120,62 +1525,45 @@ module Polars
|
|
|
1120
1525
|
#
|
|
1121
1526
|
# @param lazy_frames [Boolean]
|
|
1122
1527
|
# A list of LazyFrames to collect.
|
|
1123
|
-
# @param
|
|
1124
|
-
#
|
|
1125
|
-
#
|
|
1126
|
-
#
|
|
1127
|
-
# @param
|
|
1128
|
-
#
|
|
1129
|
-
#
|
|
1130
|
-
#
|
|
1131
|
-
#
|
|
1132
|
-
#
|
|
1133
|
-
#
|
|
1134
|
-
#
|
|
1135
|
-
# @param
|
|
1136
|
-
#
|
|
1137
|
-
#
|
|
1138
|
-
#
|
|
1139
|
-
#
|
|
1140
|
-
#
|
|
1528
|
+
# @param optimizations
|
|
1529
|
+
# The optimization passes done during query optimization.
|
|
1530
|
+
#
|
|
1531
|
+
# This has no effect if `lazy` is set to `true`.
|
|
1532
|
+
# @param engine [String]
|
|
1533
|
+
# Select the engine used to process the query, optional.
|
|
1534
|
+
# At the moment, if set to `"auto"` (default), the query is run
|
|
1535
|
+
# using the polars streaming engine. Polars will also
|
|
1536
|
+
# attempt to use the engine set by the `POLARS_ENGINE_AFFINITY`
|
|
1537
|
+
# environment variable. If it cannot run the query using the
|
|
1538
|
+
# selected engine, the query is run using the polars streaming
|
|
1539
|
+
# engine.
|
|
1540
|
+
# @param lazy [Boolean]
|
|
1541
|
+
# Return as LazyFrame that can be collected later.
|
|
1542
|
+
# This is only correct if all inputs sink to disk.
|
|
1543
|
+
#
|
|
1544
|
+
# This functionality is considered **unstable**. It may be changed
|
|
1545
|
+
# at any point without it being considered a breaking change.
|
|
1141
1546
|
#
|
|
1142
1547
|
# @return [Array]
|
|
1143
1548
|
def collect_all(
|
|
1144
1549
|
lazy_frames,
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
simplify_expression: true,
|
|
1149
|
-
string_cache: false,
|
|
1150
|
-
no_optimization: false,
|
|
1151
|
-
slice_pushdown: true,
|
|
1152
|
-
common_subplan_elimination: true,
|
|
1153
|
-
allow_streaming: false
|
|
1550
|
+
optimizations: DEFAULT_QUERY_OPT_FLAGS,
|
|
1551
|
+
engine: "auto",
|
|
1552
|
+
lazy: false
|
|
1154
1553
|
)
|
|
1155
|
-
|
|
1156
|
-
predicate_pushdown = false
|
|
1157
|
-
projection_pushdown = false
|
|
1158
|
-
slice_pushdown = false
|
|
1159
|
-
common_subplan_elimination = false
|
|
1160
|
-
end
|
|
1554
|
+
lfs = lazy_frames.map { |lf| lf._ldf }
|
|
1161
1555
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
simplify_expression,
|
|
1170
|
-
slice_pushdown,
|
|
1171
|
-
common_subplan_elimination,
|
|
1172
|
-
allow_streaming,
|
|
1173
|
-
false
|
|
1174
|
-
)
|
|
1175
|
-
prepared << ldf
|
|
1556
|
+
if lazy
|
|
1557
|
+
msg = "the `lazy` parameter of `collect_all` is considered unstable."
|
|
1558
|
+
Utils.issue_unstable_warning(msg)
|
|
1559
|
+
|
|
1560
|
+
ldf = Plr.collect_all_lazy(lfs, optimizations._rboptflags)
|
|
1561
|
+
lf = LazyFrame._from_pyldf(ldf)
|
|
1562
|
+
return lf
|
|
1176
1563
|
end
|
|
1177
1564
|
|
|
1178
|
-
|
|
1565
|
+
engine = LazyFrame._select_engine(engine)
|
|
1566
|
+
out = Plr.collect_all(lfs, engine, optimizations._rboptflags)
|
|
1179
1567
|
|
|
1180
1568
|
# wrap the rbdataframes into dataframe
|
|
1181
1569
|
result = out.map { |rbdf| Utils.wrap_df(rbdf) }
|
|
@@ -1183,6 +1571,25 @@ module Polars
|
|
|
1183
1571
|
result
|
|
1184
1572
|
end
|
|
1185
1573
|
|
|
1574
|
+
# Explain multiple LazyFrames as if passed to `collect_all`.
|
|
1575
|
+
#
|
|
1576
|
+
# Common Subplan Elimination is applied on the combined plan, meaning
|
|
1577
|
+
# that diverging queries will run only once.
|
|
1578
|
+
#
|
|
1579
|
+
# @param lazy_frames [Array]
|
|
1580
|
+
# A list of LazyFrames to collect.
|
|
1581
|
+
# @param optimizations [Object]
|
|
1582
|
+
# The optimization passes done during query optimization.
|
|
1583
|
+
#
|
|
1584
|
+
# @return [String]
|
|
1585
|
+
def explain_all(
|
|
1586
|
+
lazy_frames,
|
|
1587
|
+
optimizations: DEFAULT_QUERY_OPT_FLAGS
|
|
1588
|
+
)
|
|
1589
|
+
lfs = lazy_frames.map { |lf| lf._ldf }
|
|
1590
|
+
Plr.explain_all(lfs, optimizations._rboptflags)
|
|
1591
|
+
end
|
|
1592
|
+
|
|
1186
1593
|
# Run polars expressions without a context.
|
|
1187
1594
|
#
|
|
1188
1595
|
# This is syntactic sugar for running `df.select` on an empty DataFrame.
|
|
@@ -1191,6 +1598,9 @@ module Polars
|
|
|
1191
1598
|
# Column(s) to select, specified as positional arguments.
|
|
1192
1599
|
# Accepts expression input. Strings are parsed as column names,
|
|
1193
1600
|
# other non-expression inputs are parsed as literals.
|
|
1601
|
+
# @param eager [Boolean]
|
|
1602
|
+
# Evaluate immediately and return a `DataFrame` (default); if set to `false`,
|
|
1603
|
+
# return a `LazyFrame` instead.
|
|
1194
1604
|
# @param named_exprs [Hash]
|
|
1195
1605
|
# Additional columns to select, specified as keyword arguments.
|
|
1196
1606
|
# The columns will be renamed to the keyword used.
|
|
@@ -1212,8 +1622,9 @@ module Polars
|
|
|
1212
1622
|
# # │ 2 │
|
|
1213
1623
|
# # │ 1 │
|
|
1214
1624
|
# # └─────┘
|
|
1215
|
-
def select(*exprs, **named_exprs)
|
|
1216
|
-
DataFrame.new
|
|
1625
|
+
def select(*exprs, eager: true, **named_exprs)
|
|
1626
|
+
empty_frame = eager ? Polars::DataFrame.new : Polars::LazyFrame.new
|
|
1627
|
+
empty_frame.select(*exprs, **named_exprs)
|
|
1217
1628
|
end
|
|
1218
1629
|
|
|
1219
1630
|
# Return indices where `condition` evaluates `true`.
|
|
@@ -1258,6 +1669,10 @@ module Polars
|
|
|
1258
1669
|
# names, other non-expression inputs are parsed as literals.
|
|
1259
1670
|
# @param more_exprs [Hash]
|
|
1260
1671
|
# Additional columns to coalesce, specified as positional arguments.
|
|
1672
|
+
# @param eager [Boolean]
|
|
1673
|
+
# Evaluate immediately and return a `Series`; this requires that at least one
|
|
1674
|
+
# of the given arguments is a `Series`. If set to `false` (default), return
|
|
1675
|
+
# an expression instead.
|
|
1261
1676
|
#
|
|
1262
1677
|
# @return [Expr]
|
|
1263
1678
|
#
|
|
@@ -1297,32 +1712,55 @@ module Polars
|
|
|
1297
1712
|
# # │ null ┆ null ┆ 3 ┆ 3.0 │
|
|
1298
1713
|
# # │ null ┆ null ┆ null ┆ 10.0 │
|
|
1299
1714
|
# # └──────┴──────┴──────┴──────┘
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1715
|
+
#
|
|
1716
|
+
# @example
|
|
1717
|
+
# s1 = Polars::Series.new("a", [nil, 2, nil])
|
|
1718
|
+
# s2 = Polars::Series.new("b", [1, nil, 3])
|
|
1719
|
+
# Polars.coalesce(s1, s2, eager: true)
|
|
1720
|
+
# # =>
|
|
1721
|
+
# # shape: (3,)
|
|
1722
|
+
# # Series: 'a' [i64]
|
|
1723
|
+
# # [
|
|
1724
|
+
# # 1
|
|
1725
|
+
# # 2
|
|
1726
|
+
# # 3
|
|
1727
|
+
# # ]
|
|
1728
|
+
def coalesce(exprs, *more_exprs, eager: false)
|
|
1729
|
+
if eager
|
|
1730
|
+
exprs = [exprs] + more_exprs
|
|
1731
|
+
series = exprs.filter_map { |e| e if e.is_a?(Series) }
|
|
1732
|
+
if !series.any?
|
|
1733
|
+
msg = "expected at least one Series in 'coalesce' if 'eager: true'"
|
|
1734
|
+
raise ArgumentError, msg
|
|
1735
|
+
end
|
|
1736
|
+
|
|
1737
|
+
exprs = exprs.map { |e| e.is_a?(Series) ? e.name : e }
|
|
1738
|
+
Polars::DataFrame.new(series).select(coalesce(exprs, eager: false)).to_series
|
|
1739
|
+
else
|
|
1740
|
+
exprs = Utils.parse_into_list_of_expressions(exprs, *more_exprs)
|
|
1741
|
+
Utils.wrap_expr(Plr.coalesce(exprs))
|
|
1742
|
+
end
|
|
1303
1743
|
end
|
|
1304
1744
|
|
|
1305
1745
|
# Utility function that parses an epoch timestamp (or Unix time) to Polars Date(time).
|
|
1306
1746
|
#
|
|
1307
1747
|
# Depending on the `unit` provided, this function will return a different dtype:
|
|
1308
|
-
# -
|
|
1309
|
-
# -
|
|
1310
|
-
# -
|
|
1311
|
-
# -
|
|
1312
|
-
# -
|
|
1748
|
+
# - time_unit: "d" returns pl.Date
|
|
1749
|
+
# - time_unit: "s" returns pl.Datetime["us"] (pl.Datetime's default)
|
|
1750
|
+
# - time_unit: "ms" returns pl.Datetime["ms"]
|
|
1751
|
+
# - time_unit: "us" returns pl.Datetime["us"]
|
|
1752
|
+
# - time_unit: "ns" returns pl.Datetime["ns"]
|
|
1313
1753
|
#
|
|
1314
1754
|
# @param column [Object]
|
|
1315
1755
|
# Series or expression to parse integers to pl.Datetime.
|
|
1316
|
-
# @param
|
|
1756
|
+
# @param time_unit [String]
|
|
1317
1757
|
# The unit of the timesteps since epoch time.
|
|
1318
|
-
# @param eager [Boolean]
|
|
1319
|
-
# If eager evaluation is `true`, a Series is returned instead of an Expr.
|
|
1320
1758
|
#
|
|
1321
1759
|
# @return [Object]
|
|
1322
1760
|
#
|
|
1323
1761
|
# @example
|
|
1324
1762
|
# df = Polars::DataFrame.new({"timestamp" => [1666683077, 1666683099]}).lazy
|
|
1325
|
-
# df.select(Polars.from_epoch(Polars.col("timestamp"),
|
|
1763
|
+
# df.select(Polars.from_epoch(Polars.col("timestamp"), time_unit: "s")).collect
|
|
1326
1764
|
# # =>
|
|
1327
1765
|
# # shape: (2, 1)
|
|
1328
1766
|
# # ┌─────────────────────┐
|
|
@@ -1333,32 +1771,102 @@ module Polars
|
|
|
1333
1771
|
# # │ 2022-10-25 07:31:17 │
|
|
1334
1772
|
# # │ 2022-10-25 07:31:39 │
|
|
1335
1773
|
# # └─────────────────────┘
|
|
1336
|
-
def from_epoch(column,
|
|
1774
|
+
def from_epoch(column, time_unit: "s")
|
|
1337
1775
|
if Utils.strlike?(column)
|
|
1338
|
-
column = col(column)
|
|
1776
|
+
column = F.col(column)
|
|
1339
1777
|
elsif !column.is_a?(Series) && !column.is_a?(Expr)
|
|
1340
1778
|
column = Series.new(column)
|
|
1341
1779
|
end
|
|
1342
1780
|
|
|
1343
|
-
if
|
|
1344
|
-
|
|
1345
|
-
elsif
|
|
1346
|
-
|
|
1347
|
-
elsif Utils::DTYPE_TEMPORAL_UNITS.include?(
|
|
1348
|
-
|
|
1781
|
+
if time_unit == "d"
|
|
1782
|
+
column.cast(Date)
|
|
1783
|
+
elsif time_unit == "s"
|
|
1784
|
+
(column.cast(Int64) * 1_000_000).cast(Datetime.new("us"))
|
|
1785
|
+
elsif Utils::DTYPE_TEMPORAL_UNITS.include?(time_unit)
|
|
1786
|
+
column.cast(Datetime.new(time_unit))
|
|
1349
1787
|
else
|
|
1350
|
-
raise ArgumentError, "
|
|
1788
|
+
raise ArgumentError, "`time_unit` must be one of {{'ns', 'us', 'ms', 's', 'd'}}, got #{time_unit.inspect}."
|
|
1351
1789
|
end
|
|
1790
|
+
end
|
|
1352
1791
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1792
|
+
# Compute the rolling covariance between two columns/ expressions.
|
|
1793
|
+
#
|
|
1794
|
+
# The window at a given row includes the row itself and the
|
|
1795
|
+
# `window_size - 1` elements before it.
|
|
1796
|
+
#
|
|
1797
|
+
# @param a [Object]
|
|
1798
|
+
# Column name or Expression.
|
|
1799
|
+
# @param b [Object]
|
|
1800
|
+
# Column name or Expression.
|
|
1801
|
+
# @param window_size [Integer]
|
|
1802
|
+
# The length of the window.
|
|
1803
|
+
# @param min_samples [Integer]
|
|
1804
|
+
# The number of values in the window that should be non-null before computing
|
|
1805
|
+
# a result. If nil, it will be set equal to window size.
|
|
1806
|
+
# @param ddof [Integer]
|
|
1807
|
+
# Delta degrees of freedom. The divisor used in calculations
|
|
1808
|
+
# is `N - ddof`, where `N` represents the number of elements.
|
|
1809
|
+
#
|
|
1810
|
+
# @return [Expr]
|
|
1811
|
+
def rolling_cov(
|
|
1812
|
+
a,
|
|
1813
|
+
b,
|
|
1814
|
+
window_size:,
|
|
1815
|
+
min_samples: nil,
|
|
1816
|
+
ddof: 1
|
|
1817
|
+
)
|
|
1818
|
+
if min_samples.nil?
|
|
1819
|
+
min_samples = window_size
|
|
1820
|
+
end
|
|
1821
|
+
if Utils.strlike?(a)
|
|
1822
|
+
a = F.col(a)
|
|
1823
|
+
end
|
|
1824
|
+
if Utils.strlike?(b)
|
|
1825
|
+
b = F.col(b)
|
|
1826
|
+
end
|
|
1827
|
+
Utils.wrap_expr(
|
|
1828
|
+
Plr.rolling_cov(a._rbexpr, b._rbexpr, window_size, min_samples, ddof)
|
|
1829
|
+
)
|
|
1830
|
+
end
|
|
1831
|
+
|
|
1832
|
+
# Compute the rolling correlation between two columns/ expressions.
|
|
1833
|
+
#
|
|
1834
|
+
# The window at a given row includes the row itself and the
|
|
1835
|
+
# `window_size - 1` elements before it.
|
|
1836
|
+
#
|
|
1837
|
+
# @param a [Object]
|
|
1838
|
+
# Column name or Expression.
|
|
1839
|
+
# @param b [Object]
|
|
1840
|
+
# Column name or Expression.
|
|
1841
|
+
# @param window_size [Integer]
|
|
1842
|
+
# The length of the window.
|
|
1843
|
+
# @param min_samples [Integer]
|
|
1844
|
+
# The number of values in the window that should be non-null before computing
|
|
1845
|
+
# a result. If nil, it will be set equal to window size.
|
|
1846
|
+
# @param ddof [Integer]
|
|
1847
|
+
# Delta degrees of freedom. The divisor used in calculations
|
|
1848
|
+
# is `N - ddof`, where `N` represents the number of elements.
|
|
1849
|
+
#
|
|
1850
|
+
# @return [Expr]
|
|
1851
|
+
def rolling_corr(
|
|
1852
|
+
a,
|
|
1853
|
+
b,
|
|
1854
|
+
window_size:,
|
|
1855
|
+
min_samples: nil,
|
|
1856
|
+
ddof: 1
|
|
1857
|
+
)
|
|
1858
|
+
if min_samples.nil?
|
|
1859
|
+
min_samples = window_size
|
|
1361
1860
|
end
|
|
1861
|
+
if Utils.strlike?(a)
|
|
1862
|
+
a = F.col(a)
|
|
1863
|
+
end
|
|
1864
|
+
if Utils.strlike?(b)
|
|
1865
|
+
b = F.col(b)
|
|
1866
|
+
end
|
|
1867
|
+
Utils.wrap_expr(
|
|
1868
|
+
Plr.rolling_corr(a._rbexpr, b._rbexpr, window_size, min_samples, ddof)
|
|
1869
|
+
)
|
|
1362
1870
|
end
|
|
1363
1871
|
|
|
1364
1872
|
# Parse one or more SQL expressions to polars expression(s).
|
|
@@ -1403,5 +1911,115 @@ module Polars
|
|
|
1403
1911
|
sql.map { |q| Utils.wrap_expr(Plr.sql_expr(q)) }
|
|
1404
1912
|
end
|
|
1405
1913
|
end
|
|
1914
|
+
|
|
1915
|
+
# Generates a sequence of integers.
|
|
1916
|
+
#
|
|
1917
|
+
# The length of the returned sequence will match the context length, and the
|
|
1918
|
+
# datatype will match the one returned by `get_index_dtype()`.
|
|
1919
|
+
#
|
|
1920
|
+
# If you would like to generate sequences with custom offsets / length /
|
|
1921
|
+
# step size / datatypes, it is recommended to use `int_range` instead.
|
|
1922
|
+
#
|
|
1923
|
+
# @note
|
|
1924
|
+
# This functionality is considered **unstable**. It may be changed
|
|
1925
|
+
# at any point without it being considered a breaking change.
|
|
1926
|
+
#
|
|
1927
|
+
# @param name [String]
|
|
1928
|
+
# Name of the returned column.
|
|
1929
|
+
#
|
|
1930
|
+
# @return [Expr]
|
|
1931
|
+
#
|
|
1932
|
+
# @example
|
|
1933
|
+
# df = Polars::DataFrame.new({"x" => ["A", "A", "B", "B", "B"]})
|
|
1934
|
+
# df.with_columns(Polars.row_index, Polars.row_index("another_index"))
|
|
1935
|
+
# # =>
|
|
1936
|
+
# # shape: (5, 3)
|
|
1937
|
+
# # ┌─────┬───────┬───────────────┐
|
|
1938
|
+
# # │ x ┆ index ┆ another_index │
|
|
1939
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1940
|
+
# # │ str ┆ u32 ┆ u32 │
|
|
1941
|
+
# # ╞═════╪═══════╪═══════════════╡
|
|
1942
|
+
# # │ A ┆ 0 ┆ 0 │
|
|
1943
|
+
# # │ A ┆ 1 ┆ 1 │
|
|
1944
|
+
# # │ B ┆ 2 ┆ 2 │
|
|
1945
|
+
# # │ B ┆ 3 ┆ 3 │
|
|
1946
|
+
# # │ B ┆ 4 ┆ 4 │
|
|
1947
|
+
# # └─────┴───────┴───────────────┘
|
|
1948
|
+
#
|
|
1949
|
+
# @example
|
|
1950
|
+
# df.group_by("x").agg(Polars.row_index).sort("x")
|
|
1951
|
+
# # =>
|
|
1952
|
+
# # shape: (2, 2)
|
|
1953
|
+
# # ┌─────┬───────────┐
|
|
1954
|
+
# # │ x ┆ index │
|
|
1955
|
+
# # │ --- ┆ --- │
|
|
1956
|
+
# # │ str ┆ list[u32] │
|
|
1957
|
+
# # ╞═════╪═══════════╡
|
|
1958
|
+
# # │ A ┆ [0, 1] │
|
|
1959
|
+
# # │ B ┆ [0, 1, 2] │
|
|
1960
|
+
# # └─────┴───────────┘
|
|
1961
|
+
#
|
|
1962
|
+
# @example
|
|
1963
|
+
# df.select(Polars.row_index)
|
|
1964
|
+
# # =>
|
|
1965
|
+
# # shape: (5, 1)
|
|
1966
|
+
# # ┌───────┐
|
|
1967
|
+
# # │ index │
|
|
1968
|
+
# # │ --- │
|
|
1969
|
+
# # │ u32 │
|
|
1970
|
+
# # ╞═══════╡
|
|
1971
|
+
# # │ 0 │
|
|
1972
|
+
# # │ 1 │
|
|
1973
|
+
# # │ 2 │
|
|
1974
|
+
# # │ 3 │
|
|
1975
|
+
# # │ 4 │
|
|
1976
|
+
# # └───────┘
|
|
1977
|
+
def row_index(name = "index")
|
|
1978
|
+
# Notes
|
|
1979
|
+
# * Dispatching to `int_range` means that we cannot accept an offset
|
|
1980
|
+
# parameter, as unlike `DataFrame.with_row_index`, `int_range` will simply
|
|
1981
|
+
# truncate instead of raising an error.
|
|
1982
|
+
F.int_range(
|
|
1983
|
+
F.len,
|
|
1984
|
+
dtype: get_index_type
|
|
1985
|
+
).alias(name)
|
|
1986
|
+
end
|
|
1987
|
+
|
|
1988
|
+
private
|
|
1989
|
+
|
|
1990
|
+
def _wrap_acc_lambda(function)
|
|
1991
|
+
lambda do |t|
|
|
1992
|
+
a, b = t
|
|
1993
|
+
function.(Utils.wrap_s(a), Utils.wrap_s(b))._s
|
|
1994
|
+
end
|
|
1995
|
+
end
|
|
1996
|
+
|
|
1997
|
+
def _map_batches_wrapper(function, returns_scalar:)
|
|
1998
|
+
lambda do |sl, *args, **kwargs|
|
|
1999
|
+
return_dtype = kwargs[:return_dtype]
|
|
2000
|
+
slp = sl.map { |s| Utils.wrap_s(s) }
|
|
2001
|
+
|
|
2002
|
+
rv = nil
|
|
2003
|
+
begin
|
|
2004
|
+
rv = function.(slp, *args, **kwargs)
|
|
2005
|
+
rescue ArgumentError => e
|
|
2006
|
+
if e.message == "wrong number of arguments (given 2, expected 1)"
|
|
2007
|
+
kwargs.delete(:return_dtype)
|
|
2008
|
+
rv = function.(slp, *args, **kwargs)
|
|
2009
|
+
else
|
|
2010
|
+
raise
|
|
2011
|
+
end
|
|
2012
|
+
end
|
|
2013
|
+
|
|
2014
|
+
if rv.is_a?(Series)
|
|
2015
|
+
rv._s
|
|
2016
|
+
elsif returns_scalar
|
|
2017
|
+
Series.new([rv], dtype: return_dtype)._s
|
|
2018
|
+
else
|
|
2019
|
+
msg = "`map` with `returns_scalar: false` must return a Series; found #{rv.inspect}.\n\nIf `returns_scalar` is set to `true`, a returned value can be a scalar value."
|
|
2020
|
+
raise TypeError, msg
|
|
2021
|
+
end
|
|
2022
|
+
end
|
|
2023
|
+
end
|
|
1406
2024
|
end
|
|
1407
2025
|
end
|