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/selectors.rb
CHANGED
|
@@ -1,118 +1,5 @@
|
|
|
1
1
|
module Polars
|
|
2
2
|
module Selectors
|
|
3
|
-
# @private
|
|
4
|
-
class SelectorProxy < Expr
|
|
5
|
-
attr_accessor :_attrs
|
|
6
|
-
attr_accessor :_repr_override
|
|
7
|
-
|
|
8
|
-
def initialize(
|
|
9
|
-
expr,
|
|
10
|
-
name:,
|
|
11
|
-
parameters: nil
|
|
12
|
-
)
|
|
13
|
-
self._rbexpr = expr._rbexpr
|
|
14
|
-
self._attrs = {
|
|
15
|
-
name: name,
|
|
16
|
-
params: parameters
|
|
17
|
-
}
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def inspect
|
|
21
|
-
if !_attrs
|
|
22
|
-
as_expr.inspect
|
|
23
|
-
elsif _repr_override
|
|
24
|
-
_repr_override
|
|
25
|
-
else
|
|
26
|
-
selector_name = _attrs[:name]
|
|
27
|
-
params = _attrs[:params] || {}
|
|
28
|
-
set_ops = {"and" => "&", "or" => "|", "sub" => "-", "xor" => "^"}
|
|
29
|
-
if set_ops.include?(selector_name)
|
|
30
|
-
op = set_ops[selector_name]
|
|
31
|
-
"(#{params.values.map(&:inspect).join(" #{op} ")})"
|
|
32
|
-
else
|
|
33
|
-
str_params = params.map { |k, v| k.start_with?("*") ? v.inspect[1..-2] : "#{k}=#{v.inspect}" }.join(", ")
|
|
34
|
-
"Polars.cs.#{selector_name}(#{str_params})"
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def ~
|
|
40
|
-
if Utils.is_selector(self)
|
|
41
|
-
inverted = Selectors.all - self
|
|
42
|
-
inverted._repr_override = "~#{inspect}"
|
|
43
|
-
else
|
|
44
|
-
inverted = ~as_expr
|
|
45
|
-
end
|
|
46
|
-
inverted
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def -(other)
|
|
50
|
-
if Utils.is_selector(other)
|
|
51
|
-
SelectorProxy.new(
|
|
52
|
-
meta._as_selector.meta._selector_sub(other),
|
|
53
|
-
parameters: {"self" => self, "other" => other},
|
|
54
|
-
name: "sub"
|
|
55
|
-
)
|
|
56
|
-
else
|
|
57
|
-
as_expr - other
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def &(other)
|
|
62
|
-
if Utils.is_column(other)
|
|
63
|
-
raise Todo
|
|
64
|
-
end
|
|
65
|
-
if Utils.is_selector(other)
|
|
66
|
-
SelectorProxy.new(
|
|
67
|
-
meta._as_selector.meta._selector_and(other),
|
|
68
|
-
parameters: {"self" => self, "other" => other},
|
|
69
|
-
name: "and"
|
|
70
|
-
)
|
|
71
|
-
else
|
|
72
|
-
as_expr & other
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def |(other)
|
|
77
|
-
if Utils.is_column(other)
|
|
78
|
-
raise Todo
|
|
79
|
-
end
|
|
80
|
-
if Utils.is_selector(other)
|
|
81
|
-
SelectorProxy.new(
|
|
82
|
-
meta._as_selector.meta._selector_and(other),
|
|
83
|
-
parameters: {"self" => self, "other" => other},
|
|
84
|
-
name: "or"
|
|
85
|
-
)
|
|
86
|
-
else
|
|
87
|
-
as_expr | other
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def ^(other)
|
|
92
|
-
if Utils.is_column(other)
|
|
93
|
-
raise Todo
|
|
94
|
-
end
|
|
95
|
-
if Utils.is_selector(other)
|
|
96
|
-
SelectorProxy.new(
|
|
97
|
-
meta._as_selector.meta._selector_and(other),
|
|
98
|
-
parameters: {"self" => self, "other" => other},
|
|
99
|
-
name: "xor"
|
|
100
|
-
)
|
|
101
|
-
else
|
|
102
|
-
as_expr ^ other
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def as_expr
|
|
107
|
-
Expr._from_rbexpr(_rbexpr)
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# @private
|
|
112
|
-
def self._selector_proxy_(...)
|
|
113
|
-
SelectorProxy.new(...)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
3
|
# @private
|
|
117
4
|
def self._re_string(string, escape: true)
|
|
118
5
|
if string.is_a?(::String)
|
|
@@ -131,11 +18,28 @@ module Polars
|
|
|
131
18
|
"(#{rx})"
|
|
132
19
|
end
|
|
133
20
|
|
|
134
|
-
# Select
|
|
21
|
+
# Select no columns.
|
|
135
22
|
#
|
|
136
|
-
#
|
|
23
|
+
# This is useful for composition with other selectors.
|
|
24
|
+
#
|
|
25
|
+
# @return [Selector]
|
|
137
26
|
#
|
|
138
27
|
# @example
|
|
28
|
+
# Polars::DataFrame.new({"a" => 1, "b" => 2}).select(Polars.cs.empty)
|
|
29
|
+
# # =>
|
|
30
|
+
# # shape: (0, 0)
|
|
31
|
+
# # ┌┐
|
|
32
|
+
# # ╞╡
|
|
33
|
+
# # └┘
|
|
34
|
+
def self.empty
|
|
35
|
+
Selector._from_rbselector(RbSelector.empty)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Select all columns.
|
|
39
|
+
#
|
|
40
|
+
# @return [Selector]
|
|
41
|
+
#
|
|
42
|
+
# @example Select all columns, casting them to string:
|
|
139
43
|
# df = Polars::DataFrame.new(
|
|
140
44
|
# {
|
|
141
45
|
# "dt" => [Date.new(1999, 12, 31), Date.new(2024, 1, 1)],
|
|
@@ -143,8 +47,6 @@ module Polars
|
|
|
143
47
|
# },
|
|
144
48
|
# schema_overrides: {"value" => Polars::Int32}
|
|
145
49
|
# )
|
|
146
|
-
#
|
|
147
|
-
# @example Select all columns, casting them to string:
|
|
148
50
|
# df.select(Polars.cs.all.cast(Polars::String))
|
|
149
51
|
# # =>
|
|
150
52
|
# # shape: (2, 2)
|
|
@@ -170,7 +72,7 @@ module Polars
|
|
|
170
72
|
# # │ 2024-01-01 │
|
|
171
73
|
# # └────────────┘
|
|
172
74
|
def self.all
|
|
173
|
-
|
|
75
|
+
Selector._from_rbselector(RbSelector.all)
|
|
174
76
|
end
|
|
175
77
|
|
|
176
78
|
# Select all columns with alphabetic names (eg: only letters).
|
|
@@ -182,7 +84,7 @@ module Polars
|
|
|
182
84
|
# Indicate whether to ignore the presence of spaces in column names; if so,
|
|
183
85
|
# only the other (non-space) characters are considered.
|
|
184
86
|
#
|
|
185
|
-
# @return [
|
|
87
|
+
# @return [Selector]
|
|
186
88
|
#
|
|
187
89
|
# @note
|
|
188
90
|
# Matching column names cannot contain *any* non-alphabetic characters. Note
|
|
@@ -274,20 +176,102 @@ module Polars
|
|
|
274
176
|
# note that we need to supply a pattern compatible with the *rust* regex crate
|
|
275
177
|
re_alpha = ascii_only ? "a-zA-Z" : "\\p{Alphabetic}"
|
|
276
178
|
re_space = ignore_spaces ? " " : ""
|
|
277
|
-
|
|
278
|
-
F.col("^[#{re_alpha}#{re_space}]+$"),
|
|
279
|
-
name: "alpha",
|
|
280
|
-
parameters: {"ascii_only" => ascii_only, "ignore_spaces" => ignore_spaces},
|
|
281
|
-
)
|
|
179
|
+
Selector._from_rbselector(RbSelector.matches("^[#{re_alpha}#{re_space}]+$"))
|
|
282
180
|
end
|
|
283
181
|
|
|
284
|
-
#
|
|
285
|
-
#
|
|
286
|
-
#
|
|
182
|
+
# Select all columns with alphanumeric names (eg: only letters and the digits 0-9).
|
|
183
|
+
#
|
|
184
|
+
# @param ascii_only [Boolean]
|
|
185
|
+
# Indicate whether to consider only ASCII alphabetic characters, or the full
|
|
186
|
+
# Unicode range of valid letters (accented, idiographic, etc).
|
|
187
|
+
# @param ignore_spaces [Boolean]
|
|
188
|
+
# Indicate whether to ignore the presence of spaces in column names; if so,
|
|
189
|
+
# only the other (non-space) characters are considered.
|
|
190
|
+
#
|
|
191
|
+
# @return [Selector]
|
|
192
|
+
#
|
|
193
|
+
# @note
|
|
194
|
+
# Matching column names cannot contain *any* non-alphabetic or integer characters.
|
|
195
|
+
# Note that the definition of "alphabetic" consists of all valid Unicode alphabetic
|
|
196
|
+
# characters (`\p{Alphabetic}`) and digit characters (`\d`) by default; this
|
|
197
|
+
# can be changed by setting `ascii_only: true`.
|
|
198
|
+
#
|
|
199
|
+
# @example Select columns with alphanumeric names:
|
|
200
|
+
# df = Polars::DataFrame.new(
|
|
201
|
+
# {
|
|
202
|
+
# "1st_col" => [100, 200, 300],
|
|
203
|
+
# "flagged" => [true, false, true],
|
|
204
|
+
# "00prefix" => ["01:aa", "02:bb", "03:cc"],
|
|
205
|
+
# "last col" => ["x", "y", "z"]
|
|
206
|
+
# }
|
|
207
|
+
# )
|
|
208
|
+
# df.select(Polars.cs.alphanumeric)
|
|
209
|
+
# # =>
|
|
210
|
+
# # shape: (3, 2)
|
|
211
|
+
# # ┌─────────┬──────────┐
|
|
212
|
+
# # │ flagged ┆ 00prefix │
|
|
213
|
+
# # │ --- ┆ --- │
|
|
214
|
+
# # │ bool ┆ str │
|
|
215
|
+
# # ╞═════════╪══════════╡
|
|
216
|
+
# # │ true ┆ 01:aa │
|
|
217
|
+
# # │ false ┆ 02:bb │
|
|
218
|
+
# # │ true ┆ 03:cc │
|
|
219
|
+
# # └─────────┴──────────┘
|
|
220
|
+
#
|
|
221
|
+
# @example
|
|
222
|
+
# df.select(Polars.cs.alphanumeric(ignore_spaces: true))
|
|
223
|
+
# # =>
|
|
224
|
+
# # shape: (3, 3)
|
|
225
|
+
# # ┌─────────┬──────────┬──────────┐
|
|
226
|
+
# # │ flagged ┆ 00prefix ┆ last col │
|
|
227
|
+
# # │ --- ┆ --- ┆ --- │
|
|
228
|
+
# # │ bool ┆ str ┆ str │
|
|
229
|
+
# # ╞═════════╪══════════╪══════════╡
|
|
230
|
+
# # │ true ┆ 01:aa ┆ x │
|
|
231
|
+
# # │ false ┆ 02:bb ┆ y │
|
|
232
|
+
# # │ true ┆ 03:cc ┆ z │
|
|
233
|
+
# # └─────────┴──────────┴──────────┘
|
|
234
|
+
#
|
|
235
|
+
# @example Select all columns *except* for those with alphanumeric names:
|
|
236
|
+
# df.select(~Polars.cs.alphanumeric)
|
|
237
|
+
# # =>
|
|
238
|
+
# # shape: (3, 2)
|
|
239
|
+
# # ┌─────────┬──────────┐
|
|
240
|
+
# # │ 1st_col ┆ last col │
|
|
241
|
+
# # │ --- ┆ --- │
|
|
242
|
+
# # │ i64 ┆ str │
|
|
243
|
+
# # ╞═════════╪══════════╡
|
|
244
|
+
# # │ 100 ┆ x │
|
|
245
|
+
# # │ 200 ┆ y │
|
|
246
|
+
# # │ 300 ┆ z │
|
|
247
|
+
# # └─────────┴──────────┘
|
|
248
|
+
#
|
|
249
|
+
# @example
|
|
250
|
+
# df.select(~Polars.cs.alphanumeric(ignore_spaces: true))
|
|
251
|
+
# # =>
|
|
252
|
+
# # shape: (3, 1)
|
|
253
|
+
# # ┌─────────┐
|
|
254
|
+
# # │ 1st_col │
|
|
255
|
+
# # │ --- │
|
|
256
|
+
# # │ i64 │
|
|
257
|
+
# # ╞═════════╡
|
|
258
|
+
# # │ 100 │
|
|
259
|
+
# # │ 200 │
|
|
260
|
+
# # │ 300 │
|
|
261
|
+
# # └─────────┘
|
|
262
|
+
def self.alphanumeric(ascii_only: false, ignore_spaces: false)
|
|
263
|
+
# note that we need to supply patterns compatible with the *rust* regex crate
|
|
264
|
+
re_alpha = ascii_only ? "a-zA-Z" : "\\p{Alphabetic}"
|
|
265
|
+
re_digit = ascii_only ? "0-9" : "\\d"
|
|
266
|
+
re_space = ignore_spaces ? " " : ""
|
|
267
|
+
Selector._from_rbselector(
|
|
268
|
+
RbSelector.matches("^[#{re_alpha}#{re_digit}#{re_space}]+$")
|
|
269
|
+
)
|
|
270
|
+
end
|
|
287
271
|
|
|
288
272
|
# Select all binary columns.
|
|
289
273
|
#
|
|
290
|
-
# @return [
|
|
274
|
+
# @return [Selector]
|
|
291
275
|
#
|
|
292
276
|
# @example
|
|
293
277
|
# df = Polars::DataFrame.new({"a" => ["hello".b], "b" => ["world"], "c" => ["!".b], "d" => [":)"]})
|
|
@@ -301,7 +285,7 @@ module Polars
|
|
|
301
285
|
# # │ b"hello" ┆ world ┆ b"!" ┆ :) │
|
|
302
286
|
# # └──────────┴───────┴────────┴─────┘
|
|
303
287
|
#
|
|
304
|
-
# @example Select binary columns and export as a
|
|
288
|
+
# @example Select binary columns and export as a hash:
|
|
305
289
|
# df.select(Polars.cs.binary).to_h(as_series: false)
|
|
306
290
|
# # => {"a"=>["hello"], "c"=>["!"]}
|
|
307
291
|
#
|
|
@@ -309,12 +293,12 @@ module Polars
|
|
|
309
293
|
# df.select(~Polars.cs.binary).to_h(as_series: false)
|
|
310
294
|
# # => {"b"=>["world"], "d"=>[":)"]}
|
|
311
295
|
def self.binary
|
|
312
|
-
|
|
296
|
+
by_dtype([Binary])
|
|
313
297
|
end
|
|
314
298
|
|
|
315
299
|
# Select all boolean columns.
|
|
316
300
|
#
|
|
317
|
-
# @return [
|
|
301
|
+
# @return [Selector]
|
|
318
302
|
#
|
|
319
303
|
# @example
|
|
320
304
|
# df = Polars::DataFrame.new({"n" => 1..4}).with_columns(n_even: Polars.col("n") % 2 == 0)
|
|
@@ -361,24 +345,550 @@ module Polars
|
|
|
361
345
|
# # │ 4 │
|
|
362
346
|
# # └─────┘
|
|
363
347
|
def self.boolean
|
|
364
|
-
|
|
348
|
+
by_dtype([Boolean])
|
|
365
349
|
end
|
|
366
350
|
|
|
367
|
-
#
|
|
368
|
-
#
|
|
369
|
-
#
|
|
351
|
+
# Select all columns matching the given dtypes.
|
|
352
|
+
#
|
|
353
|
+
# @return [Selector]
|
|
354
|
+
#
|
|
355
|
+
# @example Select all columns with date or string dtypes:
|
|
356
|
+
# df = Polars::DataFrame.new(
|
|
357
|
+
# {
|
|
358
|
+
# "dt" => [Date.new(1999, 12, 31), Date.new(2024, 1, 1), Date.new(2010, 7, 5)],
|
|
359
|
+
# "value" => [1_234_500, 5_000_555, -4_500_000],
|
|
360
|
+
# "other" => ["foo", "bar", "foo"]
|
|
361
|
+
# }
|
|
362
|
+
# )
|
|
363
|
+
# df.select(Polars.cs.by_dtype(Polars::Date, Polars::String))
|
|
364
|
+
# # =>
|
|
365
|
+
# # shape: (3, 2)
|
|
366
|
+
# # ┌────────────┬───────┐
|
|
367
|
+
# # │ dt ┆ other │
|
|
368
|
+
# # │ --- ┆ --- │
|
|
369
|
+
# # │ date ┆ str │
|
|
370
|
+
# # ╞════════════╪═══════╡
|
|
371
|
+
# # │ 1999-12-31 ┆ foo │
|
|
372
|
+
# # │ 2024-01-01 ┆ bar │
|
|
373
|
+
# # │ 2010-07-05 ┆ foo │
|
|
374
|
+
# # └────────────┴───────┘
|
|
375
|
+
#
|
|
376
|
+
# @example Select all columns that are not of date or string dtype:
|
|
377
|
+
# df.select(~Polars.cs.by_dtype(Polars::Date, Polars::String))
|
|
378
|
+
# # =>
|
|
379
|
+
# # shape: (3, 1)
|
|
380
|
+
# # ┌──────────┐
|
|
381
|
+
# # │ value │
|
|
382
|
+
# # │ --- │
|
|
383
|
+
# # │ i64 │
|
|
384
|
+
# # ╞══════════╡
|
|
385
|
+
# # │ 1234500 │
|
|
386
|
+
# # │ 5000555 │
|
|
387
|
+
# # │ -4500000 │
|
|
388
|
+
# # └──────────┘
|
|
389
|
+
#
|
|
390
|
+
# Group by string columns and sum the numeric columns:
|
|
391
|
+
# df.group_by(Polars.cs.string).agg(Polars.cs.numeric.sum).sort("other")
|
|
392
|
+
# # =>
|
|
393
|
+
# # shape: (2, 2)
|
|
394
|
+
# # ┌───────┬──────────┐
|
|
395
|
+
# # │ other ┆ value │
|
|
396
|
+
# # │ --- ┆ --- │
|
|
397
|
+
# # │ str ┆ i64 │
|
|
398
|
+
# # ╞═══════╪══════════╡
|
|
399
|
+
# # │ bar ┆ 5000555 │
|
|
400
|
+
# # │ foo ┆ -3265500 │
|
|
401
|
+
# # └───────┴──────────┘
|
|
402
|
+
def self.by_dtype(*dtypes)
|
|
403
|
+
all_dtypes = []
|
|
404
|
+
dtypes.each do |tp|
|
|
405
|
+
if Utils.is_polars_dtype(tp) || tp.is_a?(Class)
|
|
406
|
+
all_dtypes << tp
|
|
407
|
+
elsif tp.is_a?(::Array)
|
|
408
|
+
tp.each do |t|
|
|
409
|
+
if !(Utils.is_polars_dtype(t) || t.is_a?(Class))
|
|
410
|
+
msg = "invalid dtype: #{t.inspect}"
|
|
411
|
+
raise TypeError, msg
|
|
412
|
+
end
|
|
413
|
+
all_dtypes << t
|
|
414
|
+
end
|
|
415
|
+
else
|
|
416
|
+
msg = "invalid dtype: #{tp.inspect}"
|
|
417
|
+
raise TypeError, msg
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
Selector._by_dtype(all_dtypes)
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
# Select all columns matching the given indices (or range objects).
|
|
425
|
+
#
|
|
426
|
+
# @param indices [Array]
|
|
427
|
+
# One or more column indices (or range objects).
|
|
428
|
+
# Negative indexing is supported.
|
|
429
|
+
#
|
|
430
|
+
# @return [Selector]
|
|
431
|
+
#
|
|
432
|
+
# @note
|
|
433
|
+
# Matching columns are returned in the order in which their indexes
|
|
434
|
+
# appear in the selector, not the underlying schema order.
|
|
435
|
+
#
|
|
436
|
+
# @example
|
|
437
|
+
# df = Polars::DataFrame.new(
|
|
438
|
+
# {
|
|
439
|
+
# "key" => ["abc"],
|
|
440
|
+
# **100.times.to_h { |i| ["c%02d" % i, 0.5 * i] }
|
|
441
|
+
# }
|
|
442
|
+
# )
|
|
443
|
+
# # =>
|
|
444
|
+
# # shape: (1, 101)
|
|
445
|
+
# # ┌─────┬─────┬─────┬─────┬───┬──────┬──────┬──────┬──────┐
|
|
446
|
+
# # │ key ┆ c00 ┆ c01 ┆ c02 ┆ … ┆ c96 ┆ c97 ┆ c98 ┆ c99 │
|
|
447
|
+
# # │ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
448
|
+
# # │ str ┆ f64 ┆ f64 ┆ f64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
|
|
449
|
+
# # ╞═════╪═════╪═════╪═════╪═══╪══════╪══════╪══════╪══════╡
|
|
450
|
+
# # │ abc ┆ 0.0 ┆ 0.5 ┆ 1.0 ┆ … ┆ 48.0 ┆ 48.5 ┆ 49.0 ┆ 49.5 │
|
|
451
|
+
# # └─────┴─────┴─────┴─────┴───┴──────┴──────┴──────┴──────┘
|
|
452
|
+
#
|
|
453
|
+
# @example Select columns by index ("key" column and the two first/last columns):
|
|
454
|
+
# df.select(Polars.cs.by_index(0, 1, 2, -2, -1))
|
|
455
|
+
# # =>
|
|
456
|
+
# # shape: (1, 5)
|
|
457
|
+
# # ┌─────┬─────┬─────┬──────┬──────┐
|
|
458
|
+
# # │ key ┆ c00 ┆ c01 ┆ c98 ┆ c99 │
|
|
459
|
+
# # │ --- ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
460
|
+
# # │ str ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
|
|
461
|
+
# # ╞═════╪═════╪═════╪══════╪══════╡
|
|
462
|
+
# # │ abc ┆ 0.0 ┆ 0.5 ┆ 49.0 ┆ 49.5 │
|
|
463
|
+
# # └─────┴─────┴─────┴──────┴──────┘
|
|
464
|
+
#
|
|
465
|
+
# @example Select the "key" column and use a `range` object to select various columns.
|
|
466
|
+
# df.select(Polars.cs.by_index(0, (1...101).step(20)))
|
|
467
|
+
# # =>
|
|
468
|
+
# # shape: (1, 6)
|
|
469
|
+
# # ┌─────┬─────┬──────┬──────┬──────┬──────┐
|
|
470
|
+
# # │ key ┆ c00 ┆ c20 ┆ c40 ┆ c60 ┆ c80 │
|
|
471
|
+
# # │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
472
|
+
# # │ str ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
|
|
473
|
+
# # ╞═════╪═════╪══════╪══════╪══════╪══════╡
|
|
474
|
+
# # │ abc ┆ 0.0 ┆ 10.0 ┆ 20.0 ┆ 30.0 ┆ 40.0 │
|
|
475
|
+
# # └─────┴─────┴──────┴──────┴──────┴──────┘
|
|
476
|
+
#
|
|
477
|
+
# @example
|
|
478
|
+
# df.select(Polars.cs.by_index(0, (101...0).step(-25), require_all: false))
|
|
479
|
+
# # =>
|
|
480
|
+
# # shape: (1, 5)
|
|
481
|
+
# # ┌─────┬──────┬──────┬──────┬─────┐
|
|
482
|
+
# # │ key ┆ c75 ┆ c50 ┆ c25 ┆ c00 │
|
|
483
|
+
# # │ --- ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
484
|
+
# # │ str ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
|
|
485
|
+
# # ╞═════╪══════╪══════╪══════╪═════╡
|
|
486
|
+
# # │ abc ┆ 37.5 ┆ 25.0 ┆ 12.5 ┆ 0.0 │
|
|
487
|
+
# # └─────┴──────┴──────┴──────┴─────┘
|
|
488
|
+
#
|
|
489
|
+
# @example Select all columns *except* for the even-indexed ones:
|
|
490
|
+
# df.select(~Polars.cs.by_index((1...100).step(2)))
|
|
491
|
+
# # =>
|
|
492
|
+
# # shape: (1, 51)
|
|
493
|
+
# # ┌─────┬─────┬─────┬─────┬───┬──────┬──────┬──────┬──────┐
|
|
494
|
+
# # │ key ┆ c01 ┆ c03 ┆ c05 ┆ … ┆ c93 ┆ c95 ┆ c97 ┆ c99 │
|
|
495
|
+
# # │ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
496
|
+
# # │ str ┆ f64 ┆ f64 ┆ f64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
|
|
497
|
+
# # ╞═════╪═════╪═════╪═════╪═══╪══════╪══════╪══════╪══════╡
|
|
498
|
+
# # │ abc ┆ 0.5 ┆ 1.5 ┆ 2.5 ┆ … ┆ 46.5 ┆ 47.5 ┆ 48.5 ┆ 49.5 │
|
|
499
|
+
# # └─────┴─────┴─────┴─────┴───┴──────┴──────┴──────┴──────┘
|
|
500
|
+
def self.by_index(*indices, require_all: true)
|
|
501
|
+
all_indices = []
|
|
502
|
+
indices.each do |idx|
|
|
503
|
+
if idx.is_a?(Enumerable)
|
|
504
|
+
all_indices.concat(idx.to_a)
|
|
505
|
+
elsif idx.is_a?(Integer)
|
|
506
|
+
all_indices << idx
|
|
507
|
+
else
|
|
508
|
+
msg = "invalid index value: #{idx.inspect}"
|
|
509
|
+
raise TypeError, msg
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
Selector._from_rbselector(RbSelector.by_index(all_indices, require_all))
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
# Select all columns matching the given names.
|
|
517
|
+
#
|
|
518
|
+
# @param names [Array]
|
|
519
|
+
# One or more names of columns to select.
|
|
520
|
+
# @param require_all [Boolean]
|
|
521
|
+
# Whether to match *all* names (the default) or *any* of the names.
|
|
522
|
+
#
|
|
523
|
+
# @return [Selector]
|
|
524
|
+
#
|
|
525
|
+
# @note
|
|
526
|
+
# Matching columns are returned in the order in which they are declared in
|
|
527
|
+
# the selector, not the underlying schema order.
|
|
528
|
+
#
|
|
529
|
+
# @example
|
|
530
|
+
# df = Polars::DataFrame.new(
|
|
531
|
+
# {
|
|
532
|
+
# "foo" => ["x", "y"],
|
|
533
|
+
# "bar" => [123, 456],
|
|
534
|
+
# "baz" => [2.0, 5.5],
|
|
535
|
+
# "zap" => [false, true]
|
|
536
|
+
# }
|
|
537
|
+
# )
|
|
538
|
+
#
|
|
539
|
+
# @example Select columns by name:
|
|
540
|
+
# df.select(Polars.cs.by_name("foo", "bar"))
|
|
541
|
+
# # =>
|
|
542
|
+
# # shape: (2, 2)
|
|
543
|
+
# # ┌─────┬─────┐
|
|
544
|
+
# # │ foo ┆ bar │
|
|
545
|
+
# # │ --- ┆ --- │
|
|
546
|
+
# # │ str ┆ i64 │
|
|
547
|
+
# # ╞═════╪═════╡
|
|
548
|
+
# # │ x ┆ 123 │
|
|
549
|
+
# # │ y ┆ 456 │
|
|
550
|
+
# # └─────┴─────┘
|
|
551
|
+
#
|
|
552
|
+
# @example Match *any* of the given columns by name:
|
|
553
|
+
# df.select(Polars.cs.by_name("baz", "moose", "foo", "bear", require_all: false))
|
|
554
|
+
# # =>
|
|
555
|
+
# # shape: (2, 2)
|
|
556
|
+
# # ┌─────┬─────┐
|
|
557
|
+
# # │ baz ┆ foo │
|
|
558
|
+
# # │ --- ┆ --- │
|
|
559
|
+
# # │ f64 ┆ str │
|
|
560
|
+
# # ╞═════╪═════╡
|
|
561
|
+
# # │ 2.0 ┆ x │
|
|
562
|
+
# # │ 5.5 ┆ y │
|
|
563
|
+
# # └─────┴─────┘
|
|
564
|
+
#
|
|
565
|
+
# @example Match all columns *except* for those given:
|
|
566
|
+
# df.select(~Polars.cs.by_name("foo", "bar"))
|
|
567
|
+
# # =>
|
|
568
|
+
# # shape: (2, 2)
|
|
569
|
+
# # ┌─────┬───────┐
|
|
570
|
+
# # │ baz ┆ zap │
|
|
571
|
+
# # │ --- ┆ --- │
|
|
572
|
+
# # │ f64 ┆ bool │
|
|
573
|
+
# # ╞═════╪═══════╡
|
|
574
|
+
# # │ 2.0 ┆ false │
|
|
575
|
+
# # │ 5.5 ┆ true │
|
|
576
|
+
# # └─────┴───────┘
|
|
577
|
+
def self.by_name(*names, require_all: true)
|
|
578
|
+
all_names = []
|
|
579
|
+
names.each do |nm|
|
|
580
|
+
if nm.is_a?(::String)
|
|
581
|
+
all_names << nm
|
|
582
|
+
elsif nm.is_a?(::Array)
|
|
583
|
+
nm.each do |n|
|
|
584
|
+
if !n.is_a?(::String)
|
|
585
|
+
msg = "invalid name: #{n.inspect}"
|
|
586
|
+
raise TypeError, msg
|
|
587
|
+
end
|
|
588
|
+
all_names << n
|
|
589
|
+
end
|
|
590
|
+
else
|
|
591
|
+
msg = "invalid name: #{nm.inspect}"
|
|
592
|
+
raise TypeError, msg
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
Selector._by_name(all_names, strict: require_all, expand_patterns: false)
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
# Select all enum columns.
|
|
600
|
+
#
|
|
601
|
+
# @return [Selector]
|
|
602
|
+
#
|
|
603
|
+
# @note
|
|
604
|
+
# This functionality is considered **unstable**. It may be changed
|
|
605
|
+
# at any point without it being considered a breaking change.
|
|
606
|
+
#
|
|
607
|
+
# @example Select all enum columns:
|
|
608
|
+
# df = Polars::DataFrame.new(
|
|
609
|
+
# {
|
|
610
|
+
# "foo" => ["xx", "yy"],
|
|
611
|
+
# "bar" => [123, 456],
|
|
612
|
+
# "baz" => [2.0, 5.5],
|
|
613
|
+
# },
|
|
614
|
+
# schema_overrides: {"foo" => Polars::Enum.new(["xx", "yy"])}
|
|
615
|
+
# )
|
|
616
|
+
# df.select(Polars.cs.enum)
|
|
617
|
+
# # =>
|
|
618
|
+
# # shape: (2, 1)
|
|
619
|
+
# # ┌──────┐
|
|
620
|
+
# # │ foo │
|
|
621
|
+
# # │ --- │
|
|
622
|
+
# # │ enum │
|
|
623
|
+
# # ╞══════╡
|
|
624
|
+
# # │ xx │
|
|
625
|
+
# # │ yy │
|
|
626
|
+
# # └──────┘
|
|
627
|
+
#
|
|
628
|
+
# @example Select all columns *except* for those that are enum:
|
|
629
|
+
# df.select(~Polars.cs.enum)
|
|
630
|
+
# # =>
|
|
631
|
+
# # shape: (2, 2)
|
|
632
|
+
# # ┌─────┬─────┐
|
|
633
|
+
# # │ bar ┆ baz │
|
|
634
|
+
# # │ --- ┆ --- │
|
|
635
|
+
# # │ i64 ┆ f64 │
|
|
636
|
+
# # ╞═════╪═════╡
|
|
637
|
+
# # │ 123 ┆ 2.0 │
|
|
638
|
+
# # │ 456 ┆ 5.5 │
|
|
639
|
+
# # └─────┴─────┘
|
|
640
|
+
def self.enum
|
|
641
|
+
Selector._from_rbselector(RbSelector.enum_)
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
# Select all list columns.
|
|
645
|
+
#
|
|
646
|
+
# @return [Selector]
|
|
647
|
+
#
|
|
648
|
+
# @note
|
|
649
|
+
# This functionality is considered **unstable**. It may be changed
|
|
650
|
+
# at any point without it being considered a breaking change.
|
|
651
|
+
#
|
|
652
|
+
# @example Select all list columns:
|
|
653
|
+
# df = Polars::DataFrame.new(
|
|
654
|
+
# {
|
|
655
|
+
# "foo" => [["xx", "yy"], ["x"]],
|
|
656
|
+
# "bar" => [123, 456],
|
|
657
|
+
# "baz" => [2.0, 5.5]
|
|
658
|
+
# }
|
|
659
|
+
# )
|
|
660
|
+
# df.select(Polars.cs.list)
|
|
661
|
+
# # =>
|
|
662
|
+
# # shape: (2, 1)
|
|
663
|
+
# # ┌──────────────┐
|
|
664
|
+
# # │ foo │
|
|
665
|
+
# # │ --- │
|
|
666
|
+
# # │ list[str] │
|
|
667
|
+
# # ╞══════════════╡
|
|
668
|
+
# # │ ["xx", "yy"] │
|
|
669
|
+
# # │ ["x"] │
|
|
670
|
+
# # └──────────────┘
|
|
671
|
+
#
|
|
672
|
+
# @example Select all columns *except* for those that are list:
|
|
673
|
+
# df.select(~Polars.cs.list)
|
|
674
|
+
# # =>
|
|
675
|
+
# # shape: (2, 2)
|
|
676
|
+
# # ┌─────┬─────┐
|
|
677
|
+
# # │ bar ┆ baz │
|
|
678
|
+
# # │ --- ┆ --- │
|
|
679
|
+
# # │ i64 ┆ f64 │
|
|
680
|
+
# # ╞═════╪═════╡
|
|
681
|
+
# # │ 123 ┆ 2.0 │
|
|
682
|
+
# # │ 456 ┆ 5.5 │
|
|
683
|
+
# # └─────┴─────┘
|
|
684
|
+
#
|
|
685
|
+
# @example Select all list columns with a certain matching inner type:
|
|
686
|
+
# df.select(Polars.cs.list(Polars.cs.string))
|
|
687
|
+
# # =>
|
|
688
|
+
# # shape: (2, 1)
|
|
689
|
+
# # ┌──────────────┐
|
|
690
|
+
# # │ foo │
|
|
691
|
+
# # │ --- │
|
|
692
|
+
# # │ list[str] │
|
|
693
|
+
# # ╞══════════════╡
|
|
694
|
+
# # │ ["xx", "yy"] │
|
|
695
|
+
# # │ ["x"] │
|
|
696
|
+
# # └──────────────┘
|
|
697
|
+
#
|
|
698
|
+
# @example
|
|
699
|
+
# df.select(Polars.cs.list(Polars.cs.integer))
|
|
700
|
+
# # =>
|
|
701
|
+
# # shape: (0, 0)
|
|
702
|
+
# # ┌┐
|
|
703
|
+
# # ╞╡
|
|
704
|
+
# # └┘
|
|
705
|
+
def self.list(inner = nil)
|
|
706
|
+
inner_s = !inner.nil? ? inner._rbselector : nil
|
|
707
|
+
Selector._from_rbselector(RbSelector.list(inner_s))
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
# Select all array columns.
|
|
711
|
+
#
|
|
712
|
+
# @return [Selector]
|
|
713
|
+
#
|
|
714
|
+
# @note
|
|
715
|
+
# This functionality is considered **unstable**. It may be changed
|
|
716
|
+
# at any point without it being considered a breaking change.
|
|
717
|
+
#
|
|
718
|
+
# @example Select all array columns:
|
|
719
|
+
# df = Polars::DataFrame.new(
|
|
720
|
+
# {
|
|
721
|
+
# "foo" => [["xx", "yy"], ["x", "y"]],
|
|
722
|
+
# "bar" => [123, 456],
|
|
723
|
+
# "baz" => [2.0, 5.5]
|
|
724
|
+
# },
|
|
725
|
+
# schema_overrides: {"foo" => Polars::Array.new(Polars::String, 2)}
|
|
726
|
+
# )
|
|
727
|
+
# df.select(Polars.cs.array)
|
|
728
|
+
# # =>
|
|
729
|
+
# # shape: (2, 1)
|
|
730
|
+
# # ┌───────────────┐
|
|
731
|
+
# # │ foo │
|
|
732
|
+
# # │ --- │
|
|
733
|
+
# # │ array[str, 2] │
|
|
734
|
+
# # ╞═══════════════╡
|
|
735
|
+
# # │ ["xx", "yy"] │
|
|
736
|
+
# # │ ["x", "y"] │
|
|
737
|
+
# # └───────────────┘
|
|
738
|
+
#
|
|
739
|
+
# @example Select all columns *except* for those that are array:
|
|
740
|
+
# df.select(~Polars.cs.array)
|
|
741
|
+
# # =>
|
|
742
|
+
# # shape: (2, 2)
|
|
743
|
+
# # ┌─────┬─────┐
|
|
744
|
+
# # │ bar ┆ baz │
|
|
745
|
+
# # │ --- ┆ --- │
|
|
746
|
+
# # │ i64 ┆ f64 │
|
|
747
|
+
# # ╞═════╪═════╡
|
|
748
|
+
# # │ 123 ┆ 2.0 │
|
|
749
|
+
# # │ 456 ┆ 5.5 │
|
|
750
|
+
# # └─────┴─────┘
|
|
751
|
+
#
|
|
752
|
+
# @example Select all array columns with a certain matching inner type:
|
|
753
|
+
# df.select(Polars.cs.array(Polars.cs.string))
|
|
754
|
+
# # =>
|
|
755
|
+
# # shape: (2, 1)
|
|
756
|
+
# # ┌───────────────┐
|
|
757
|
+
# # │ foo │
|
|
758
|
+
# # │ --- │
|
|
759
|
+
# # │ array[str, 2] │
|
|
760
|
+
# # ╞═══════════════╡
|
|
761
|
+
# # │ ["xx", "yy"] │
|
|
762
|
+
# # │ ["x", "y"] │
|
|
763
|
+
# # └───────────────┘
|
|
764
|
+
#
|
|
765
|
+
# @example
|
|
766
|
+
# df.select(Polars.cs.array(Polars.cs.integer))
|
|
767
|
+
# # =>
|
|
768
|
+
# # shape: (0, 0)
|
|
769
|
+
# # ┌┐
|
|
770
|
+
# # ╞╡
|
|
771
|
+
# # └┘
|
|
772
|
+
#
|
|
773
|
+
# @example
|
|
774
|
+
# df.select(Polars.cs.array(width: 2))
|
|
775
|
+
# # =>
|
|
776
|
+
# # shape: (2, 1)
|
|
777
|
+
# # ┌───────────────┐
|
|
778
|
+
# # │ foo │
|
|
779
|
+
# # │ --- │
|
|
780
|
+
# # │ array[str, 2] │
|
|
781
|
+
# # ╞═══════════════╡
|
|
782
|
+
# # │ ["xx", "yy"] │
|
|
783
|
+
# # │ ["x", "y"] │
|
|
784
|
+
# # └───────────────┘
|
|
785
|
+
#
|
|
786
|
+
# @example
|
|
787
|
+
# df.select(Polars.cs.array(width: 3))
|
|
788
|
+
# # =>
|
|
789
|
+
# # shape: (0, 0)
|
|
790
|
+
# # ┌┐
|
|
791
|
+
# # ╞╡
|
|
792
|
+
# # └┘
|
|
793
|
+
def self.array(inner = nil, width: nil)
|
|
794
|
+
inner_s = !inner.nil? ? inner._rbselector : nil
|
|
795
|
+
Selector._from_rbselector(RbSelector.array(inner_s, width))
|
|
796
|
+
end
|
|
370
797
|
|
|
371
|
-
#
|
|
372
|
-
#
|
|
373
|
-
#
|
|
798
|
+
# Select all struct columns.
|
|
799
|
+
#
|
|
800
|
+
# @return [Selector]
|
|
801
|
+
#
|
|
802
|
+
# @note
|
|
803
|
+
# This functionality is considered **unstable**. It may be changed
|
|
804
|
+
# at any point without it being considered a breaking change.
|
|
805
|
+
#
|
|
806
|
+
# @example Select all struct columns:
|
|
807
|
+
# df = Polars::DataFrame.new(
|
|
808
|
+
# {
|
|
809
|
+
# "foo" => [{"a" => "xx", "b" => "z"}, {"a" => "x", "b" => "y"}],
|
|
810
|
+
# "bar" => [123, 456],
|
|
811
|
+
# "baz" => [2.0, 5.5]
|
|
812
|
+
# }
|
|
813
|
+
# )
|
|
814
|
+
# df.select(Polars.cs.struct)
|
|
815
|
+
# # =>
|
|
816
|
+
# # shape: (2, 1)
|
|
817
|
+
# # ┌────────────┐
|
|
818
|
+
# # │ foo │
|
|
819
|
+
# # │ --- │
|
|
820
|
+
# # │ struct[2] │
|
|
821
|
+
# # ╞════════════╡
|
|
822
|
+
# # │ {"xx","z"} │
|
|
823
|
+
# # │ {"x","y"} │
|
|
824
|
+
# # └────────────┘
|
|
825
|
+
#
|
|
826
|
+
# @example Select all columns *except* for those that are struct:
|
|
827
|
+
# df.select(~Polars.cs.struct)
|
|
828
|
+
# # =>
|
|
829
|
+
# # shape: (2, 2)
|
|
830
|
+
# # ┌─────┬─────┐
|
|
831
|
+
# # │ bar ┆ baz │
|
|
832
|
+
# # │ --- ┆ --- │
|
|
833
|
+
# # │ i64 ┆ f64 │
|
|
834
|
+
# # ╞═════╪═════╡
|
|
835
|
+
# # │ 123 ┆ 2.0 │
|
|
836
|
+
# # │ 456 ┆ 5.5 │
|
|
837
|
+
# # └─────┴─────┘
|
|
838
|
+
def self.struct
|
|
839
|
+
Selector._from_rbselector(RbSelector.struct_)
|
|
840
|
+
end
|
|
374
841
|
|
|
375
|
-
#
|
|
376
|
-
#
|
|
377
|
-
#
|
|
842
|
+
# Select all nested columns.
|
|
843
|
+
#
|
|
844
|
+
# A nested column is a list, array or struct.
|
|
845
|
+
#
|
|
846
|
+
# @return [Selector]
|
|
847
|
+
#
|
|
848
|
+
# @note
|
|
849
|
+
# This functionality is considered **unstable**. It may be changed
|
|
850
|
+
# at any point without it being considered a breaking change.
|
|
851
|
+
#
|
|
852
|
+
# @example Select all nested columns:
|
|
853
|
+
# df = Polars::DataFrame.new(
|
|
854
|
+
# {
|
|
855
|
+
# "foo" => [{"a" => "xx", "b" => "z"}, {"a" => "x", "b" => "y"}],
|
|
856
|
+
# "bar" => [123, 456],
|
|
857
|
+
# "baz" => [2.0, 5.5],
|
|
858
|
+
# "wow" => [[1, 2], [3]]
|
|
859
|
+
# }
|
|
860
|
+
# )
|
|
861
|
+
# df.select(Polars.cs.nested)
|
|
862
|
+
# # =>
|
|
863
|
+
# # shape: (2, 2)
|
|
864
|
+
# # ┌────────────┬───────────┐
|
|
865
|
+
# # │ foo ┆ wow │
|
|
866
|
+
# # │ --- ┆ --- │
|
|
867
|
+
# # │ struct[2] ┆ list[i64] │
|
|
868
|
+
# # ╞════════════╪═══════════╡
|
|
869
|
+
# # │ {"xx","z"} ┆ [1, 2] │
|
|
870
|
+
# # │ {"x","y"} ┆ [3] │
|
|
871
|
+
# # └────────────┴───────────┘
|
|
872
|
+
#
|
|
873
|
+
# @example Select all columns *except* for those that are nested:
|
|
874
|
+
# df.select(~Polars.cs.nested)
|
|
875
|
+
# # =>
|
|
876
|
+
# # shape: (2, 2)
|
|
877
|
+
# # ┌─────┬─────┐
|
|
878
|
+
# # │ bar ┆ baz │
|
|
879
|
+
# # │ --- ┆ --- │
|
|
880
|
+
# # │ i64 ┆ f64 │
|
|
881
|
+
# # ╞═════╪═════╡
|
|
882
|
+
# # │ 123 ┆ 2.0 │
|
|
883
|
+
# # │ 456 ┆ 5.5 │
|
|
884
|
+
# # └─────┴─────┘
|
|
885
|
+
def self.nested
|
|
886
|
+
Selector._from_rbselector(RbSelector.nested)
|
|
887
|
+
end
|
|
378
888
|
|
|
379
889
|
# Select all categorical columns.
|
|
380
890
|
#
|
|
381
|
-
# @return [
|
|
891
|
+
# @return [Selector]
|
|
382
892
|
#
|
|
383
893
|
# @example
|
|
384
894
|
# df = Polars::DataFrame.new(
|
|
@@ -416,7 +926,7 @@ module Polars
|
|
|
416
926
|
# # │ 456 ┆ 5.5 │
|
|
417
927
|
# # └─────┴─────┘
|
|
418
928
|
def self.categorical
|
|
419
|
-
|
|
929
|
+
Selector._from_rbselector(RbSelector.categorical)
|
|
420
930
|
end
|
|
421
931
|
|
|
422
932
|
# Select columns whose names contain the given literal substring(s).
|
|
@@ -424,7 +934,7 @@ module Polars
|
|
|
424
934
|
# @param substring [Object]
|
|
425
935
|
# Substring(s) that matching column names should contain.
|
|
426
936
|
#
|
|
427
|
-
# @return [
|
|
937
|
+
# @return [Selector]
|
|
428
938
|
#
|
|
429
939
|
# @example
|
|
430
940
|
# df = Polars::DataFrame.new(
|
|
@@ -478,16 +988,12 @@ module Polars
|
|
|
478
988
|
escaped_substring = _re_string(substring)
|
|
479
989
|
raw_params = "^.*#{escaped_substring}.*$"
|
|
480
990
|
|
|
481
|
-
|
|
482
|
-
F.col(raw_params),
|
|
483
|
-
name: "contains",
|
|
484
|
-
parameters: {"*substring" => escaped_substring}
|
|
485
|
-
)
|
|
991
|
+
Selector._from_rbselector(RbSelector.matches(raw_params))
|
|
486
992
|
end
|
|
487
993
|
|
|
488
994
|
# Select all date columns.
|
|
489
995
|
#
|
|
490
|
-
# @return [
|
|
996
|
+
# @return [Selector]
|
|
491
997
|
#
|
|
492
998
|
# @example
|
|
493
999
|
# df = Polars::DataFrame.new(
|
|
@@ -523,16 +1029,41 @@ module Polars
|
|
|
523
1029
|
# # │ 2031-12-31 00:30:00 │
|
|
524
1030
|
# # └─────────────────────┘
|
|
525
1031
|
def self.date
|
|
526
|
-
|
|
1032
|
+
by_dtype([Date])
|
|
527
1033
|
end
|
|
528
1034
|
|
|
529
|
-
#
|
|
530
|
-
#
|
|
531
|
-
#
|
|
1035
|
+
# Select all datetime columns, optionally filtering by time unit/zone.
|
|
1036
|
+
#
|
|
1037
|
+
# @param time_unit ['ms', 'us', 'ns']
|
|
1038
|
+
# One (or more) of the allowed timeunit precision strings, "ms", "us", and "ns".
|
|
1039
|
+
# Omit to select columns with any valid timeunit.
|
|
1040
|
+
# @param time_zone [String]
|
|
1041
|
+
# * One or more timezone strings, as defined in zoneinfo (to see valid options
|
|
1042
|
+
# run `import zoneinfo; zoneinfo.available_timezones()` for a full list).
|
|
1043
|
+
# * Set `nil` to select Datetime columns that do not have a timezone.
|
|
1044
|
+
# * Set "*" to select Datetime columns that have *any* timezone.
|
|
1045
|
+
#
|
|
1046
|
+
# @return [Selector]
|
|
1047
|
+
def self.datetime(time_unit = nil, time_zone: ["*", nil])
|
|
1048
|
+
if time_unit.nil?
|
|
1049
|
+
time_unit_lst = ["ms", "us", "ns"]
|
|
1050
|
+
else
|
|
1051
|
+
time_unit_lst = time_unit.is_a?(::String) ? [time_unit] : time_unit.to_a
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
if time_zone.nil?
|
|
1055
|
+
time_zone_lst = [nil]
|
|
1056
|
+
elsif time_zone
|
|
1057
|
+
# TODO improve
|
|
1058
|
+
time_zone_lst = time_zone.to_a
|
|
1059
|
+
end
|
|
1060
|
+
|
|
1061
|
+
Selector._from_rbselector(RbSelector.datetime(time_unit_lst, time_zone_lst))
|
|
1062
|
+
end
|
|
532
1063
|
|
|
533
1064
|
# Select all decimal columns.
|
|
534
1065
|
#
|
|
535
|
-
# @return [
|
|
1066
|
+
# @return [Selector]
|
|
536
1067
|
#
|
|
537
1068
|
# @example
|
|
538
1069
|
# df = Polars::DataFrame.new(
|
|
@@ -548,14 +1079,14 @@ module Polars
|
|
|
548
1079
|
# df.select(Polars.cs.decimal)
|
|
549
1080
|
# # =>
|
|
550
1081
|
# # shape: (2, 2)
|
|
551
|
-
# #
|
|
552
|
-
# # │ bar
|
|
553
|
-
# # │ ---
|
|
554
|
-
# # │ decimal[
|
|
555
|
-
# #
|
|
556
|
-
# # │ 123
|
|
557
|
-
# # │ 456
|
|
558
|
-
# #
|
|
1082
|
+
# # ┌───────────────┬───────────────┐
|
|
1083
|
+
# # │ bar ┆ baz │
|
|
1084
|
+
# # │ --- ┆ --- │
|
|
1085
|
+
# # │ decimal[38,0] ┆ decimal[10,5] │
|
|
1086
|
+
# # ╞═══════════════╪═══════════════╡
|
|
1087
|
+
# # │ 123 ┆ 2.00050 │
|
|
1088
|
+
# # │ 456 ┆ -50.55550 │
|
|
1089
|
+
# # └───────────────┴───────────────┘
|
|
559
1090
|
#
|
|
560
1091
|
# @example Select all columns *except* the decimal ones:
|
|
561
1092
|
#
|
|
@@ -572,7 +1103,112 @@ module Polars
|
|
|
572
1103
|
# # └─────┘
|
|
573
1104
|
def self.decimal
|
|
574
1105
|
# TODO: allow explicit selection by scale/precision?
|
|
575
|
-
|
|
1106
|
+
Selector._from_rbselector(RbSelector.decimal)
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
# Select all columns having names consisting only of digits.
|
|
1110
|
+
#
|
|
1111
|
+
# @return [Selector]
|
|
1112
|
+
#
|
|
1113
|
+
# @note
|
|
1114
|
+
# Matching column names cannot contain *any* non-digit characters. Note that the
|
|
1115
|
+
# definition of "digit" consists of all valid Unicode digit characters (`\d`)
|
|
1116
|
+
# by default; this can be changed by setting `ascii_only: true`.
|
|
1117
|
+
#
|
|
1118
|
+
# @example
|
|
1119
|
+
# df = Polars::DataFrame.new(
|
|
1120
|
+
# {
|
|
1121
|
+
# "key" => ["aaa", "bbb", "aaa", "bbb", "bbb"],
|
|
1122
|
+
# "year" => [2001, 2001, 2025, 2025, 2001],
|
|
1123
|
+
# "value" => [-25, 100, 75, -15, -5]
|
|
1124
|
+
# }
|
|
1125
|
+
# ).pivot(
|
|
1126
|
+
# "year",
|
|
1127
|
+
# values: "value",
|
|
1128
|
+
# index: "key",
|
|
1129
|
+
# aggregate_function: "sum"
|
|
1130
|
+
# )
|
|
1131
|
+
# # =>
|
|
1132
|
+
# # shape: (2, 3)
|
|
1133
|
+
# # ┌─────┬──────┬──────┐
|
|
1134
|
+
# # │ key ┆ 2001 ┆ 2025 │
|
|
1135
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1136
|
+
# # │ str ┆ i64 ┆ i64 │
|
|
1137
|
+
# # ╞═════╪══════╪══════╡
|
|
1138
|
+
# # │ aaa ┆ -25 ┆ 75 │
|
|
1139
|
+
# # │ bbb ┆ 95 ┆ -15 │
|
|
1140
|
+
# # └─────┴──────┴──────┘
|
|
1141
|
+
#
|
|
1142
|
+
# @example Select columns with digit names:
|
|
1143
|
+
# df.select(Polars.cs.digit)
|
|
1144
|
+
# # =>
|
|
1145
|
+
# # shape: (2, 2)
|
|
1146
|
+
# # ┌──────┬──────┐
|
|
1147
|
+
# # │ 2001 ┆ 2025 │
|
|
1148
|
+
# # │ --- ┆ --- │
|
|
1149
|
+
# # │ i64 ┆ i64 │
|
|
1150
|
+
# # ╞══════╪══════╡
|
|
1151
|
+
# # │ -25 ┆ 75 │
|
|
1152
|
+
# # │ 95 ┆ -15 │
|
|
1153
|
+
# # └──────┴──────┘
|
|
1154
|
+
#
|
|
1155
|
+
# @example Select all columns *except* for those with digit names:
|
|
1156
|
+
# df.select(~Polars.cs.digit)
|
|
1157
|
+
# # =>
|
|
1158
|
+
# # shape: (2, 1)
|
|
1159
|
+
# # ┌─────┐
|
|
1160
|
+
# # │ key │
|
|
1161
|
+
# # │ --- │
|
|
1162
|
+
# # │ str │
|
|
1163
|
+
# # ╞═════╡
|
|
1164
|
+
# # │ aaa │
|
|
1165
|
+
# # │ bbb │
|
|
1166
|
+
# # └─────┘
|
|
1167
|
+
#
|
|
1168
|
+
# @example Demonstrate use of `ascii_only` flag (by default all valid unicode digits are considered, but this can be constrained to ascii 0-9):
|
|
1169
|
+
# df = Polars::DataFrame.new({"१९९९" => [1999], "२०७७" => [2077], "3000": [3000]})
|
|
1170
|
+
# df.select(Polars.cs.digit)
|
|
1171
|
+
# # =>
|
|
1172
|
+
# # shape: (1, 3)
|
|
1173
|
+
# # ┌──────┬──────┬──────┐
|
|
1174
|
+
# # │ १९९९ ┆ २०७७ ┆ 3000 │
|
|
1175
|
+
# # │ --- ┆ --- ┆ --- │
|
|
1176
|
+
# # │ i64 ┆ i64 ┆ i64 │
|
|
1177
|
+
# # ╞══════╪══════╪══════╡
|
|
1178
|
+
# # │ 1999 ┆ 2077 ┆ 3000 │
|
|
1179
|
+
# # └──────┴──────┴──────┘
|
|
1180
|
+
#
|
|
1181
|
+
# @example
|
|
1182
|
+
# df.select(Polars.cs.digit(ascii_only: true))
|
|
1183
|
+
# # =>
|
|
1184
|
+
# # shape: (1, 1)
|
|
1185
|
+
# # ┌──────┐
|
|
1186
|
+
# # │ 3000 │
|
|
1187
|
+
# # │ --- │
|
|
1188
|
+
# # │ i64 │
|
|
1189
|
+
# # ╞══════╡
|
|
1190
|
+
# # │ 3000 │
|
|
1191
|
+
# # └──────┘
|
|
1192
|
+
def self.digit(ascii_only: false)
|
|
1193
|
+
re_digit = ascii_only ? "[0-9]" : "\\d"
|
|
1194
|
+
Selector._from_rbselector(RbSelector.matches("^#{re_digit}+$"))
|
|
1195
|
+
end
|
|
1196
|
+
|
|
1197
|
+
# Select all duration columns, optionally filtering by time unit.
|
|
1198
|
+
#
|
|
1199
|
+
# @param time_unit ['ms', 'us', 'ns']
|
|
1200
|
+
# One (or more) of the allowed timeunit precision strings, "ms", "us", and "ns".
|
|
1201
|
+
# Omit to select columns with any valid timeunit.
|
|
1202
|
+
#
|
|
1203
|
+
# @return [Selector]
|
|
1204
|
+
def self.duration(time_unit = nil)
|
|
1205
|
+
if time_unit.nil?
|
|
1206
|
+
time_unit = ["ms", "us", "ns"]
|
|
1207
|
+
else
|
|
1208
|
+
time_unit = time_unit.is_a?(::String) ? [time_unit] : time_unit.to_a
|
|
1209
|
+
end
|
|
1210
|
+
|
|
1211
|
+
Selector._from_rbselector(RbSelector.duration(time_unit))
|
|
576
1212
|
end
|
|
577
1213
|
|
|
578
1214
|
# Select columns that end with the given substring(s).
|
|
@@ -580,7 +1216,7 @@ module Polars
|
|
|
580
1216
|
# @param suffix [Object]
|
|
581
1217
|
# Substring(s) that matching column names should end with.
|
|
582
1218
|
#
|
|
583
|
-
# @return [
|
|
1219
|
+
# @return [Selector]
|
|
584
1220
|
#
|
|
585
1221
|
# @example
|
|
586
1222
|
# df = Polars::DataFrame.new(
|
|
@@ -634,16 +1270,64 @@ module Polars
|
|
|
634
1270
|
escaped_suffix = _re_string(suffix)
|
|
635
1271
|
raw_params = "^.*#{escaped_suffix}$"
|
|
636
1272
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
1273
|
+
Selector._from_rbselector(RbSelector.matches(raw_params))
|
|
1274
|
+
end
|
|
1275
|
+
|
|
1276
|
+
# Select all columns except those matching the given columns, datatypes, or selectors.
|
|
1277
|
+
#
|
|
1278
|
+
# @param columns [Object]
|
|
1279
|
+
# One or more columns (col or name), datatypes, columns, or selectors representing
|
|
1280
|
+
# the columns to exclude.
|
|
1281
|
+
# @param more_columns [Array]
|
|
1282
|
+
# Additional columns, datatypes, or selectors to exclude, specified as positional
|
|
1283
|
+
# arguments.
|
|
1284
|
+
#
|
|
1285
|
+
# @return [Selector]
|
|
1286
|
+
#
|
|
1287
|
+
# @note
|
|
1288
|
+
# If excluding a single selector it is simpler to write as `~selector` instead.
|
|
1289
|
+
#
|
|
1290
|
+
# @example Exclude by column name(s):
|
|
1291
|
+
# df = Polars::DataFrame.new(
|
|
1292
|
+
# {
|
|
1293
|
+
# "aa" => [1, 2, 3],
|
|
1294
|
+
# "ba" => ["a", "b", nil],
|
|
1295
|
+
# "cc" => [nil, 2.5, 1.5]
|
|
1296
|
+
# }
|
|
1297
|
+
# )
|
|
1298
|
+
# df.select(Polars.cs.exclude("ba", "xx"))
|
|
1299
|
+
# # =>
|
|
1300
|
+
# # shape: (3, 2)
|
|
1301
|
+
# # ┌─────┬──────┐
|
|
1302
|
+
# # │ aa ┆ cc │
|
|
1303
|
+
# # │ --- ┆ --- │
|
|
1304
|
+
# # │ i64 ┆ f64 │
|
|
1305
|
+
# # ╞═════╪══════╡
|
|
1306
|
+
# # │ 1 ┆ null │
|
|
1307
|
+
# # │ 2 ┆ 2.5 │
|
|
1308
|
+
# # │ 3 ┆ 1.5 │
|
|
1309
|
+
# # └─────┴──────┘
|
|
1310
|
+
#
|
|
1311
|
+
# @example Exclude using a column name, a selector, and a dtype:
|
|
1312
|
+
# df.select(Polars.cs.exclude("aa", Polars.cs.string, Polars::UInt32))
|
|
1313
|
+
# # =>
|
|
1314
|
+
# # shape: (3, 1)
|
|
1315
|
+
# # ┌──────┐
|
|
1316
|
+
# # │ cc │
|
|
1317
|
+
# # │ --- │
|
|
1318
|
+
# # │ f64 │
|
|
1319
|
+
# # ╞══════╡
|
|
1320
|
+
# # │ null │
|
|
1321
|
+
# # │ 2.5 │
|
|
1322
|
+
# # │ 1.5 │
|
|
1323
|
+
# # └──────┘
|
|
1324
|
+
def self.exclude(columns, *more_columns)
|
|
1325
|
+
~_combine_as_selector(columns, *more_columns)
|
|
642
1326
|
end
|
|
643
1327
|
|
|
644
1328
|
# Select the first column in the current scope.
|
|
645
1329
|
#
|
|
646
|
-
# @return [
|
|
1330
|
+
# @return [Selector]
|
|
647
1331
|
#
|
|
648
1332
|
# @example
|
|
649
1333
|
# df = Polars::DataFrame.new(
|
|
@@ -680,13 +1364,13 @@ module Polars
|
|
|
680
1364
|
# # │ 123 ┆ 2.0 ┆ 0 │
|
|
681
1365
|
# # │ 456 ┆ 5.5 ┆ 1 │
|
|
682
1366
|
# # └─────┴─────┴─────┘
|
|
683
|
-
def self.first
|
|
684
|
-
|
|
1367
|
+
def self.first(strict: true)
|
|
1368
|
+
Selector._from_rbselector(RbSelector.first(strict))
|
|
685
1369
|
end
|
|
686
1370
|
|
|
687
1371
|
# Select all float columns.
|
|
688
1372
|
#
|
|
689
|
-
# @return [
|
|
1373
|
+
# @return [Selector]
|
|
690
1374
|
#
|
|
691
1375
|
# @example
|
|
692
1376
|
# df = Polars::DataFrame.new(
|
|
@@ -725,12 +1409,12 @@ module Polars
|
|
|
725
1409
|
# # │ y ┆ 456 │
|
|
726
1410
|
# # └─────┴─────┘
|
|
727
1411
|
def self.float
|
|
728
|
-
|
|
1412
|
+
Selector._from_rbselector(RbSelector.float)
|
|
729
1413
|
end
|
|
730
1414
|
|
|
731
1415
|
# Select all integer columns.
|
|
732
1416
|
#
|
|
733
|
-
# @return [
|
|
1417
|
+
# @return [Selector]
|
|
734
1418
|
#
|
|
735
1419
|
# @example
|
|
736
1420
|
# df = Polars::DataFrame.new(
|
|
@@ -768,12 +1452,12 @@ module Polars
|
|
|
768
1452
|
# # │ y ┆ 5.5 │
|
|
769
1453
|
# # └─────┴─────┘
|
|
770
1454
|
def self.integer
|
|
771
|
-
|
|
1455
|
+
Selector._from_rbselector(RbSelector.integer)
|
|
772
1456
|
end
|
|
773
1457
|
|
|
774
1458
|
# Select all signed integer columns.
|
|
775
1459
|
#
|
|
776
|
-
# @return [
|
|
1460
|
+
# @return [Selector]
|
|
777
1461
|
#
|
|
778
1462
|
# @example
|
|
779
1463
|
# df = Polars::DataFrame.new(
|
|
@@ -825,12 +1509,12 @@ module Polars
|
|
|
825
1509
|
# # │ -456 ┆ 6789 ┆ 4321 │
|
|
826
1510
|
# # └──────┴──────┴──────┘
|
|
827
1511
|
def self.signed_integer
|
|
828
|
-
|
|
1512
|
+
Selector._from_rbselector(RbSelector.signed_integer)
|
|
829
1513
|
end
|
|
830
1514
|
|
|
831
1515
|
# Select all unsigned integer columns.
|
|
832
1516
|
#
|
|
833
|
-
# @return [
|
|
1517
|
+
# @return [Selector]
|
|
834
1518
|
#
|
|
835
1519
|
# @example
|
|
836
1520
|
# df = Polars::DataFrame.new(
|
|
@@ -882,12 +1566,12 @@ module Polars
|
|
|
882
1566
|
# # │ -456 ┆ 6789 ┆ 4321 │
|
|
883
1567
|
# # └──────┴──────┴──────┘
|
|
884
1568
|
def self.unsigned_integer
|
|
885
|
-
|
|
1569
|
+
Selector._from_rbselector(RbSelector.unsigned_integer)
|
|
886
1570
|
end
|
|
887
1571
|
|
|
888
1572
|
# Select the last column in the current scope.
|
|
889
1573
|
#
|
|
890
|
-
# @return [
|
|
1574
|
+
# @return [Selector]
|
|
891
1575
|
#
|
|
892
1576
|
# @example
|
|
893
1577
|
# df = Polars::DataFrame.new(
|
|
@@ -924,13 +1608,71 @@ module Polars
|
|
|
924
1608
|
# # │ x ┆ 123 ┆ 2.0 │
|
|
925
1609
|
# # │ y ┆ 456 ┆ 5.5 │
|
|
926
1610
|
# # └─────┴─────┴─────┘
|
|
927
|
-
def self.last
|
|
928
|
-
|
|
1611
|
+
def self.last(strict: true)
|
|
1612
|
+
Selector._from_rbselector(RbSelector.last(strict))
|
|
1613
|
+
end
|
|
1614
|
+
|
|
1615
|
+
# Select all columns that match the given regex pattern.
|
|
1616
|
+
#
|
|
1617
|
+
# @param pattern [String]
|
|
1618
|
+
# A valid regular expression pattern, compatible with the [regex crate](https://docs.rs/regex/latest/regex/).
|
|
1619
|
+
#
|
|
1620
|
+
# @return [Selector]
|
|
1621
|
+
#
|
|
1622
|
+
# @example Match column names containing an 'a', preceded by a character that is not 'z':
|
|
1623
|
+
# df = Polars::DataFrame.new(
|
|
1624
|
+
# {
|
|
1625
|
+
# "foo" => ["x", "y"],
|
|
1626
|
+
# "bar" => [123, 456],
|
|
1627
|
+
# "baz" => [2.0, 5.5],
|
|
1628
|
+
# "zap" => [0, 1]
|
|
1629
|
+
# }
|
|
1630
|
+
# )
|
|
1631
|
+
# df.select(Polars.cs.matches("[^z]a"))
|
|
1632
|
+
# # =>
|
|
1633
|
+
# # shape: (2, 2)
|
|
1634
|
+
# # ┌─────┬─────┐
|
|
1635
|
+
# # │ bar ┆ baz │
|
|
1636
|
+
# # │ --- ┆ --- │
|
|
1637
|
+
# # │ i64 ┆ f64 │
|
|
1638
|
+
# # ╞═════╪═════╡
|
|
1639
|
+
# # │ 123 ┆ 2.0 │
|
|
1640
|
+
# # │ 456 ┆ 5.5 │
|
|
1641
|
+
# # └─────┴─────┘
|
|
1642
|
+
#
|
|
1643
|
+
# @example Do not match column names ending in 'R' or 'z' (case-insensitively):
|
|
1644
|
+
# df.select(~Polars.cs.matches("(?i)R|z$"))
|
|
1645
|
+
# # =>
|
|
1646
|
+
# # shape: (2, 2)
|
|
1647
|
+
# # ┌─────┬─────┐
|
|
1648
|
+
# # │ foo ┆ zap │
|
|
1649
|
+
# # │ --- ┆ --- │
|
|
1650
|
+
# # │ str ┆ i64 │
|
|
1651
|
+
# # ╞═════╪═════╡
|
|
1652
|
+
# # │ x ┆ 0 │
|
|
1653
|
+
# # │ y ┆ 1 │
|
|
1654
|
+
# # └─────┴─────┘
|
|
1655
|
+
def self.matches(pattern)
|
|
1656
|
+
if pattern == ".*"
|
|
1657
|
+
all
|
|
1658
|
+
else
|
|
1659
|
+
if pattern.start_with?(".*")
|
|
1660
|
+
pattern = pattern[2..]
|
|
1661
|
+
elsif pattern.end_with?(".*")
|
|
1662
|
+
pattern = pattern[..-3]
|
|
1663
|
+
end
|
|
1664
|
+
|
|
1665
|
+
pfx = !pattern.start_with?("^") ? "^.*" : ""
|
|
1666
|
+
sfx = !pattern.end_with?("$") ? ".*$" : ""
|
|
1667
|
+
raw_params = "#{pfx}#{pattern}#{sfx}"
|
|
1668
|
+
|
|
1669
|
+
Selector._from_rbselector(RbSelector.matches(raw_params))
|
|
1670
|
+
end
|
|
929
1671
|
end
|
|
930
1672
|
|
|
931
1673
|
# Select all numeric columns.
|
|
932
1674
|
#
|
|
933
|
-
# @return [
|
|
1675
|
+
# @return [Selector]
|
|
934
1676
|
#
|
|
935
1677
|
# @example
|
|
936
1678
|
# df = Polars::DataFrame.new(
|
|
@@ -969,7 +1711,26 @@ module Polars
|
|
|
969
1711
|
# # │ y │
|
|
970
1712
|
# # └─────┘
|
|
971
1713
|
def self.numeric
|
|
972
|
-
|
|
1714
|
+
Selector._from_rbselector(RbSelector.numeric)
|
|
1715
|
+
end
|
|
1716
|
+
|
|
1717
|
+
# Select all object columns.
|
|
1718
|
+
#
|
|
1719
|
+
# @return [Selector]
|
|
1720
|
+
#
|
|
1721
|
+
# @example
|
|
1722
|
+
# df = Polars::DataFrame.new(
|
|
1723
|
+
# {
|
|
1724
|
+
# "idx" => [0, 1],
|
|
1725
|
+
# "uuid_obj" => ["6be063cf-c9c6-43be-878e-e446cfd42981", "7849d8f9-2cac-48e7-96d3-63cf81c14869"],
|
|
1726
|
+
# "uuid_str" => ["acab9fea-c05d-4b91-b639-418004a63f33", "28c65415-8b7d-4857-a4ce-300dca14b12b"]
|
|
1727
|
+
# },
|
|
1728
|
+
# schema_overrides: {"idx" => Polars::Int32, "uuid_obj" => Polars::Object}
|
|
1729
|
+
# )
|
|
1730
|
+
# df.select(Polars.cs.object).to_h(as_series: false)
|
|
1731
|
+
# # => {"uuid_obj"=>["6be063cf-c9c6-43be-878e-e446cfd42981", "7849d8f9-2cac-48e7-96d3-63cf81c14869"]}
|
|
1732
|
+
def self.object
|
|
1733
|
+
Selector._from_rbselector(RbSelector.object)
|
|
973
1734
|
end
|
|
974
1735
|
|
|
975
1736
|
# Select columns that start with the given substring(s).
|
|
@@ -977,7 +1738,7 @@ module Polars
|
|
|
977
1738
|
# @param prefix [Object]
|
|
978
1739
|
# Substring(s) that matching column names should start with.
|
|
979
1740
|
#
|
|
980
|
-
# @return [
|
|
1741
|
+
# @return [Selector]
|
|
981
1742
|
#
|
|
982
1743
|
# @example
|
|
983
1744
|
# df = Polars::DataFrame.new(
|
|
@@ -1031,16 +1792,12 @@ module Polars
|
|
|
1031
1792
|
escaped_prefix = _re_string(prefix)
|
|
1032
1793
|
raw_params = "^#{escaped_prefix}.*$"
|
|
1033
1794
|
|
|
1034
|
-
|
|
1035
|
-
F.col(raw_params),
|
|
1036
|
-
name: "starts_with",
|
|
1037
|
-
parameters: {"*prefix" => prefix}
|
|
1038
|
-
)
|
|
1795
|
+
Selector._from_rbselector(RbSelector.matches(raw_params))
|
|
1039
1796
|
end
|
|
1040
1797
|
|
|
1041
1798
|
# Select all String (and, optionally, Categorical) string columns.
|
|
1042
1799
|
#
|
|
1043
|
-
# @return [
|
|
1800
|
+
# @return [Selector]
|
|
1044
1801
|
#
|
|
1045
1802
|
# @example
|
|
1046
1803
|
# df = Polars::DataFrame.new(
|
|
@@ -1087,16 +1844,66 @@ module Polars
|
|
|
1087
1844
|
string_dtypes << Categorical
|
|
1088
1845
|
end
|
|
1089
1846
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1847
|
+
by_dtype(string_dtypes)
|
|
1848
|
+
end
|
|
1849
|
+
|
|
1850
|
+
# Select all temporal columns.
|
|
1851
|
+
#
|
|
1852
|
+
# @return [Selector]
|
|
1853
|
+
#
|
|
1854
|
+
# @example Match all temporal columns:
|
|
1855
|
+
# df = Polars::DataFrame.new(
|
|
1856
|
+
# {
|
|
1857
|
+
# "dt" => [Date.new(2021, 1, 1), Date.new(2021, 1, 2)],
|
|
1858
|
+
# "tm" => [DateTime.new(2000, 1, 1, 12, 0, 0), DateTime.new(2000, 1, 1, 20, 30, 45)],
|
|
1859
|
+
# "value" => [1.2345, 2.3456],
|
|
1860
|
+
# },
|
|
1861
|
+
# schema_overrides: {"tm" => Polars::Time}
|
|
1862
|
+
# )
|
|
1863
|
+
# df.select(Polars.cs.temporal)
|
|
1864
|
+
# # =>
|
|
1865
|
+
# # shape: (2, 2)
|
|
1866
|
+
# # ┌────────────┬──────────┐
|
|
1867
|
+
# # │ dt ┆ tm │
|
|
1868
|
+
# # │ --- ┆ --- │
|
|
1869
|
+
# # │ date ┆ time │
|
|
1870
|
+
# # ╞════════════╪══════════╡
|
|
1871
|
+
# # │ 2021-01-01 ┆ 12:00:00 │
|
|
1872
|
+
# # │ 2021-01-02 ┆ 20:30:45 │
|
|
1873
|
+
# # └────────────┴──────────┘
|
|
1874
|
+
#
|
|
1875
|
+
# @example Match all temporal columns *except* for time columns:
|
|
1876
|
+
# df.select(Polars.cs.temporal - Polars.cs.time)
|
|
1877
|
+
# # =>
|
|
1878
|
+
# # shape: (2, 1)
|
|
1879
|
+
# # ┌────────────┐
|
|
1880
|
+
# # │ dt │
|
|
1881
|
+
# # │ --- │
|
|
1882
|
+
# # │ date │
|
|
1883
|
+
# # ╞════════════╡
|
|
1884
|
+
# # │ 2021-01-01 │
|
|
1885
|
+
# # │ 2021-01-02 │
|
|
1886
|
+
# # └────────────┘
|
|
1887
|
+
#
|
|
1888
|
+
# @example Match all columns *except* for temporal columns:
|
|
1889
|
+
# df.select(~Polars.cs.temporal)
|
|
1890
|
+
# # =>
|
|
1891
|
+
# # shape: (2, 1)
|
|
1892
|
+
# # ┌────────┐
|
|
1893
|
+
# # │ value │
|
|
1894
|
+
# # │ --- │
|
|
1895
|
+
# # │ f64 │
|
|
1896
|
+
# # ╞════════╡
|
|
1897
|
+
# # │ 1.2345 │
|
|
1898
|
+
# # │ 2.3456 │
|
|
1899
|
+
# # └────────┘
|
|
1900
|
+
def self.temporal
|
|
1901
|
+
Selector._from_rbselector(RbSelector.temporal)
|
|
1095
1902
|
end
|
|
1096
1903
|
|
|
1097
1904
|
# Select all time columns.
|
|
1098
1905
|
#
|
|
1099
|
-
# @return [
|
|
1906
|
+
# @return [Selector]
|
|
1100
1907
|
#
|
|
1101
1908
|
# @example
|
|
1102
1909
|
# df = Polars::DataFrame.new(
|
|
@@ -1134,11 +1941,51 @@ module Polars
|
|
|
1134
1941
|
# # │ 2031-12-31 00:30:00 ┆ 2024-08-09 │
|
|
1135
1942
|
# # └─────────────────────┴────────────┘
|
|
1136
1943
|
def self.time
|
|
1137
|
-
|
|
1944
|
+
by_dtype([Time])
|
|
1945
|
+
end
|
|
1946
|
+
|
|
1947
|
+
# @private
|
|
1948
|
+
def self._combine_as_selector(items, *more_items)
|
|
1949
|
+
names, regexes, dtypes = [], [], []
|
|
1950
|
+
selectors = []
|
|
1951
|
+
((items.is_a?(::Array) ? items : [items]) + more_items).each do |item|
|
|
1952
|
+
if Utils.is_selector(item)
|
|
1953
|
+
selectors << item
|
|
1954
|
+
elsif item.is_a?(::String)
|
|
1955
|
+
if item.start_with?("^") && item.end_with?("$")
|
|
1956
|
+
regexes << item
|
|
1957
|
+
else
|
|
1958
|
+
names << item
|
|
1959
|
+
end
|
|
1960
|
+
elsif Utils.is_polars_dtype(item)
|
|
1961
|
+
dtypes << item
|
|
1962
|
+
elsif Utils.is_column(item)
|
|
1963
|
+
names << item.meta.output_name
|
|
1964
|
+
else
|
|
1965
|
+
msg = "expected one or more `str`, `DataType` or selector; found #{item.inspect} instead."
|
|
1966
|
+
raise TypeError, msg
|
|
1967
|
+
end
|
|
1968
|
+
end
|
|
1969
|
+
|
|
1970
|
+
selected = []
|
|
1971
|
+
if names.any?
|
|
1972
|
+
selected << by_name(*names, require_all: false)
|
|
1973
|
+
end
|
|
1974
|
+
if dtypes.any?
|
|
1975
|
+
selected << by_dtype(*dtypes)
|
|
1976
|
+
end
|
|
1977
|
+
if regexes.any?
|
|
1978
|
+
raise Todo
|
|
1979
|
+
end
|
|
1980
|
+
if selectors.any?
|
|
1981
|
+
selected.concat(selectors)
|
|
1982
|
+
end
|
|
1983
|
+
|
|
1984
|
+
selected.reduce(empty, :|)
|
|
1138
1985
|
end
|
|
1139
1986
|
end
|
|
1140
1987
|
|
|
1141
1988
|
def self.cs
|
|
1142
|
-
|
|
1989
|
+
Selectors
|
|
1143
1990
|
end
|
|
1144
1991
|
end
|