polars-df 0.1.1 → 0.1.3

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/.yardopts +3 -0
  3. data/CHANGELOG.md +8 -0
  4. data/Cargo.lock +2 -1
  5. data/README.md +1 -1
  6. data/ext/polars/Cargo.toml +7 -1
  7. data/ext/polars/src/batched_csv.rs +120 -0
  8. data/ext/polars/src/conversion.rs +139 -6
  9. data/ext/polars/src/dataframe.rs +360 -15
  10. data/ext/polars/src/error.rs +9 -0
  11. data/ext/polars/src/file.rs +8 -7
  12. data/ext/polars/src/lazy/apply.rs +7 -0
  13. data/ext/polars/src/lazy/dataframe.rs +135 -3
  14. data/ext/polars/src/lazy/dsl.rs +97 -2
  15. data/ext/polars/src/lazy/meta.rs +1 -1
  16. data/ext/polars/src/lazy/mod.rs +1 -0
  17. data/ext/polars/src/lib.rs +227 -12
  18. data/ext/polars/src/series.rs +190 -38
  19. data/ext/polars/src/set.rs +91 -0
  20. data/ext/polars/src/utils.rs +19 -0
  21. data/lib/polars/batched_csv_reader.rb +96 -0
  22. data/lib/polars/cat_expr.rb +39 -0
  23. data/lib/polars/data_frame.rb +2813 -100
  24. data/lib/polars/date_time_expr.rb +1282 -7
  25. data/lib/polars/exceptions.rb +20 -0
  26. data/lib/polars/expr.rb +631 -11
  27. data/lib/polars/expr_dispatch.rb +14 -0
  28. data/lib/polars/functions.rb +219 -0
  29. data/lib/polars/group_by.rb +517 -0
  30. data/lib/polars/io.rb +763 -4
  31. data/lib/polars/lazy_frame.rb +1415 -67
  32. data/lib/polars/lazy_functions.rb +430 -9
  33. data/lib/polars/lazy_group_by.rb +79 -0
  34. data/lib/polars/list_expr.rb +5 -0
  35. data/lib/polars/meta_expr.rb +21 -0
  36. data/lib/polars/series.rb +2244 -192
  37. data/lib/polars/slice.rb +104 -0
  38. data/lib/polars/string_expr.rb +663 -2
  39. data/lib/polars/struct_expr.rb +73 -0
  40. data/lib/polars/utils.rb +76 -3
  41. data/lib/polars/version.rb +2 -1
  42. data/lib/polars/when.rb +1 -0
  43. data/lib/polars/when_then.rb +1 -0
  44. data/lib/polars.rb +8 -2
  45. metadata +12 -2
