polars-df 0.14.0-x86_64-linux-musl → 0.16.0-x86_64-linux-musl

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/Cargo.lock +1523 -378
  4. data/LICENSE-THIRD-PARTY.txt +23495 -12923
  5. data/LICENSE.txt +1 -0
  6. data/README.md +38 -4
  7. data/lib/polars/3.2/polars.so +0 -0
  8. data/lib/polars/3.3/polars.so +0 -0
  9. data/lib/polars/{3.1 → 3.4}/polars.so +0 -0
  10. data/lib/polars/batched_csv_reader.rb +0 -2
  11. data/lib/polars/binary_expr.rb +133 -9
  12. data/lib/polars/binary_name_space.rb +101 -6
  13. data/lib/polars/config.rb +4 -0
  14. data/lib/polars/data_frame.rb +452 -101
  15. data/lib/polars/data_type_group.rb +28 -0
  16. data/lib/polars/data_types.rb +3 -1
  17. data/lib/polars/date_time_expr.rb +244 -0
  18. data/lib/polars/date_time_name_space.rb +87 -0
  19. data/lib/polars/expr.rb +103 -2
  20. data/lib/polars/functions/aggregation/horizontal.rb +10 -4
  21. data/lib/polars/functions/as_datatype.rb +51 -2
  22. data/lib/polars/functions/col.rb +1 -1
  23. data/lib/polars/functions/eager.rb +1 -3
  24. data/lib/polars/functions/lazy.rb +95 -13
  25. data/lib/polars/functions/range/time_range.rb +21 -21
  26. data/lib/polars/io/csv.rb +14 -16
  27. data/lib/polars/io/database.rb +2 -2
  28. data/lib/polars/io/delta.rb +126 -0
  29. data/lib/polars/io/ipc.rb +14 -4
  30. data/lib/polars/io/ndjson.rb +10 -0
  31. data/lib/polars/io/parquet.rb +168 -111
  32. data/lib/polars/lazy_frame.rb +684 -20
  33. data/lib/polars/list_name_space.rb +169 -0
  34. data/lib/polars/selectors.rb +1226 -0
  35. data/lib/polars/series.rb +465 -35
  36. data/lib/polars/string_cache.rb +27 -1
  37. data/lib/polars/string_expr.rb +0 -1
  38. data/lib/polars/string_name_space.rb +73 -3
  39. data/lib/polars/struct_name_space.rb +31 -7
  40. data/lib/polars/utils/various.rb +5 -1
  41. data/lib/polars/utils.rb +45 -10
  42. data/lib/polars/version.rb +1 -1
  43. data/lib/polars.rb +17 -1
  44. metadata +10 -9
  45. data/lib/polars/functions.rb +0 -57