@@ -0,0 +1,517 @@
1
+ module Polars
2
+ class GroupBy
3
+ # @private
4
+ attr_accessor :_df, :_dataframe_class, :by, :maintain_order
5
+
6
+ # @private
7
+ def initialize(df, by, dataframe_class, maintain_order: false)
8
+ self._df = df
9
+ self._dataframe_class = dataframe_class
10
+ self.by = by
11
+ self.maintain_order = maintain_order
12
+ end
13
+
14
+ # def apply
15
+ # end
16
+
17
+ # Use multiple aggregations on columns.
18
+ #
19
+ # This can be combined with complete lazy API and is considered idiomatic polars.
20
+ #
21
+ # @param aggs [Object]
22
+ # Single / multiple aggregation expression(s).
23
+ #
24
+ # @return [DataFrame]
25
+ #
26
+ # @example
27
+ # df = Polars::DataFrame.new(
28
+ # {"foo" => ["one", "two", "two", "one", "two"], "bar" => [5, 3, 2, 4, 1]}
29
+ # )
30
+ # df.groupby("foo", maintain_order: true).agg(
31
+ # [
32
+ # Polars.sum("bar").suffix("_sum"),
33
+ # Polars.col("bar").sort.tail(2).sum.suffix("_tail_sum")
34
+ # ]
35
+ # )
36
+ # # =>
37
+ # # shape: (2, 3)
38
+ # # ┌─────┬─────────┬──────────────┐
39
+ # # │ foo ┆ bar_sum ┆ bar_tail_sum │
40
+ # # │ --- ┆ --- ┆ --- │
41
+ # # │ str ┆ i64 ┆ i64 │
42
+ # # ╞═════╪═════════╪══════════════╡
43
+ # # │ one ┆ 9 ┆ 9 │
44
+ # # ├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
45
+ # # │ two ┆ 6 ┆ 5 │
46
+ # # └─────┴─────────┴──────────────┘
47
+ def agg(aggs)
48
+ df = Utils.wrap_df(_df)
49
+ .lazy
50
+ .groupby(by, maintain_order: maintain_order)
51
+ .agg(aggs)
52
+ .collect(no_optimization: true, string_cache: false)
53
+ _dataframe_class._from_rbdf(df._df)
54
+ end
55
+
56
+ # Get the first `n` rows of each group.
57
+ #
58
+ # @param n [Integer]
59
+ # Number of rows to return.
60
+ #
61
+ # @return [DataFrame]
62
+ #
63
+ # @example
64
+ # df = Polars::DataFrame.new(
65
+ # {
66
+ # "letters" => ["c", "c", "a", "c", "a", "b"],
67
+ # "nrs" => [1, 2, 3, 4, 5, 6]
68
+ # }
69
+ # )
70
+ # # =>
71
+ # # shape: (6, 2)
72
+ # # ┌─────────┬─────┐
73
+ # # │ letters ┆ nrs │
74
+ # # │ --- ┆ --- │
75
+ # # │ str ┆ i64 │
76
+ # # ╞═════════╪═════╡
77
+ # # │ c ┆ 1 │
78
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
79
+ # # │ c ┆ 2 │
80
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
81
+ # # │ a ┆ 3 │
82
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
83
+ # # │ c ┆ 4 │
84
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
85
+ # # │ a ┆ 5 │
86
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
87
+ # # │ b ┆ 6 │
88
+ # # └─────────┴─────┘
89
+ #
90
+ # @example
91
+ # df.groupby("letters").head(2).sort("letters")
92
+ # # =>
93
+ # # shape: (5, 2)
94
+ # # ┌─────────┬─────┐
95
+ # # │ letters ┆ nrs │
96
+ # # │ --- ┆ --- │
97
+ # # │ str ┆ i64 │
98
+ # # ╞═════════╪═════╡
99
+ # # │ a ┆ 3 │
100
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
101
+ # # │ a ┆ 5 │
102
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
103
+ # # │ b ┆ 6 │
104
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
105
+ # # │ c ┆ 1 │
106
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
107
+ # # │ c ┆ 2 │
108
+ # # └─────────┴─────┘
109
+ def head(n = 5)
110
+ df = (
111
+ Utils.wrap_df(_df)
112
+ .lazy
113
+ .groupby(by, maintain_order: maintain_order)
114
+ .head(n)
115
+ .collect(no_optimization: true, string_cache: false)
116
+ )
117
+ _dataframe_class._from_rbdf(df._df)
118
+ end
119
+
120
+ # Get the last `n` rows of each group.
121
+ #
122
+ # @param n [Integer]
123
+ # Number of rows to return.
124
+ #
125
+ # @return [DataFrame]
126
+ #
127
+ # @example
128
+ # df = Polars::DataFrame.new(
129
+ # {
130
+ # "letters" => ["c", "c", "a", "c", "a", "b"],
131
+ # "nrs" => [1, 2, 3, 4, 5, 6]
132
+ # }
133
+ # )
134
+ # # =>
135
+ # # shape: (6, 2)
136
+ # # ┌─────────┬─────┐
137
+ # # │ letters ┆ nrs │
138
+ # # │ --- ┆ --- │
139
+ # # │ str ┆ i64 │
140
+ # # ╞═════════╪═════╡
141
+ # # │ c ┆ 1 │
142
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
143
+ # # │ c ┆ 2 │
144
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
145
+ # # │ a ┆ 3 │
146
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
147
+ # # │ c ┆ 4 │
148
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
149
+ # # │ a ┆ 5 │
150
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
151
+ # # │ b ┆ 6 │
152
+ # # └─────────┴─────┘
153
+ #
154
+ # @example
155
+ # df.groupby("letters").tail(2).sort("letters")
156
+ # # =>
157
+ # # shape: (5, 2)
158
+ # # ┌─────────┬─────┐
159
+ # # │ letters ┆ nrs │
160
+ # # │ --- ┆ --- │
161
+ # # │ str ┆ i64 │
162
+ # # ╞═════════╪═════╡
163
+ # # │ a ┆ 3 │
164
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
165
+ # # │ a ┆ 5 │
166
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
167
+ # # │ b ┆ 6 │
168
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
169
+ # # │ c ┆ 2 │
170
+ # # ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤
171
+ # # │ c ┆ 4 │
172
+ # # └─────────┴─────┘
173
+ def tail(n = 5)
174
+ df = (
175
+ Utils.wrap_df(_df)
176
+ .lazy
177
+ .groupby(by, maintain_order: maintain_order)
178
+ .tail(n)
179
+ .collect(no_optimization: true, string_cache: false)
180
+ )
181
+ _dataframe_class._from_rbdf(df._df)
182
+ end
183
+
184
+ # def pivot
185
+ # end
186
+
187
+ # Aggregate the first values in the group.
188
+ #
189
+ # @return [DataFrame]
190
+ #
191
+ # @example
192
+ # df = Polars::DataFrame.new(
193
+ # {
194
+ # "a" => [1, 2, 2, 3, 4, 5],
195
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
196
+ # "c" => [true, true, true, false, false, true],
197
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
198
+ # }
199
+ # )
200
+ # df.groupby("d", maintain_order: true).first
201
+ # # =>
202
+ # # shape: (3, 4)
203
+ # # ┌────────┬─────┬──────┬───────┐
204
+ # # │ d ┆ a ┆ b ┆ c │
205
+ # # │ --- ┆ --- ┆ --- ┆ --- │
206
+ # # │ str ┆ i64 ┆ f64 ┆ bool │
207
+ # # ╞════════╪═════╪══════╪═══════╡
208
+ # # │ Apple ┆ 1 ┆ 0.5 ┆ true │
209
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
210
+ # # │ Orange ┆ 2 ┆ 0.5 ┆ true │
211
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
212
+ # # │ Banana ┆ 4 ┆ 13.0 ┆ false │
213
+ # # └────────┴─────┴──────┴───────┘
214
+ def first
215
+ agg(Polars.all.first)
216
+ end
217
+
218
+ # Aggregate the last values in the group.
219
+ #
220
+ # @return [DataFrame]
221
+ #
222
+ # @example
223
+ # df = Polars::DataFrame.new(
224
+ # {
225
+ # "a" => [1, 2, 2, 3, 4, 5],
226
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
227
+ # "c" => [true, true, true, false, false, true],
228
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
229
+ # }
230
+ # )
231
+ # df.groupby("d", maintain_order: true).last
232
+ # # =>
233
+ # # shape: (3, 4)
234
+ # # ┌────────┬─────┬──────┬───────┐
235
+ # # │ d ┆ a ┆ b ┆ c │
236
+ # # │ --- ┆ --- ┆ --- ┆ --- │
237
+ # # │ str ┆ i64 ┆ f64 ┆ bool │
238
+ # # ╞════════╪═════╪══════╪═══════╡
239
+ # # │ Apple ┆ 3 ┆ 10.0 ┆ false │
240
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
241
+ # # │ Orange ┆ 2 ┆ 0.5 ┆ true │
242
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
243
+ # # │ Banana ┆ 5 ┆ 14.0 ┆ true │
244
+ # # └────────┴─────┴──────┴───────┘
245
+ def last
246
+ agg(Polars.all.last)
247
+ end
248
+
249
+ # Reduce the groups to the sum.
250
+ #
251
+ # @return [DataFrame]
252
+ #
253
+ # @example
254
+ # df = Polars::DataFrame.new(
255
+ # {
256
+ # "a" => [1, 2, 2, 3, 4, 5],
257
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
258
+ # "c" => [true, true, true, false, false, true],
259
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
260
+ # }
261
+ # )
262
+ # df.groupby("d", maintain_order: true).sum
263
+ # # =>
264
+ # # shape: (3, 4)
265
+ # # ┌────────┬─────┬──────┬─────┐
266
+ # # │ d ┆ a ┆ b ┆ c │
267
+ # # │ --- ┆ --- ┆ --- ┆ --- │
268
+ # # │ str ┆ i64 ┆ f64 ┆ u32 │
269
+ # # ╞════════╪═════╪══════╪═════╡
270
+ # # │ Apple ┆ 6 ┆ 14.5 ┆ 2 │
271
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
272
+ # # │ Orange ┆ 2 ┆ 0.5 ┆ 1 │
273
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
274
+ # # │ Banana ┆ 9 ┆ 27.0 ┆ 1 │
275
+ # # └────────┴─────┴──────┴─────┘
276
+ def sum
277
+ agg(Polars.all.sum)
278
+ end
279
+
280
+ # Reduce the groups to the minimal value.
281
+ #
282
+ # @return [DataFrame]
283
+ #
284
+ # @example
285
+ # df = Polars::DataFrame.new(
286
+ # {
287
+ # "a" => [1, 2, 2, 3, 4, 5],
288
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
289
+ # "c" => [true, true, true, false, false, true],
290
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"],
291
+ # }
292
+ # )
293
+ # df.groupby("d", maintain_order: true).min
294
+ # # =>
295
+ # # shape: (3, 4)
296
+ # # ┌────────┬─────┬──────┬─────┐
297
+ # # │ d ┆ a ┆ b ┆ c │
298
+ # # │ --- ┆ --- ┆ --- ┆ --- │
299
+ # # │ str ┆ i64 ┆ f64 ┆ u32 │
300
+ # # ╞════════╪═════╪══════╪═════╡
301
+ # # │ Apple ┆ 1 ┆ 0.5 ┆ 0 │
302
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
303
+ # # │ Orange ┆ 2 ┆ 0.5 ┆ 1 │
304
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
305
+ # # │ Banana ┆ 4 ┆ 13.0 ┆ 0 │
306
+ # # └────────┴─────┴──────┴─────┘
307
+ def min
308
+ agg(Polars.all.min)
309
+ end
310
+
311
+ # Reduce the groups to the maximal value.
312
+ #
313
+ # @return [DataFrame]
314
+ #
315
+ # @example
316
+ # df = Polars::DataFrame.new(
317
+ # {
318
+ # "a" => [1, 2, 2, 3, 4, 5],
319
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
320
+ # "c" => [true, true, true, false, false, true],
321
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
322
+ # }
323
+ # )
324
+ # df.groupby("d", maintain_order: true).max
325
+ # # =>
326
+ # # shape: (3, 4)
327
+ # # ┌────────┬─────┬──────┬─────┐
328
+ # # │ d ┆ a ┆ b ┆ c │
329
+ # # │ --- ┆ --- ┆ --- ┆ --- │
330
+ # # │ str ┆ i64 ┆ f64 ┆ u32 │
331
+ # # ╞════════╪═════╪══════╪═════╡
332
+ # # │ Apple ┆ 3 ┆ 10.0 ┆ 1 │
333
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
334
+ # # │ Orange ┆ 2 ┆ 0.5 ┆ 1 │
335
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
336
+ # # │ Banana ┆ 5 ┆ 14.0 ┆ 1 │
337
+ # # └────────┴─────┴──────┴─────┘
338
+ def max
339
+ agg(Polars.all.max)
340
+ end
341
+
342
+ # Count the number of values in each group.
343
+ #
344
+ # @return [DataFrame]
345
+ #
346
+ # @example
347
+ # df = Polars::DataFrame.new(
348
+ # {
349
+ # "a" => [1, 2, 2, 3, 4, 5],
350
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
351
+ # "c" => [true, true, true, false, false, true],
352
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
353
+ # }
354
+ # )
355
+ # df.groupby("d", maintain_order: true).count
356
+ # # =>
357
+ # # shape: (3, 2)
358
+ # # ┌────────┬───────┐
359
+ # # │ d ┆ count │
360
+ # # │ --- ┆ --- │
361
+ # # │ str ┆ u32 │
362
+ # # ╞════════╪═══════╡
363
+ # # │ Apple ┆ 3 │
364
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
365
+ # # │ Orange ┆ 1 │
366
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
367
+ # # │ Banana ┆ 2 │
368
+ # # └────────┴───────┘
369
+ def count
370
+ agg(Polars.count)
371
+ end
372
+
373
+ # Reduce the groups to the mean values.
374
+ #
375
+ # @return [DataFrame]
376
+ #
377
+ # @example
378
+ # df = Polars::DataFrame.new(
379
+ # {
380
+ # "a" => [1, 2, 2, 3, 4, 5],
381
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
382
+ # "c" => [true, true, true, false, false, true],
383
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
384
+ # }
385
+ # )
386
+ # df.groupby("d", maintain_order: true).mean
387
+ # # =>
388
+ # # shape: (3, 4)
389
+ # # ┌────────┬─────┬──────────┬──────┐
390
+ # # │ d ┆ a ┆ b ┆ c │
391
+ # # │ --- ┆ --- ┆ --- ┆ --- │
392
+ # # │ str ┆ f64 ┆ f64 ┆ bool │
393
+ # # ╞════════╪═════╪══════════╪══════╡
394
+ # # │ Apple ┆ 2.0 ┆ 4.833333 ┆ null │
395
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┤
396
+ # # │ Orange ┆ 2.0 ┆ 0.5 ┆ null │
397
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┤
398
+ # # │ Banana ┆ 4.5 ┆ 13.5 ┆ null │
399
+ # # └────────┴─────┴──────────┴──────┘
400
+ def mean
401
+ agg(Polars.all.mean)
402
+ end
403
+
404
+ # Count the unique values per group.
405
+ #
406
+ # @return [DataFrame]
407
+ #
408
+ # @example
409
+ # df = Polars::DataFrame.new(
410
+ # {
411
+ # "a" => [1, 2, 1, 3, 4, 5],
412
+ # "b" => [0.5, 0.5, 0.5, 10, 13, 14],
413
+ # "d" => ["Apple", "Banana", "Apple", "Apple", "Banana", "Banana"]
414
+ # }
415
+ # )
416
+ # df.groupby("d", maintain_order: true).n_unique
417
+ # # =>
418
+ # # shape: (2, 3)
419
+ # # ┌────────┬─────┬─────┐
420
+ # # │ d ┆ a ┆ b │
421
+ # # │ --- ┆ --- ┆ --- │
422
+ # # │ str ┆ u32 ┆ u32 │
423
+ # # ╞════════╪═════╪═════╡
424
+ # # │ Apple ┆ 2 ┆ 2 │
425
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
426
+ # # │ Banana ┆ 3 ┆ 3 │
427
+ # # └────────┴─────┴─────┘
428
+ def n_unique
429
+ agg(Polars.all.n_unique)
430
+ end
431
+
432
+ # Compute the quantile per group.
433
+ #
434
+ # @param quantile [Float]
435
+ # Quantile between 0.0 and 1.0.
436
+ # @param interpolation ["nearest", "higher", "lower", "midpoint", "linear"]
437
+ # Interpolation method.
438
+ #
439
+ # @return [DataFrame]
440
+ #
441
+ # @example
442
+ # df = Polars::DataFrame.new(
443
+ # {
444
+ # "a" => [1, 2, 2, 3, 4, 5],
445
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
446
+ # "d" => ["Apple", "Orange", "Apple", "Apple", "Banana", "Banana"]
447
+ # }
448
+ # )
449
+ # df.groupby("d", maintain_order: true).quantile(1)
450
+ # # =>
451
+ # # shape: (3, 3)
452
+ # # ┌────────┬─────┬──────┐
453
+ # # │ d ┆ a ┆ b │
454
+ # # │ --- ┆ --- ┆ --- │
455
+ # # │ str ┆ f64 ┆ f64 │
456
+ # # ╞════════╪═════╪══════╡
457
+ # # │ Apple ┆ 3.0 ┆ 10.0 │
458
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┤
459
+ # # │ Orange ┆ 2.0 ┆ 0.5 │
460
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┤
461
+ # # │ Banana ┆ 5.0 ┆ 14.0 │
462
+ # # └────────┴─────┴──────┘
463
+ def quantile(quantile, interpolation: "nearest")
464
+ agg(Polars.all.quantile(quantile, interpolation: interpolation))
465
+ end
466
+
467
+ # Return the median per group.
468
+ #
469
+ # @return [DataFrame]
470
+ #
471
+ # @example
472
+ # df = Polars::DataFrame.new(
473
+ # {
474
+ # "a" => [1, 2, 2, 3, 4, 5],
475
+ # "b" => [0.5, 0.5, 4, 10, 13, 14],
476
+ # "d" => ["Apple", "Banana", "Apple", "Apple", "Banana", "Banana"]
477
+ # }
478
+ # )
479
+ # df.groupby("d", maintain_order: true).median
480
+ # # =>
481
+ # # shape: (2, 3)
482
+ # # ┌────────┬─────┬──────┐
483
+ # # │ d ┆ a ┆ b │
484
+ # # │ --- ┆ --- ┆ --- │
485
+ # # │ str ┆ f64 ┆ f64 │
486
+ # # ╞════════╪═════╪══════╡
487
+ # # │ Apple ┆ 2.0 ┆ 4.0 │
488
+ # # ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌┤
489
+ # # │ Banana ┆ 4.0 ┆ 13.0 │
490
+ # # └────────┴─────┴──────┘
491
+ def median
492
+ agg(Polars.all.median)
493
+ end
494
+
495
+ # Aggregate the groups into Series.
496
+ #
497
+ # @return [DataFrame]
498
+ #
499
+ # @example
500
+ # df = Polars::DataFrame.new({"a" => ["one", "two", "one", "two"], "b" => [1, 2, 3, 4]})
501
+ # df.groupby("a", maintain_order: true).agg_list
502
+ # # =>
503
+ # # shape: (2, 2)
504
+ # # ┌─────┬───────────┐
505
+ # # │ a ┆ b │
506
+ # # │ --- ┆ --- │
507
+ # # │ str ┆ list[i64] │
508
+ # # ╞═════╪═══════════╡
509
+ # # │ one ┆ [1, 3] │
510
+ # # ├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
511
+ # # │ two ┆ [2, 4] │
512
+ # # └─────┴───────────┘
513
+ def agg_list
514
+ agg(Polars.all.list)
515
+ end
516
+ end
517
+ end