@@ -0,0 +1,1226 @@
1
+ module Polars
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
+ # @private
117
+ def self._re_string(string, escape: true)
118
+ if string.is_a?(::String)
119
+ rx = escape ? Utils.re_escape(string) : string
120
+ else
121
+ strings = []
122
+ string.each do |st|
123
+ if st.is_a?(Array)
124
+ strings.concat(st)
125
+ else
126
+ strings << st
127
+ end
128
+ end
129
+ rx = strings.map { |x| escape ? Utils.re_escape(x) : x }.join("|")
130
+ end
131
+ "(#{rx})"
132
+ end
133
+
134
+ # Select all columns.
135
+ #
136
+ # @return [SelectorProxy]
137
+ #
138
+ # @example
139
+ # df = Polars::DataFrame.new(
140
+ # {
141
+ # "dt" => [Date.new(1999, 12, 31), Date.new(2024, 1, 1)],
142
+ # "value" => [1_234_500, 5_000_555]
143
+ # },
144
+ # schema_overrides: {"value" => Polars::Int32}
145
+ # )
146
+ #
147
+ # @example Select all columns, casting them to string:
148
+ # df.select(Polars.cs.all.cast(Polars::String))
149
+ # # =>
150
+ # # shape: (2, 2)
151
+ # # ┌────────────┬─────────┐
152
+ # # │ dt ┆ value │
153
+ # # │ --- ┆ --- │
154
+ # # │ str ┆ str │
155
+ # # ╞════════════╪═════════╡
156
+ # # │ 1999-12-31 ┆ 1234500 │
157
+ # # │ 2024-01-01 ┆ 5000555 │
158
+ # # └────────────┴─────────┘
159
+ #
160
+ # @example Select all columns *except* for those matching the given dtypes:
161
+ # df.select(Polars.cs.all - Polars.cs.numeric)
162
+ # # =>
163
+ # # shape: (2, 1)
164
+ # # ┌────────────┐
165
+ # # │ dt │
166
+ # # │ --- │
167
+ # # │ date │
168
+ # # ╞════════════╡
169
+ # # │ 1999-12-31 │
170
+ # # │ 2024-01-01 │
171
+ # # └────────────┘
172
+ def self.all
173
+ _selector_proxy_(F.all, name: "all")
174
+ end
175
+
176
+ # Select all columns with alphabetic names (eg: only letters).
177
+ #
178
+ # @param ascii_only [Boolean]
179
+ # Indicate whether to consider only ASCII alphabetic characters, or the full
180
+ # Unicode range of valid letters (accented, idiographic, etc).
181
+ # @param ignore_spaces [Boolean]
182
+ # Indicate whether to ignore the presence of spaces in column names; if so,
183
+ # only the other (non-space) characters are considered.
184
+ #
185
+ # @return [SelectorProxy]
186
+ #
187
+ # @note
188
+ # Matching column names cannot contain *any* non-alphabetic characters. Note
189
+ # that the definition of "alphabetic" consists of all valid Unicode alphabetic
190
+ # characters (`\p{Alphabetic}`) by default; this can be changed by setting
191
+ # `ascii_only: true`.
192
+ #
193
+ # @example
194
+ # df = Polars::DataFrame.new(
195
+ # {
196
+ # "no1" => [100, 200, 300],
197
+ # "café" => ["espresso", "latte", "mocha"],
198
+ # "t or f" => [true, false, nil],
199
+ # "hmm" => ["aaa", "bbb", "ccc"],
200
+ # "都市" => ["東京", "大阪", "京都"]
201
+ # }
202
+ # )
203
+ #
204
+ # @example Select columns with alphabetic names; note that accented characters and kanji are recognised as alphabetic here:
205
+ # df.select(Polars.cs.alpha)
206
+ # # =>
207
+ # # shape: (3, 3)
208
+ # # ┌──────────┬─────┬──────┐
209
+ # # │ café ┆ hmm ┆ 都市 │
210
+ # # │ --- ┆ --- ┆ --- │
211
+ # # │ str ┆ str ┆ str │
212
+ # # ╞══════════╪═════╪══════╡
213
+ # # │ espresso ┆ aaa ┆ 東京 │
214
+ # # │ latte ┆ bbb ┆ 大阪 │
215
+ # # │ mocha ┆ ccc ┆ 京都 │
216
+ # # └──────────┴─────┴──────┘
217
+ #
218
+ # @example Constrain the definition of "alphabetic" to ASCII characters only:
219
+ # df.select(Polars.cs.alpha(ascii_only: true))
220
+ # # =>
221
+ # # shape: (3, 1)
222
+ # # ┌─────┐
223
+ # # │ hmm │
224
+ # # │ --- │
225
+ # # │ str │
226
+ # # ╞═════╡
227
+ # # │ aaa │
228
+ # # │ bbb │
229
+ # # │ ccc │
230
+ # # └─────┘
231
+ #
232
+ # @example
233
+ # df.select(Polars.cs.alpha(ascii_only: true, ignore_spaces: true))
234
+ # # =>
235
+ # # shape: (3, 2)
236
+ # # ┌────────┬─────┐
237
+ # # │ t or f ┆ hmm │
238
+ # # │ --- ┆ --- │
239
+ # # │ bool ┆ str │
240
+ # # ╞════════╪═════╡
241
+ # # │ true ┆ aaa │
242
+ # # │ false ┆ bbb │
243
+ # # │ null ┆ ccc │
244
+ # # └────────┴─────┘
245
+ #
246
+ # @example Select all columns *except* for those with alphabetic names:
247
+ # df.select(~Polars.cs.alpha)
248
+ # # =>
249
+ # # shape: (3, 2)
250
+ # # ┌─────┬────────┐
251
+ # # │ no1 ┆ t or f │
252
+ # # │ --- ┆ --- │
253
+ # # │ i64 ┆ bool │
254
+ # # ╞═════╪════════╡
255
+ # # │ 100 ┆ true │
256
+ # # │ 200 ┆ false │
257
+ # # │ 300 ┆ null │
258
+ # # └─────┴────────┘
259
+ #
260
+ # @example
261
+ # df.select(~Polars.cs.alpha(ignore_spaces: true))
262
+ # # =>
263
+ # # shape: (3, 1)
264
+ # # ┌─────┐
265
+ # # │ no1 │
266
+ # # │ --- │
267
+ # # │ i64 │
268
+ # # ╞═════╡
269
+ # # │ 100 │
270
+ # # │ 200 │
271
+ # # │ 300 │
272
+ # # └─────┘
273
+ def self.alpha(ascii_only: false, ignore_spaces: false)
274
+ # note that we need to supply a pattern compatible with the *rust* regex crate
275
+ re_alpha = ascii_only ? "a-zA-Z" : "\\p{Alphabetic}"
276
+ re_space = ignore_spaces ? " " : ""
277
+ _selector_proxy_(
278
+ F.col("^[#{re_alpha}#{re_space}]+$"),
279
+ name: "alpha",
280
+ parameters: {"ascii_only" => ascii_only, "ignore_spaces" => ignore_spaces},
281
+ )
282
+ end
283
+
284
+ # TODO
285
+ # def alphanumeric
286
+ # end
287
+
288
+ # Select all binary columns.
289
+ #
290
+ # @return [SelectorProxy]
291
+ #
292
+ # @example
293
+ # df = Polars::DataFrame.new({"a" => ["hello".b], "b" => ["world"], "c" => ["!".b], "d" => [":)"]})
294
+ # # =>
295
+ # # shape: (1, 4)
296
+ # # ┌──────────┬───────┬────────┬─────┐
297
+ # # │ a ┆ b ┆ c ┆ d │
298
+ # # │ --- ┆ --- ┆ --- ┆ --- │
299
+ # # │ binary ┆ str ┆ binary ┆ str │
300
+ # # ╞══════════╪═══════╪════════╪═════╡
301
+ # # │ b"hello" ┆ world ┆ b"!" ┆ :) │
302
+ # # └──────────┴───────┴────────┴─────┘
303
+ #
304
+ # @example Select binary columns and export as a dict:
305
+ # df.select(Polars.cs.binary).to_h(as_series: false)
306
+ # # => {"a"=>["hello"], "c"=>["!"]}
307
+ #
308
+ # @example Select all columns *except* for those that are binary:
309
+ # df.select(~Polars.cs.binary).to_h(as_series: false)
310
+ # # => {"b"=>["world"], "d"=>[":)"]}
311
+ def self.binary
312
+ _selector_proxy_(F.col(Binary), name: "binary")
313
+ end
314
+
315
+ # Select all boolean columns.
316
+ #
317
+ # @return [SelectorProxy]
318
+ #
319
+ # @example
320
+ # df = Polars::DataFrame.new({"n" => 1..4}).with_columns(n_even: Polars.col("n") % 2 == 0)
321
+ # # =>
322
+ # # shape: (4, 2)
323
+ # # ┌─────┬────────┐
324
+ # # │ n ┆ n_even │
325
+ # # │ --- ┆ --- │
326
+ # # │ i64 ┆ bool │
327
+ # # ╞═════╪════════╡
328
+ # # │ 1 ┆ false │
329
+ # # │ 2 ┆ true │
330
+ # # │ 3 ┆ false │
331
+ # # │ 4 ┆ true │
332
+ # # └─────┴────────┘
333
+ #
334
+ # @example Select and invert boolean columns:
335
+ # df.with_columns(is_odd: Polars.cs.boolean.not_)
336
+ # # =>
337
+ # # shape: (4, 3)
338
+ # # ┌─────┬────────┬────────┐
339
+ # # │ n ┆ n_even ┆ is_odd │
340
+ # # │ --- ┆ --- ┆ --- │
341
+ # # │ i64 ┆ bool ┆ bool │
342
+ # # ╞═════╪════════╪════════╡
343
+ # # │ 1 ┆ false ┆ true │
344
+ # # │ 2 ┆ true ┆ false │
345
+ # # │ 3 ┆ false ┆ true │
346
+ # # │ 4 ┆ true ┆ false │
347
+ # # └─────┴────────┴────────┘
348
+ #
349
+ # @example Select all columns *except* for those that are boolean:
350
+ # df.select(~Polars.cs.boolean)
351
+ # # =>
352
+ # # shape: (4, 1)
353
+ # # ┌─────┐
354
+ # # │ n │
355
+ # # │ --- │
356
+ # # │ i64 │
357
+ # # ╞═════╡
358
+ # # │ 1 │
359
+ # # │ 2 │
360
+ # # │ 3 │
361
+ # # │ 4 │
362
+ # # └─────┘
363
+ def self.boolean
364
+ _selector_proxy_(F.col(Boolean), name: "boolean")
365
+ end
366
+
367
+ # TODO
368
+ # def by_dtype
369
+ # end
370
+
371
+ # TODO
372
+ # def by_index
373
+ # end
374
+
375
+ # Select all columns matching the given names.
376
+ #
377
+ # @param names [Array]
378
+ # One or more names of columns to select.
379
+ # @param require_all [Boolean]
380
+ # Whether to match *all* names (the default) or *any* of the names.
381
+ #
382
+ # @return [SelectorProxy]
383
+ #
384
+ # @note
385
+ # Matching columns are returned in the order in which they are declared in
386
+ # the selector, not the underlying schema order.
387
+ #
388
+ # @example
389
+ # df = Polars::DataFrame.new(
390
+ # {
391
+ # "foo" => ["x", "y"],
392
+ # "bar" => [123, 456],
393
+ # "baz" => [2.0, 5.5],
394
+ # "zap" => [false, true]
395
+ # }
396
+ # )
397
+ #
398
+ # @example Select columns by name:
399
+ # df.select(Polars.cs.by_name("foo", "bar"))
400
+ # # =>
401
+ # # shape: (2, 2)
402
+ # # ┌─────┬─────┐
403
+ # # │ foo ┆ bar │
404
+ # # │ --- ┆ --- │
405
+ # # │ str ┆ i64 │
406
+ # # ╞═════╪═════╡
407
+ # # │ x ┆ 123 │
408
+ # # │ y ┆ 456 │
409
+ # # └─────┴─────┘
410
+ #
411
+ # @example Match *any* of the given columns by name:
412
+ # df.select(Polars.cs.by_name("baz", "moose", "foo", "bear", require_all: false))
413
+ # # =>
414
+ # # shape: (2, 2)
415
+ # # ┌─────┬─────┐
416
+ # # │ foo ┆ baz │
417
+ # # │ --- ┆ --- │
418
+ # # │ str ┆ f64 │
419
+ # # ╞═════╪═════╡
420
+ # # │ x ┆ 2.0 │
421
+ # # │ y ┆ 5.5 │
422
+ # # └─────┴─────┘
423
+ #
424
+ # @example Match all columns *except* for those given:
425
+ # df.select(~Polars.cs.by_name("foo", "bar"))
426
+ # # =>
427
+ # # shape: (2, 2)
428
+ # # ┌─────┬───────┐
429
+ # # │ baz ┆ zap │
430
+ # # │ --- ┆ --- │
431
+ # # │ f64 ┆ bool │
432
+ # # ╞═════╪═══════╡
433
+ # # │ 2.0 ┆ false │
434
+ # # │ 5.5 ┆ true │
435
+ # # └─────┴───────┘
436
+ def self.by_name(*names, require_all: true)
437
+ all_names = []
438
+ names.each do |nm|
439
+ if nm.is_a?(::String)
440
+ all_names << nm
441
+ else
442
+ msg = "invalid name: #{nm.inspect}"
443
+ raise TypeError, msg
444
+ end
445
+ end
446
+
447
+ selector_params = {"*names" => all_names}
448
+ match_cols = all_names
449
+ if !require_all
450
+ match_cols = "^(#{all_names.map { |nm| Utils.re_escape(nm) }.join("|")})$"
451
+ selector_params["require_all"] = require_all
452
+ end
453
+
454
+ _selector_proxy_(
455
+ F.col(match_cols),
456
+ name: "by_name",
457
+ parameters: selector_params
458
+ )
459
+ end
460
+
461
+ # Select all categorical columns.
462
+ #
463
+ # @return [SelectorProxy]
464
+ #
465
+ # @example
466
+ # df = Polars::DataFrame.new(
467
+ # {
468
+ # "foo" => ["xx", "yy"],
469
+ # "bar" => [123, 456],
470
+ # "baz" => [2.0, 5.5]
471
+ # },
472
+ # schema_overrides: {"foo" => Polars::Categorical}
473
+ # )
474
+ #
475
+ # @example Select all categorical columns:
476
+ # df.select(Polars.cs.categorical)
477
+ # # =>
478
+ # # shape: (2, 1)
479
+ # # ┌─────┐
480
+ # # │ foo │
481
+ # # │ --- │
482
+ # # │ cat │
483
+ # # ╞═════╡
484
+ # # │ xx │
485
+ # # │ yy │
486
+ # # └─────┘
487
+ #
488
+ # @example Select all columns *except* for those that are categorical:
489
+ # df.select(~Polars.cs.categorical)
490
+ # # =>
491
+ # # shape: (2, 2)
492
+ # # ┌─────┬─────┐
493
+ # # │ bar ┆ baz │
494
+ # # │ --- ┆ --- │
495
+ # # │ i64 ┆ f64 │
496
+ # # ╞═════╪═════╡
497
+ # # │ 123 ┆ 2.0 │
498
+ # # │ 456 ┆ 5.5 │
499
+ # # └─────┴─────┘
500
+ def self.categorical
501
+ _selector_proxy_(F.col(Categorical), name: "categorical")
502
+ end
503
+
504
+ # Select columns whose names contain the given literal substring(s).
505
+ #
506
+ # @param substring [Object]
507
+ # Substring(s) that matching column names should contain.
508
+ #
509
+ # @return [SelectorProxy]
510
+ #
511
+ # @example
512
+ # df = Polars::DataFrame.new(
513
+ # {
514
+ # "foo" => ["x", "y"],
515
+ # "bar" => [123, 456],
516
+ # "baz" => [2.0, 5.5],
517
+ # "zap" => [false, true]
518
+ # }
519
+ # )
520
+ #
521
+ # @example Select columns that contain the substring 'ba':
522
+ # df.select(Polars.cs.contains("ba"))
523
+ # # =>
524
+ # # shape: (2, 2)
525
+ # # ┌─────┬─────┐
526
+ # # │ bar ┆ baz │
527
+ # # │ --- ┆ --- │
528
+ # # │ i64 ┆ f64 │
529
+ # # ╞═════╪═════╡
530
+ # # │ 123 ┆ 2.0 │
531
+ # # │ 456 ┆ 5.5 │
532
+ # # └─────┴─────┘
533
+ #
534
+ # @example Select columns that contain the substring 'ba' or the letter 'z':
535
+ # df.select(Polars.cs.contains("ba", "z"))
536
+ # # =>
537
+ # # shape: (2, 3)
538
+ # # ┌─────┬─────┬───────┐
539
+ # # │ bar ┆ baz ┆ zap │
540
+ # # │ --- ┆ --- ┆ --- │
541
+ # # │ i64 ┆ f64 ┆ bool │
542
+ # # ╞═════╪═════╪═══════╡
543
+ # # │ 123 ┆ 2.0 ┆ false │
544
+ # # │ 456 ┆ 5.5 ┆ true │
545
+ # # └─────┴─────┴───────┘
546
+ #
547
+ # @example Select all columns *except* for those that contain the substring 'ba':
548
+ # df.select(~Polars.cs.contains("ba"))
549
+ # # =>
550
+ # # shape: (2, 2)
551
+ # # ┌─────┬───────┐
552
+ # # │ foo ┆ zap │
553
+ # # │ --- ┆ --- │
554
+ # # │ str ┆ bool │
555
+ # # ╞═════╪═══════╡
556
+ # # │ x ┆ false │
557
+ # # │ y ┆ true │
558
+ # # └─────┴───────┘
559
+ def self.contains(*substring)
560
+ escaped_substring = _re_string(substring)
561
+ raw_params = "^.*#{escaped_substring}.*$"
562
+
563
+ _selector_proxy_(
564
+ F.col(raw_params),
565
+ name: "contains",
566
+ parameters: {"*substring" => escaped_substring}
567
+ )
568
+ end
569
+
570
+ # Select all date columns.
571
+ #
572
+ # @return [SelectorProxy]
573
+ #
574
+ # @example
575
+ # df = Polars::DataFrame.new(
576
+ # {
577
+ # "dtm" => [DateTime.new(2001, 5, 7, 10, 25), DateTime.new(2031, 12, 31, 0, 30)],
578
+ # "dt" => [Date.new(1999, 12, 31), Date.new(2024, 8, 9)]
579
+ # }
580
+ # )
581
+ #
582
+ # @example Select all date columns:
583
+ # df.select(Polars.cs.date)
584
+ # # =>
585
+ # # shape: (2, 1)
586
+ # # ┌────────────┐
587
+ # # │ dt │
588
+ # # │ --- │
589
+ # # │ date │
590
+ # # ╞════════════╡
591
+ # # │ 1999-12-31 │
592
+ # # │ 2024-08-09 │
593
+ # # └────────────┘
594
+ #
595
+ # @example Select all columns *except* for those that are dates:
596
+ # df.select(~Polars.cs.date)
597
+ # # =>
598
+ # # shape: (2, 1)
599
+ # # ┌─────────────────────┐
600
+ # # │ dtm │
601
+ # # │ --- │
602
+ # # │ datetime[ns] │
603
+ # # ╞═════════════════════╡
604
+ # # │ 2001-05-07 10:25:00 │
605
+ # # │ 2031-12-31 00:30:00 │
606
+ # # └─────────────────────┘
607
+ def self.date
608
+ _selector_proxy_(F.col(Date), name: "date")
609
+ end
610
+
611
+ # TODO
612
+ # def datetime
613
+ # end
614
+
615
+ # Select all decimal columns.
616
+ #
617
+ # @return [SelectorProxy]
618
+ #
619
+ # @example
620
+ # df = Polars::DataFrame.new(
621
+ # {
622
+ # "foo" => ["x", "y"],
623
+ # "bar" => [BigDecimal("123"), BigDecimal("456")],
624
+ # "baz" => [BigDecimal("2.0005"), BigDecimal("-50.5555")],
625
+ # },
626
+ # schema_overrides: {"baz" => Polars::Decimal.new(10, 5)}
627
+ # )
628
+ #
629
+ # @example Select all decimal columns:
630
+ # df.select(Polars.cs.decimal)
631
+ # # =>
632
+ # # shape: (2, 2)
633
+ # # ┌──────────────┬───────────────┐
634
+ # # │ bar ┆ baz │
635
+ # # │ --- ┆ --- │
636
+ # # │ decimal[*,0] ┆ decimal[10,5] │
637
+ # # ╞══════════════╪═══════════════╡
638
+ # # │ 123 ┆ 2.00050 │
639
+ # # │ 456 ┆ -50.55550 │
640
+ # # └──────────────┴───────────────┘
641
+ #
642
+ # @example Select all columns *except* the decimal ones:
643
+ #
644
+ # df.select(~Polars.cs.decimal)
645
+ # # =>
646
+ # # shape: (2, 1)
647
+ # # ┌─────┐
648
+ # # │ foo │
649
+ # # │ --- │
650
+ # # │ str │
651
+ # # ╞═════╡
652
+ # # │ x │
653
+ # # │ y │
654
+ # # └─────┘
655
+ def self.decimal
656
+ # TODO: allow explicit selection by scale/precision?
657
+ _selector_proxy_(F.col(Decimal), name: "decimal")
658
+ end
659
+
660
+ # Select columns that end with the given substring(s).
661
+ #
662
+ # @param suffix [Object]
663
+ # Substring(s) that matching column names should end with.
664
+ #
665
+ # @return [SelectorProxy]
666
+ #
667
+ # @example
668
+ # df = Polars::DataFrame.new(
669
+ # {
670
+ # "foo" => ["x", "y"],
671
+ # "bar" => [123, 456],
672
+ # "baz" => [2.0, 5.5],
673
+ # "zap" => [false, true]
674
+ # }
675
+ # )
676
+ #
677
+ # @example Select columns that end with the substring 'z':
678
+ # df.select(Polars.cs.ends_with("z"))
679
+ # # =>
680
+ # # shape: (2, 1)
681
+ # # ┌─────┐
682
+ # # │ baz │
683
+ # # │ --- │
684
+ # # │ f64 │
685
+ # # ╞═════╡
686
+ # # │ 2.0 │
687
+ # # │ 5.5 │
688
+ # # └─────┘
689
+ #
690
+ # @example Select columns that end with *either* the letter 'z' or 'r':
691
+ # df.select(Polars.cs.ends_with("z", "r"))
692
+ # # =>
693
+ # # shape: (2, 2)
694
+ # # ┌─────┬─────┐
695
+ # # │ bar ┆ baz │
696
+ # # │ --- ┆ --- │
697
+ # # │ i64 ┆ f64 │
698
+ # # ╞═════╪═════╡
699
+ # # │ 123 ┆ 2.0 │
700
+ # # │ 456 ┆ 5.5 │
701
+ # # └─────┴─────┘
702
+ #
703
+ # @example Select all columns *except* for those that end with the substring 'z':
704
+ # df.select(~Polars.cs.ends_with("z"))
705
+ # # =>
706
+ # # shape: (2, 3)
707
+ # # ┌─────┬─────┬───────┐
708
+ # # │ foo ┆ bar ┆ zap │
709
+ # # │ --- ┆ --- ┆ --- │
710
+ # # │ str ┆ i64 ┆ bool │
711
+ # # ╞═════╪═════╪═══════╡
712
+ # # │ x ┆ 123 ┆ false │
713
+ # # │ y ┆ 456 ┆ true │
714
+ # # └─────┴─────┴───────┘
715
+ def self.ends_with(*suffix)
716
+ escaped_suffix = _re_string(suffix)
717
+ raw_params = "^.*#{escaped_suffix}$"
718
+
719
+ _selector_proxy_(
720
+ F.col(raw_params),
721
+ name: "ends_with",
722
+ parameters: {"*suffix" => escaped_suffix},
723
+ )
724
+ end
725
+
726
+ # Select the first column in the current scope.
727
+ #
728
+ # @return [SelectorProxy]
729
+ #
730
+ # @example
731
+ # df = Polars::DataFrame.new(
732
+ # {
733
+ # "foo" => ["x", "y"],
734
+ # "bar" => [123, 456],
735
+ # "baz" => [2.0, 5.5],
736
+ # "zap" => [0, 1]
737
+ # }
738
+ # )
739
+ #
740
+ # @example Select the first column:
741
+ # df.select(Polars.cs.first)
742
+ # # =>
743
+ # # shape: (2, 1)
744
+ # # ┌─────┐
745
+ # # │ foo │
746
+ # # │ --- │
747
+ # # │ str │
748
+ # # ╞═════╡
749
+ # # │ x │
750
+ # # │ y │
751
+ # # └─────┘
752
+ #
753
+ # @example Select everything *except* for the first column:
754
+ # df.select(~Polars.cs.first)
755
+ # # =>
756
+ # # shape: (2, 3)
757
+ # # ┌─────┬─────┬─────┐
758
+ # # │ bar ┆ baz ┆ zap │
759
+ # # │ --- ┆ --- ┆ --- │
760
+ # # │ i64 ┆ f64 ┆ i64 │
761
+ # # ╞═════╪═════╪═════╡
762
+ # # │ 123 ┆ 2.0 ┆ 0 │
763
+ # # │ 456 ┆ 5.5 ┆ 1 │
764
+ # # └─────┴─────┴─────┘
765
+ def self.first
766
+ _selector_proxy_(F.first, name: "first")
767
+ end
768
+
769
+ # Select all float columns.
770
+ #
771
+ # @return [SelectorProxy]
772
+ #
773
+ # @example
774
+ # df = Polars::DataFrame.new(
775
+ # {
776
+ # "foo" => ["x", "y"],
777
+ # "bar" => [123, 456],
778
+ # "baz" => [2.0, 5.5],
779
+ # "zap" => [0.0, 1.0]
780
+ # },
781
+ # schema_overrides: {"baz" => Polars::Float32, "zap" => Polars::Float64}
782
+ # )
783
+ #
784
+ # @example Select all float columns:
785
+ # df.select(Polars.cs.float)
786
+ # # =>
787
+ # # shape: (2, 2)
788
+ # # ┌─────┬─────┐
789
+ # # │ baz ┆ zap │
790
+ # # │ --- ┆ --- │
791
+ # # │ f32 ┆ f64 │
792
+ # # ╞═════╪═════╡
793
+ # # │ 2.0 ┆ 0.0 │
794
+ # # │ 5.5 ┆ 1.0 │
795
+ # # └─────┴─────┘
796
+ #
797
+ # @example Select all columns *except* for those that are float:
798
+ # df.select(~Polars.cs.float)
799
+ # # =>
800
+ # # shape: (2, 2)
801
+ # # ┌─────┬─────┐
802
+ # # │ foo ┆ bar │
803
+ # # │ --- ┆ --- │
804
+ # # │ str ┆ i64 │
805
+ # # ╞═════╪═════╡
806
+ # # │ x ┆ 123 │
807
+ # # │ y ┆ 456 │
808
+ # # └─────┴─────┘
809
+ def self.float
810
+ _selector_proxy_(F.col(FLOAT_DTYPES), name: "float")
811
+ end
812
+
813
+ # Select all integer columns.
814
+ #
815
+ # @return [SelectorProxy]
816
+ #
817
+ # @example
818
+ # df = Polars::DataFrame.new(
819
+ # {
820
+ # "foo" => ["x", "y"],
821
+ # "bar" => [123, 456],
822
+ # "baz" => [2.0, 5.5],
823
+ # "zap" => [0, 1]
824
+ # }
825
+ # )
826
+ #
827
+ # @example Select all integer columns:
828
+ # df.select(Polars.cs.integer)
829
+ # # =>
830
+ # # shape: (2, 2)
831
+ # # ┌─────┬─────┐
832
+ # # │ bar ┆ zap │
833
+ # # │ --- ┆ --- │
834
+ # # │ i64 ┆ i64 │
835
+ # # ╞═════╪═════╡
836
+ # # │ 123 ┆ 0 │
837
+ # # │ 456 ┆ 1 │
838
+ # # └─────┴─────┘
839
+ #
840
+ # @example Select all columns *except* for those that are integer:
841
+ # df.select(~Polars.cs.integer)
842
+ # # =>
843
+ # # shape: (2, 2)
844
+ # # ┌─────┬─────┐
845
+ # # │ foo ┆ baz │
846
+ # # │ --- ┆ --- │
847
+ # # │ str ┆ f64 │
848
+ # # ╞═════╪═════╡
849
+ # # │ x ┆ 2.0 │
850
+ # # │ y ┆ 5.5 │
851
+ # # └─────┴─────┘
852
+ def self.integer
853
+ _selector_proxy_(F.col(INTEGER_DTYPES), name: "integer")
854
+ end
855
+
856
+ # Select all signed integer columns.
857
+ #
858
+ # @return [SelectorProxy]
859
+ #
860
+ # @example
861
+ # df = Polars::DataFrame.new(
862
+ # {
863
+ # "foo" => [-123, -456],
864
+ # "bar" => [3456, 6789],
865
+ # "baz" => [7654, 4321],
866
+ # "zap" => ["ab", "cd"]
867
+ # },
868
+ # schema_overrides: {"bar" => Polars::UInt32, "baz" => Polars::UInt64}
869
+ # )
870
+ #
871
+ # @example Select all signed integer columns:
872
+ # df.select(Polars.cs.signed_integer)
873
+ # # =>
874
+ # # shape: (2, 1)
875
+ # # ┌──────┐
876
+ # # │ foo │
877
+ # # │ --- │
878
+ # # │ i64 │
879
+ # # ╞══════╡
880
+ # # │ -123 │
881
+ # # │ -456 │
882
+ # # └──────┘
883
+ #
884
+ # @example
885
+ # df.select(~Polars.cs.signed_integer)
886
+ # # =>
887
+ # # shape: (2, 3)
888
+ # # ┌──────┬──────┬─────┐
889
+ # # │ bar ┆ baz ┆ zap │
890
+ # # │ --- ┆ --- ┆ --- │
891
+ # # │ u32 ┆ u64 ┆ str │
892
+ # # ╞══════╪══════╪═════╡
893
+ # # │ 3456 ┆ 7654 ┆ ab │
894
+ # # │ 6789 ┆ 4321 ┆ cd │
895
+ # # └──────┴──────┴─────┘
896
+ #
897
+ # @example Select all integer columns (both signed and unsigned):
898
+ # df.select(Polars.cs.integer)
899
+ # # =>
900
+ # # shape: (2, 3)
901
+ # # ┌──────┬──────┬──────┐
902
+ # # │ foo ┆ bar ┆ baz │
903
+ # # │ --- ┆ --- ┆ --- │
904
+ # # │ i64 ┆ u32 ┆ u64 │
905
+ # # ╞══════╪══════╪══════╡
906
+ # # │ -123 ┆ 3456 ┆ 7654 │
907
+ # # │ -456 ┆ 6789 ┆ 4321 │
908
+ # # └──────┴──────┴──────┘
909
+ def self.signed_integer
910
+ _selector_proxy_(F.col(SIGNED_INTEGER_DTYPES), name: "signed_integer")
911
+ end
912
+
913
+ # Select all unsigned integer columns.
914
+ #
915
+ # @return [SelectorProxy]
916
+ #
917
+ # @example
918
+ # df = Polars::DataFrame.new(
919
+ # {
920
+ # "foo" => [-123, -456],
921
+ # "bar" => [3456, 6789],
922
+ # "baz" => [7654, 4321],
923
+ # "zap" => ["ab", "cd"]
924
+ # },
925
+ # schema_overrides: {"bar" => Polars::UInt32, "baz" => Polars::UInt64}
926
+ # )
927
+ #
928
+ # @example Select all unsigned integer columns:
929
+ # df.select(Polars.cs.unsigned_integer)
930
+ # # =>
931
+ # # shape: (2, 2)
932
+ # # ┌──────┬──────┐
933
+ # # │ bar ┆ baz │
934
+ # # │ --- ┆ --- │
935
+ # # │ u32 ┆ u64 │
936
+ # # ╞══════╪══════╡
937
+ # # │ 3456 ┆ 7654 │
938
+ # # │ 6789 ┆ 4321 │
939
+ # # └──────┴──────┘
940
+ #
941
+ # @example Select all columns *except* for those that are unsigned integers:
942
+ # df.select(~Polars.cs.unsigned_integer)
943
+ # # =>
944
+ # # shape: (2, 2)
945
+ # # ┌──────┬─────┐
946
+ # # │ foo ┆ zap │
947
+ # # │ --- ┆ --- │
948
+ # # │ i64 ┆ str │
949
+ # # ╞══════╪═════╡
950
+ # # │ -123 ┆ ab │
951
+ # # │ -456 ┆ cd │
952
+ # # └──────┴─────┘
953
+ #
954
+ # @example Select all integer columns (both signed and unsigned):
955
+ # df.select(Polars.cs.integer)
956
+ # # =>
957
+ # # shape: (2, 3)
958
+ # # ┌──────┬──────┬──────┐
959
+ # # │ foo ┆ bar ┆ baz │
960
+ # # │ --- ┆ --- ┆ --- │
961
+ # # │ i64 ┆ u32 ┆ u64 │
962
+ # # ╞══════╪══════╪══════╡
963
+ # # │ -123 ┆ 3456 ┆ 7654 │
964
+ # # │ -456 ┆ 6789 ┆ 4321 │
965
+ # # └──────┴──────┴──────┘
966
+ def self.unsigned_integer
967
+ _selector_proxy_(F.col(UNSIGNED_INTEGER_DTYPES), name: "unsigned_integer")
968
+ end
969
+
970
+ # Select the last column in the current scope.
971
+ #
972
+ # @return [SelectorProxy]
973
+ #
974
+ # @example
975
+ # df = Polars::DataFrame.new(
976
+ # {
977
+ # "foo" => ["x", "y"],
978
+ # "bar" => [123, 456],
979
+ # "baz" => [2.0, 5.5],
980
+ # "zap" => [0, 1]
981
+ # }
982
+ # )
983
+ #
984
+ # @example Select the last column:
985
+ # df.select(Polars.cs.last)
986
+ # # =>
987
+ # # shape: (2, 1)
988
+ # # ┌─────┐
989
+ # # │ zap │
990
+ # # │ --- │
991
+ # # │ i64 │
992
+ # # ╞═════╡
993
+ # # │ 0 │
994
+ # # │ 1 │
995
+ # # └─────┘
996
+ #
997
+ # @example Select everything *except* for the last column:
998
+ # df.select(~Polars.cs.last)
999
+ # # =>
1000
+ # # shape: (2, 3)
1001
+ # # ┌─────┬─────┬─────┐
1002
+ # # │ foo ┆ bar ┆ baz │
1003
+ # # │ --- ┆ --- ┆ --- │
1004
+ # # │ str ┆ i64 ┆ f64 │
1005
+ # # ╞═════╪═════╪═════╡
1006
+ # # │ x ┆ 123 ┆ 2.0 │
1007
+ # # │ y ┆ 456 ┆ 5.5 │
1008
+ # # └─────┴─────┴─────┘
1009
+ def self.last
1010
+ _selector_proxy_(F.last, name: "last")
1011
+ end
1012
+
1013
+ # Select all numeric columns.
1014
+ #
1015
+ # @return [SelectorProxy]
1016
+ #
1017
+ # @example
1018
+ # df = Polars::DataFrame.new(
1019
+ # {
1020
+ # "foo" => ["x", "y"],
1021
+ # "bar" => [123, 456],
1022
+ # "baz" => [2.0, 5.5],
1023
+ # "zap" => [0, 0]
1024
+ # },
1025
+ # schema_overrides: {"bar" => Polars::Int16, "baz" => Polars::Float32, "zap" => Polars::UInt8},
1026
+ # )
1027
+ #
1028
+ # @example Match all numeric columns:
1029
+ # df.select(Polars.cs.numeric)
1030
+ # # =>
1031
+ # # shape: (2, 3)
1032
+ # # ┌─────┬─────┬─────┐
1033
+ # # │ bar ┆ baz ┆ zap │
1034
+ # # │ --- ┆ --- ┆ --- │
1035
+ # # │ i16 ┆ f32 ┆ u8 │
1036
+ # # ╞═════╪═════╪═════╡
1037
+ # # │ 123 ┆ 2.0 ┆ 0 │
1038
+ # # │ 456 ┆ 5.5 ┆ 0 │
1039
+ # # └─────┴─────┴─────┘
1040
+ #
1041
+ # @example Match all columns *except* for those that are numeric:
1042
+ # df.select(~Polars.cs.numeric)
1043
+ # # =>
1044
+ # # shape: (2, 1)
1045
+ # # ┌─────┐
1046
+ # # │ foo │
1047
+ # # │ --- │
1048
+ # # │ str │
1049
+ # # ╞═════╡
1050
+ # # │ x │
1051
+ # # │ y │
1052
+ # # └─────┘
1053
+ def self.numeric
1054
+ _selector_proxy_(F.col(NUMERIC_DTYPES), name: "numeric")
1055
+ end
1056
+
1057
+ # Select columns that start with the given substring(s).
1058
+ #
1059
+ # @param prefix [Object]
1060
+ # Substring(s) that matching column names should start with.
1061
+ #
1062
+ # @return [SelectorProxy]
1063
+ #
1064
+ # @example
1065
+ # df = Polars::DataFrame.new(
1066
+ # {
1067
+ # "foo" => [1.0, 2.0],
1068
+ # "bar" => [3.0, 4.0],
1069
+ # "baz" => [5, 6],
1070
+ # "zap" => [7, 8]
1071
+ # }
1072
+ # )
1073
+ #
1074
+ # @example Match columns starting with a 'b':
1075
+ # df.select(Polars.cs.starts_with("b"))
1076
+ # # =>
1077
+ # # shape: (2, 2)
1078
+ # # ┌─────┬─────┐
1079
+ # # │ bar ┆ baz │
1080
+ # # │ --- ┆ --- │
1081
+ # # │ f64 ┆ i64 │
1082
+ # # ╞═════╪═════╡
1083
+ # # │ 3.0 ┆ 5 │
1084
+ # # │ 4.0 ┆ 6 │
1085
+ # # └─────┴─────┘
1086
+ #
1087
+ # @example Match columns starting with *either* the letter 'b' or 'z':
1088
+ # df.select(Polars.cs.starts_with("b", "z"))
1089
+ # # =>
1090
+ # # shape: (2, 3)
1091
+ # # ┌─────┬─────┬─────┐
1092
+ # # │ bar ┆ baz ┆ zap │
1093
+ # # │ --- ┆ --- ┆ --- │
1094
+ # # │ f64 ┆ i64 ┆ i64 │
1095
+ # # ╞═════╪═════╪═════╡
1096
+ # # │ 3.0 ┆ 5 ┆ 7 │
1097
+ # # │ 4.0 ┆ 6 ┆ 8 │
1098
+ # # └─────┴─────┴─────┘
1099
+ #
1100
+ # @example Match all columns *except* for those starting with 'b':
1101
+ # df.select(~Polars.cs.starts_with("b"))
1102
+ # # =>
1103
+ # # shape: (2, 2)
1104
+ # # ┌─────┬─────┐
1105
+ # # │ foo ┆ zap │
1106
+ # # │ --- ┆ --- │
1107
+ # # │ f64 ┆ i64 │
1108
+ # # ╞═════╪═════╡
1109
+ # # │ 1.0 ┆ 7 │
1110
+ # # │ 2.0 ┆ 8 │
1111
+ # # └─────┴─────┘
1112
+ def self.starts_with(*prefix)
1113
+ escaped_prefix = _re_string(prefix)
1114
+ raw_params = "^#{escaped_prefix}.*$"
1115
+
1116
+ _selector_proxy_(
1117
+ F.col(raw_params),
1118
+ name: "starts_with",
1119
+ parameters: {"*prefix" => prefix}
1120
+ )
1121
+ end
1122
+
1123
+ # Select all String (and, optionally, Categorical) string columns.
1124
+ #
1125
+ # @return [SelectorProxy]
1126
+ #
1127
+ # @example
1128
+ # df = Polars::DataFrame.new(
1129
+ # {
1130
+ # "w" => ["xx", "yy", "xx", "yy", "xx"],
1131
+ # "x" => [1, 2, 1, 4, -2],
1132
+ # "y" => [3.0, 4.5, 1.0, 2.5, -2.0],
1133
+ # "z" => ["a", "b", "a", "b", "b"]
1134
+ # },
1135
+ # ).with_columns(
1136
+ # z: Polars.col("z").cast(Polars::Categorical.new("lexical")),
1137
+ # )
1138
+ #
1139
+ # @example Group by all string columns, sum the numeric columns, then sort by the string cols:
1140
+ # >>> df.group_by(Polars.cs.string).agg(Polars.cs.numeric.sum).sort(Polars.cs.string)
1141
+ # shape: (2, 3)
1142
+ # ┌─────┬─────┬─────┐
1143
+ # │ w ┆ x ┆ y │
1144
+ # │ --- ┆ --- ┆ --- │
1145
+ # │ str ┆ i64 ┆ f64 │
1146
+ # ╞═════╪═════╪═════╡
1147
+ # │ xx ┆ 0 ┆ 2.0 │
1148
+ # │ yy ┆ 6 ┆ 7.0 │
1149
+ # └─────┴─────┴─────┘
1150
+ #
1151
+ # @example Group by all string *and* categorical columns:
1152
+ # df.group_by(Polars.cs.string(include_categorical: true)).agg(Polars.cs.numeric.sum).sort(
1153
+ # Polars.cs.string(include_categorical: true)
1154
+ # )
1155
+ # # =>
1156
+ # # shape: (3, 4)
1157
+ # # ┌─────┬─────┬─────┬──────┐
1158
+ # # │ w ┆ z ┆ x ┆ y │
1159
+ # # │ --- ┆ --- ┆ --- ┆ --- │
1160
+ # # │ str ┆ cat ┆ i64 ┆ f64 │
1161
+ # # ╞═════╪═════╪═════╪══════╡
1162
+ # # │ xx ┆ a ┆ 2 ┆ 4.0 │
1163
+ # # │ xx ┆ b ┆ -2 ┆ -2.0 │
1164
+ # # │ yy ┆ b ┆ 6 ┆ 7.0 │
1165
+ # # └─────┴─────┴─────┴──────┘
1166
+ def self.string(include_categorical: false)
1167
+ string_dtypes = [String]
1168
+ if include_categorical
1169
+ string_dtypes << Categorical
1170
+ end
1171
+
1172
+ _selector_proxy_(
1173
+ F.col(string_dtypes),
1174
+ name: "string",
1175
+ parameters: {"include_categorical" => include_categorical},
1176
+ )
1177
+ end
1178
+
1179
+ # Select all time columns.
1180
+ #
1181
+ # @return [SelectorProxy]
1182
+ #
1183
+ # @example
1184
+ # df = Polars::DataFrame.new(
1185
+ # {
1186
+ # "dtm" => [DateTime.new(2001, 5, 7, 10, 25), DateTime.new(2031, 12, 31, 0, 30)],
1187
+ # "dt" => [Date.new(1999, 12, 31), Date.new(2024, 8, 9)],
1188
+ # "tm" => [Time.utc(2001, 1, 1, 0, 0, 0), Time.utc(2001, 1, 1, 23, 59, 59)]
1189
+ # },
1190
+ # schema_overrides: {"tm" => Polars::Time}
1191
+ # )
1192
+ #
1193
+ # @example Select all time columns:
1194
+ # df.select(Polars.cs.time)
1195
+ # # =>
1196
+ # # shape: (2, 1)
1197
+ # # ┌──────────┐
1198
+ # # │ tm │
1199
+ # # │ --- │
1200
+ # # │ time │
1201
+ # # ╞══════════╡
1202
+ # # │ 00:00:00 │
1203
+ # # │ 23:59:59 │
1204
+ # # └──────────┘
1205
+ #
1206
+ # @example Select all columns *except* for those that are times:
1207
+ # df.select(~Polars.cs.time)
1208
+ # # =>
1209
+ # # shape: (2, 2)
1210
+ # # ┌─────────────────────┬────────────┐
1211
+ # # │ dtm ┆ dt │
1212
+ # # │ --- ┆ --- │
1213
+ # # │ datetime[ns] ┆ date │
1214
+ # # ╞═════════════════════╪════════════╡
1215
+ # # │ 2001-05-07 10:25:00 ┆ 1999-12-31 │
1216
+ # # │ 2031-12-31 00:30:00 ┆ 2024-08-09 │
1217
+ # # └─────────────────────┴────────────┘
1218
+ def self.time
1219
+ _selector_proxy_(F.col(Time), name: "time")
1220
+ end
1221
+ end
1222
+
1223
+ def self.cs
1224
+ Polars::Selectors
1225
+ end
1226
+ end