polars-df 0.25.1 → 0.26.1
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 +32 -1
- data/Cargo.lock +278 -106
- data/Cargo.toml +0 -3
- data/LICENSE.txt +1 -1
- data/README.md +7 -3
- data/ext/polars/Cargo.toml +18 -18
- data/ext/polars/src/catalog/unity.rs +15 -20
- data/ext/polars/src/conversion/any_value.rs +25 -24
- data/ext/polars/src/conversion/chunked_array.rs +58 -56
- data/ext/polars/src/conversion/datetime.rs +58 -7
- data/ext/polars/src/conversion/mod.rs +205 -142
- data/ext/polars/src/dataframe/export.rs +15 -12
- data/ext/polars/src/dataframe/general.rs +5 -4
- data/ext/polars/src/dataframe/map.rs +6 -4
- data/ext/polars/src/error.rs +1 -1
- data/ext/polars/src/expr/array.rs +0 -24
- data/ext/polars/src/expr/datatype.rs +3 -2
- data/ext/polars/src/expr/datetime.rs +4 -4
- data/ext/polars/src/expr/general.rs +27 -15
- data/ext/polars/src/expr/list.rs +0 -26
- data/ext/polars/src/functions/business.rs +2 -2
- data/ext/polars/src/functions/io.rs +4 -3
- data/ext/polars/src/functions/lazy.rs +58 -46
- data/ext/polars/src/functions/meta.rs +6 -5
- data/ext/polars/src/functions/mod.rs +0 -1
- data/ext/polars/src/functions/utils.rs +4 -2
- data/ext/polars/src/interop/arrow/mod.rs +4 -2
- data/ext/polars/src/interop/arrow/to_rb.rs +17 -12
- data/ext/polars/src/interop/numo/to_numo_series.rs +26 -25
- data/ext/polars/src/io/scan_options.rs +6 -3
- data/ext/polars/src/io/sink_options.rs +2 -0
- data/ext/polars/src/lazyframe/general.rs +32 -16
- data/ext/polars/src/lazyframe/optflags.rs +2 -1
- data/ext/polars/src/lib.rs +21 -37
- data/ext/polars/src/map/lazy.rs +5 -2
- data/ext/polars/src/map/series.rs +19 -18
- data/ext/polars/src/on_startup.rs +16 -7
- data/ext/polars/src/ruby/capsule.rs +27 -0
- data/ext/polars/src/ruby/mod.rs +1 -0
- data/ext/polars/src/ruby/numo.rs +3 -4
- data/ext/polars/src/ruby/rb_modules.rs +2 -4
- data/ext/polars/src/ruby/ruby_udf.rs +7 -9
- data/ext/polars/src/ruby/utils.rs +12 -1
- data/ext/polars/src/series/aggregation.rs +13 -1
- data/ext/polars/src/series/export.rs +38 -38
- data/ext/polars/src/series/general.rs +4 -3
- data/ext/polars/src/series/map.rs +3 -2
- data/ext/polars/src/series/scatter.rs +4 -4
- data/ext/polars/src/utils.rs +31 -7
- data/lib/polars/array_expr.rb +23 -7
- data/lib/polars/array_name_space.rb +16 -2
- data/lib/polars/binary_name_space.rb +32 -0
- data/lib/polars/data_frame.rb +83 -11
- data/lib/polars/date_time_expr.rb +91 -3
- data/lib/polars/date_time_name_space.rb +7 -1
- data/lib/polars/expr.rb +122 -44
- data/lib/polars/functions/aggregation/horizontal.rb +4 -4
- data/lib/polars/functions/business.rb +2 -2
- data/lib/polars/functions/eager.rb +80 -7
- data/lib/polars/functions/lazy.rb +5 -2
- data/lib/polars/iceberg_dataset.rb +81 -14
- data/lib/polars/io/csv.rb +27 -5
- data/lib/polars/io/delta.rb +4 -0
- data/lib/polars/io/ipc.rb +1 -1
- data/lib/polars/io/lines.rb +4 -4
- data/lib/polars/io/sink_options.rb +4 -2
- data/lib/polars/lazy_frame.rb +97 -14
- data/lib/polars/list_expr.rb +21 -7
- data/lib/polars/list_name_space.rb +16 -2
- data/lib/polars/query_opt_flags.rb +22 -5
- data/lib/polars/schema.rb +9 -0
- data/lib/polars/selectors.rb +1 -1
- data/lib/polars/series.rb +106 -19
- data/lib/polars/sql_context.rb +2 -2
- data/lib/polars/string_cache.rb +19 -72
- data/lib/polars/string_expr.rb +1 -7
- data/lib/polars/string_name_space.rb +1 -7
- data/lib/polars/utils/construction/series.rb +8 -3
- data/lib/polars/utils/convert.rb +16 -6
- data/lib/polars/utils/parse.rb +7 -0
- data/lib/polars/utils/reduce_balanced.rb +43 -0
- data/lib/polars/utils/various.rb +5 -0
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +5 -1
- metadata +4 -17
- data/ext/polars/src/functions/string_cache.rs +0 -24
|
@@ -242,10 +242,10 @@ module Polars
|
|
|
242
242
|
rbexprs = Utils.parse_into_list_of_expressions(*exprs)
|
|
243
243
|
exprs_wrapped = rbexprs.map { |e| Utils.wrap_expr(e) }
|
|
244
244
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
245
|
+
Polars.cum_fold(
|
|
246
|
+
Polars.lit(0).cast(Polars.dtype_of(Polars.sum_horizontal(exprs))),
|
|
247
|
+
exprs_wrapped
|
|
248
|
+
) { |a, b| a + b }.alias("cum_sum")
|
|
249
249
|
end
|
|
250
250
|
end
|
|
251
251
|
end
|
|
@@ -81,13 +81,13 @@ module Polars
|
|
|
81
81
|
)
|
|
82
82
|
start_rbexpr = Utils.parse_into_expression(start)
|
|
83
83
|
end_rbexpr = Utils.parse_into_expression(stop)
|
|
84
|
-
|
|
84
|
+
holidays_rbexpr = Utils._holidays_to_expr(holidays)
|
|
85
85
|
Utils.wrap_expr(
|
|
86
86
|
Plr.business_day_count(
|
|
87
87
|
start_rbexpr,
|
|
88
88
|
end_rbexpr,
|
|
89
89
|
week_mask,
|
|
90
|
-
|
|
90
|
+
holidays_rbexpr
|
|
91
91
|
)
|
|
92
92
|
)
|
|
93
93
|
end
|
|
@@ -399,6 +399,85 @@ module Polars
|
|
|
399
399
|
out
|
|
400
400
|
end
|
|
401
401
|
|
|
402
|
+
# Merge multiple sorted DataFrames or LazyFrames by the sorted key.
|
|
403
|
+
#
|
|
404
|
+
# The output of this operation will also be sorted.
|
|
405
|
+
# It is the callers responsibility that the frames
|
|
406
|
+
# are sorted in ascending order by that key otherwise
|
|
407
|
+
# the output will not make sense.
|
|
408
|
+
#
|
|
409
|
+
# @note
|
|
410
|
+
# This functionality is considered **unstable**. It may be changed
|
|
411
|
+
# at any point without it being considered a breaking change.
|
|
412
|
+
#
|
|
413
|
+
# @param items [Array]
|
|
414
|
+
# DataFrames or LazyFrames to merge.
|
|
415
|
+
# @param key [String]
|
|
416
|
+
# Key that is sorted.
|
|
417
|
+
# @param maintain_order [Boolean]
|
|
418
|
+
# If `true`, the output is guaranteed to have left-biased ordering
|
|
419
|
+
# for equal keys: rows from the left frame appear before rows from
|
|
420
|
+
# the right frame when their keys are equal.
|
|
421
|
+
#
|
|
422
|
+
# @return [Object]
|
|
423
|
+
#
|
|
424
|
+
# @example
|
|
425
|
+
# df0 = Polars::DataFrame.new(
|
|
426
|
+
# {"name" => ["steve", "elise", "bob"], "age" => [42, 44, 18]}
|
|
427
|
+
# ).sort("age")
|
|
428
|
+
# df1 = Polars::DataFrame.new(
|
|
429
|
+
# {"name" => ["anna", "megan", "steve", "thomas"], "age" => [21, 33, 17, 20]}
|
|
430
|
+
# ).sort("age")
|
|
431
|
+
# df2 = Polars::DataFrame.new({"name" => ["ida", "maya"], "age" => [37, 27]}).sort("age")
|
|
432
|
+
# Polars.merge_sorted([df0, df1, df2], "age")
|
|
433
|
+
# # =>
|
|
434
|
+
# # shape: (9, 2)
|
|
435
|
+
# # ┌────────┬─────┐
|
|
436
|
+
# # │ name ┆ age │
|
|
437
|
+
# # │ --- ┆ --- │
|
|
438
|
+
# # │ str ┆ i64 │
|
|
439
|
+
# # ╞════════╪═════╡
|
|
440
|
+
# # │ steve ┆ 17 │
|
|
441
|
+
# # │ bob ┆ 18 │
|
|
442
|
+
# # │ thomas ┆ 20 │
|
|
443
|
+
# # │ anna ┆ 21 │
|
|
444
|
+
# # │ maya ┆ 27 │
|
|
445
|
+
# # │ megan ┆ 33 │
|
|
446
|
+
# # │ ida ┆ 37 │
|
|
447
|
+
# # │ steve ┆ 42 │
|
|
448
|
+
# # │ elise ┆ 44 │
|
|
449
|
+
# # └────────┴─────┘
|
|
450
|
+
def merge_sorted(
|
|
451
|
+
items,
|
|
452
|
+
key,
|
|
453
|
+
maintain_order: false
|
|
454
|
+
)
|
|
455
|
+
elems = items.to_a
|
|
456
|
+
|
|
457
|
+
if elems.empty?
|
|
458
|
+
msg = "cannot merge_sort empty list"
|
|
459
|
+
raise ArgumentError, msg
|
|
460
|
+
end
|
|
461
|
+
if elems.length == 1 && (elems[0].is_a?(DataFrame) || elems[0].is_a?(LazyFrame))
|
|
462
|
+
return elems[0]
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
if !Utils.is_non_empty_sequence_of(elems, DataFrame) && !Utils.is_non_empty_sequence_of(elems, LazyFrame)
|
|
466
|
+
msg = "merge_sorted is not supported for #{elems[0].inspect}"
|
|
467
|
+
raise TypeError, msg
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
frames = elems.map { |df| df.lazy }
|
|
471
|
+
|
|
472
|
+
reduce_fn = lambda do |x, y|
|
|
473
|
+
x.merge_sorted(y, key, maintain_order: maintain_order)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
lf = Utils.reduce_balanced(reduce_fn, frames)
|
|
477
|
+
eager = elems[0].is_a?(DataFrame)
|
|
478
|
+
eager ? lf.collect : lf
|
|
479
|
+
end
|
|
480
|
+
|
|
402
481
|
# Align an array of frames using the unique values from one or more columns as a key.
|
|
403
482
|
#
|
|
404
483
|
# Frames that do not contain the given key values have rows injected (with nulls
|
|
@@ -464,16 +543,10 @@ module Polars
|
|
|
464
543
|
def align_frames(
|
|
465
544
|
*frames,
|
|
466
545
|
on:,
|
|
467
|
-
how:
|
|
546
|
+
how: "full",
|
|
468
547
|
select: nil,
|
|
469
548
|
descending: false
|
|
470
549
|
)
|
|
471
|
-
# TODO update
|
|
472
|
-
if how.nil?
|
|
473
|
-
warn "The default `how` for `align_frames` method will change from `left` to `full` in a future version"
|
|
474
|
-
how = "left"
|
|
475
|
-
end
|
|
476
|
-
|
|
477
550
|
if frames.empty?
|
|
478
551
|
return []
|
|
479
552
|
elsif frames.map(&:class).uniq.length != 1
|
|
@@ -141,6 +141,9 @@ module Polars
|
|
|
141
141
|
#
|
|
142
142
|
# @param columns [Array]
|
|
143
143
|
# One or more column names.
|
|
144
|
+
# @param maintain_order [Boolean]
|
|
145
|
+
# Whether to preserve the order of elements in the list. Setting this
|
|
146
|
+
# to `false` can improve performance, especially within `group_by`.
|
|
144
147
|
#
|
|
145
148
|
# @return [Expr]
|
|
146
149
|
#
|
|
@@ -174,8 +177,8 @@ module Polars
|
|
|
174
177
|
# # ╞═══════════╪═══════════════════════╡
|
|
175
178
|
# # │ [9, 8, 7] ┆ ["foo", "bar", "foo"] │
|
|
176
179
|
# # └───────────┴───────────────────────┘
|
|
177
|
-
def implode(*columns)
|
|
178
|
-
col(*columns).implode
|
|
180
|
+
def implode(*columns, maintain_order: true)
|
|
181
|
+
col(*columns).implode(maintain_order: maintain_order)
|
|
179
182
|
end
|
|
180
183
|
|
|
181
184
|
# Get the standard deviation.
|
|
@@ -17,24 +17,48 @@ module Polars
|
|
|
17
17
|
|
|
18
18
|
table = scan.table
|
|
19
19
|
snapshot = scan.snapshot
|
|
20
|
-
schema = snapshot ? table.schema_by_id(snapshot[:schema_id]) : table.current_schema
|
|
20
|
+
schema = snapshot ? table.schema_by_id(snapshot.is_a?(Hash) ? snapshot[:schema_id] : snapshot.schema_id) : table.current_schema
|
|
21
21
|
|
|
22
|
-
if files.empty?
|
|
23
|
-
# TODO
|
|
22
|
+
if files.empty? && !schema.respond_to?(:arrow_c_schema)
|
|
23
|
+
# TODO remove in 0.27.0
|
|
24
24
|
schema =
|
|
25
25
|
schema.fields.to_h do |field|
|
|
26
26
|
dtype =
|
|
27
27
|
case field[:type]
|
|
28
|
+
when "unknown"
|
|
29
|
+
Unknown
|
|
30
|
+
when "boolean"
|
|
31
|
+
Boolean
|
|
28
32
|
when "int"
|
|
29
|
-
|
|
33
|
+
Int32
|
|
30
34
|
when "long"
|
|
31
|
-
|
|
35
|
+
Int64
|
|
36
|
+
when "float"
|
|
37
|
+
Float32
|
|
32
38
|
when "double"
|
|
33
|
-
|
|
39
|
+
Float64
|
|
40
|
+
when "decimal"
|
|
41
|
+
Decimal.new(field[:precision], field[:scale])
|
|
34
42
|
when "string"
|
|
35
|
-
|
|
43
|
+
String
|
|
44
|
+
when "uuid"
|
|
45
|
+
Binary
|
|
46
|
+
when "fixed"
|
|
47
|
+
Binary
|
|
48
|
+
when "binary"
|
|
49
|
+
Binary
|
|
50
|
+
when "date"
|
|
51
|
+
Date
|
|
52
|
+
when "time"
|
|
53
|
+
Time # ns instead of us since does not support time unit
|
|
36
54
|
when "timestamp"
|
|
37
|
-
|
|
55
|
+
Datetime.new("us")
|
|
56
|
+
when "timestamp_ns"
|
|
57
|
+
Datetime.new("ns")
|
|
58
|
+
when "timestamptz"
|
|
59
|
+
Datetime.new("us", "+00:00")
|
|
60
|
+
when "timestamptz_ns"
|
|
61
|
+
Datetime.new("ns", "+00:00")
|
|
38
62
|
else
|
|
39
63
|
raise Todo
|
|
40
64
|
end
|
|
@@ -44,25 +68,26 @@ module Polars
|
|
|
44
68
|
|
|
45
69
|
LazyFrame.new(schema: schema)
|
|
46
70
|
else
|
|
47
|
-
sources = files.map { |v| v[:data_file_path] }
|
|
71
|
+
sources = files.map { |v| v.is_a?(Hash) ? v[:data_file_path] : v.file.file_path }
|
|
48
72
|
|
|
49
73
|
column_mapping = [
|
|
50
74
|
"iceberg-column-mapping",
|
|
51
|
-
arrow_schema(schema)
|
|
75
|
+
schema.respond_to?(:arrow_c_schema) ? schema : arrow_schema(schema)
|
|
52
76
|
]
|
|
53
77
|
|
|
54
78
|
deletion_files = [
|
|
55
79
|
"iceberg-position-delete",
|
|
56
80
|
files.map.with_index
|
|
57
|
-
.select { |v, i| v[:deletes].any? }
|
|
58
|
-
.to_h { |v, i| [i, v[:deletes].map { |d| d[:file_path] }] }
|
|
81
|
+
.select { |v, i| (v.is_a?(Hash) ? v[:deletes] : v.delete_files).any? }
|
|
82
|
+
.to_h { |v, i| [i, v.is_a?(Hash) ? v[:deletes].map { |d| d[:file_path] } : v.delete_files.map(&:file_path)] }
|
|
59
83
|
]
|
|
60
84
|
|
|
61
85
|
scan_options = {
|
|
62
|
-
|
|
86
|
+
schema: schema.respond_to?(:arrow_c_schema) ? Schema.new(schema) : nil,
|
|
63
87
|
cast_options: Polars::ScanCastOptions._default_iceberg,
|
|
64
88
|
missing_columns: "insert",
|
|
65
89
|
extra_columns: "ignore",
|
|
90
|
+
storage_options: @storage_options,
|
|
66
91
|
_column_mapping: column_mapping,
|
|
67
92
|
_deletion_files: deletion_files
|
|
68
93
|
}
|
|
@@ -73,11 +98,14 @@ module Polars
|
|
|
73
98
|
|
|
74
99
|
private
|
|
75
100
|
|
|
101
|
+
# TODO remove in 0.27.0
|
|
76
102
|
def arrow_schema(schema)
|
|
77
103
|
fields =
|
|
78
104
|
schema.fields.map do |field|
|
|
79
105
|
type =
|
|
80
106
|
case field[:type]
|
|
107
|
+
when "unknown"
|
|
108
|
+
"unknown"
|
|
81
109
|
when "boolean"
|
|
82
110
|
"boolean"
|
|
83
111
|
when "int"
|
|
@@ -88,11 +116,42 @@ module Polars
|
|
|
88
116
|
"float32"
|
|
89
117
|
when "double"
|
|
90
118
|
"float64"
|
|
119
|
+
when "decimal"
|
|
120
|
+
"decimal"
|
|
121
|
+
when "string"
|
|
122
|
+
"string"
|
|
123
|
+
when "uuid"
|
|
124
|
+
limit = 16
|
|
125
|
+
"fixed_size_binary"
|
|
126
|
+
when "fixed"
|
|
127
|
+
limit = field[:limit]
|
|
128
|
+
"fixed_size_binary"
|
|
129
|
+
when "binary"
|
|
130
|
+
"large_binary"
|
|
131
|
+
when "date"
|
|
132
|
+
"date32"
|
|
133
|
+
when "time"
|
|
134
|
+
time_unit = "us"
|
|
135
|
+
"time64"
|
|
136
|
+
when "timestamp"
|
|
137
|
+
time_unit = "us"
|
|
138
|
+
"timestamp"
|
|
139
|
+
when "timestamp_ns"
|
|
140
|
+
time_unit = "ns"
|
|
141
|
+
"timestamp"
|
|
142
|
+
when "timestamptz"
|
|
143
|
+
time_unit = "us"
|
|
144
|
+
time_zone = "+00:00"
|
|
145
|
+
"timestamp"
|
|
146
|
+
when "timestamptz_ns"
|
|
147
|
+
time_unit = "ns"
|
|
148
|
+
time_zone = "+00:00"
|
|
149
|
+
"timestamp"
|
|
91
150
|
else
|
|
92
151
|
raise Todo
|
|
93
152
|
end
|
|
94
153
|
|
|
95
|
-
{
|
|
154
|
+
arrow_field = {
|
|
96
155
|
name: field[:name],
|
|
97
156
|
type: type,
|
|
98
157
|
nullable: !field[:required],
|
|
@@ -100,6 +159,14 @@ module Polars
|
|
|
100
159
|
"PARQUET:field_id" => field[:id].to_s
|
|
101
160
|
}
|
|
102
161
|
}
|
|
162
|
+
arrow_field[:limit] = limit if limit
|
|
163
|
+
if type == "decimal"
|
|
164
|
+
arrow_field[:precision] = field[:precision]
|
|
165
|
+
arrow_field[:scale] = field[:scale]
|
|
166
|
+
end
|
|
167
|
+
arrow_field[:time_unit] = time_unit if time_unit
|
|
168
|
+
arrow_field[:time_zone] = time_zone if time_zone
|
|
169
|
+
arrow_field
|
|
103
170
|
end
|
|
104
171
|
|
|
105
172
|
{fields: fields}
|
data/lib/polars/io/csv.rb
CHANGED
|
@@ -648,6 +648,12 @@ module Polars
|
|
|
648
648
|
# (which defaults to 1 hour) if not given.
|
|
649
649
|
# @param include_file_paths [String]
|
|
650
650
|
# Include the path of the source file(s) as a column with this name.
|
|
651
|
+
# @param missing_columns ['insert', 'raise']
|
|
652
|
+
# Configuration for behavior when columns defined in the schema are
|
|
653
|
+
# missing from the data:
|
|
654
|
+
#
|
|
655
|
+
# * `"insert"`: Insert the missing columns with NULL values.
|
|
656
|
+
# * `"raise"`: Raise an error.
|
|
651
657
|
#
|
|
652
658
|
# @return [LazyFrame]
|
|
653
659
|
def scan_csv(
|
|
@@ -663,7 +669,7 @@ module Polars
|
|
|
663
669
|
null_values: nil,
|
|
664
670
|
missing_utf8_is_empty_string: false,
|
|
665
671
|
ignore_errors: false,
|
|
666
|
-
cache:
|
|
672
|
+
cache: nil,
|
|
667
673
|
with_column_names: nil,
|
|
668
674
|
infer_schema: true,
|
|
669
675
|
infer_schema_length: N_INFER_DEFAULT,
|
|
@@ -685,7 +691,8 @@ module Polars
|
|
|
685
691
|
credential_provider: "auto",
|
|
686
692
|
retries: nil,
|
|
687
693
|
file_cache_ttl: nil,
|
|
688
|
-
include_file_paths: nil
|
|
694
|
+
include_file_paths: nil,
|
|
695
|
+
missing_columns: nil
|
|
689
696
|
)
|
|
690
697
|
if new_columns&.any? && schema_overrides.is_a?(::Array)
|
|
691
698
|
msg = "expected 'schema_overrides' hash, found #{schema_overrides.inspect}"
|
|
@@ -734,6 +741,11 @@ module Polars
|
|
|
734
741
|
storage_options["file_cache_ttl"] = file_cache_ttl
|
|
735
742
|
end
|
|
736
743
|
|
|
744
|
+
if !missing_columns.nil?
|
|
745
|
+
msg = "The `missing_columns` parameter of `scan_csv` is considered unstable."
|
|
746
|
+
Utils.issue_unstable_warning(msg)
|
|
747
|
+
end
|
|
748
|
+
|
|
737
749
|
credential_provider_builder = _init_credential_provider_builder(
|
|
738
750
|
credential_provider, source, storage_options, "scan_csv"
|
|
739
751
|
)
|
|
@@ -768,7 +780,8 @@ module Polars
|
|
|
768
780
|
glob: glob,
|
|
769
781
|
storage_options: storage_options,
|
|
770
782
|
credential_provider: credential_provider_builder,
|
|
771
|
-
include_file_paths: include_file_paths
|
|
783
|
+
include_file_paths: include_file_paths,
|
|
784
|
+
missing_columns: missing_columns
|
|
772
785
|
)
|
|
773
786
|
end
|
|
774
787
|
|
|
@@ -804,7 +817,8 @@ module Polars
|
|
|
804
817
|
glob: true,
|
|
805
818
|
storage_options: nil,
|
|
806
819
|
credential_provider: nil,
|
|
807
|
-
include_file_paths: nil
|
|
820
|
+
include_file_paths: nil,
|
|
821
|
+
missing_columns: nil
|
|
808
822
|
)
|
|
809
823
|
dtype_list = nil
|
|
810
824
|
if !schema_overrides.nil?
|
|
@@ -822,6 +836,13 @@ module Polars
|
|
|
822
836
|
sources = []
|
|
823
837
|
end
|
|
824
838
|
|
|
839
|
+
# TODO: This is a hack. We conditionally set `missing_columns` to mimic
|
|
840
|
+
# existing behavior. This should be removed once the workaround is no
|
|
841
|
+
# longer needed.
|
|
842
|
+
if missing_columns.nil? && !schema.nil? && has_header
|
|
843
|
+
missing_columns = "insert"
|
|
844
|
+
end
|
|
845
|
+
|
|
825
846
|
rblf =
|
|
826
847
|
RbLazyFrame.new_from_csv(
|
|
827
848
|
source,
|
|
@@ -854,7 +875,8 @@ module Polars
|
|
|
854
875
|
schema,
|
|
855
876
|
storage_options,
|
|
856
877
|
credential_provider,
|
|
857
|
-
include_file_paths
|
|
878
|
+
include_file_paths,
|
|
879
|
+
missing_columns
|
|
858
880
|
)
|
|
859
881
|
Utils.wrap_ldf(rblf)
|
|
860
882
|
end
|
data/lib/polars/io/delta.rb
CHANGED
|
@@ -25,6 +25,8 @@ module Polars
|
|
|
25
25
|
storage_options: nil,
|
|
26
26
|
delta_table_options: nil
|
|
27
27
|
)
|
|
28
|
+
require "deltalake-rb"
|
|
29
|
+
|
|
28
30
|
df =
|
|
29
31
|
scan_delta(
|
|
30
32
|
source,
|
|
@@ -62,6 +64,8 @@ module Polars
|
|
|
62
64
|
delta_table_options: nil,
|
|
63
65
|
rechunk: nil
|
|
64
66
|
)
|
|
67
|
+
require "deltalake-rb"
|
|
68
|
+
|
|
65
69
|
dl_tbl =
|
|
66
70
|
_get_delta_lake_table(
|
|
67
71
|
source,
|
data/lib/polars/io/ipc.rb
CHANGED
data/lib/polars/io/lines.rb
CHANGED
|
@@ -49,7 +49,7 @@ module Polars
|
|
|
49
49
|
# # =>
|
|
50
50
|
# # shape: (2, 1)
|
|
51
51
|
# # ┌───────┐
|
|
52
|
-
# # │
|
|
52
|
+
# # │ line │
|
|
53
53
|
# # │ --- │
|
|
54
54
|
# # │ str │
|
|
55
55
|
# # ╞═══════╡
|
|
@@ -58,7 +58,7 @@ module Polars
|
|
|
58
58
|
# # └───────┘
|
|
59
59
|
def read_lines(
|
|
60
60
|
source,
|
|
61
|
-
name: "
|
|
61
|
+
name: "line",
|
|
62
62
|
n_rows: nil,
|
|
63
63
|
row_index_name: nil,
|
|
64
64
|
row_index_offset: 0,
|
|
@@ -129,7 +129,7 @@ module Polars
|
|
|
129
129
|
# # =>
|
|
130
130
|
# # shape: (2, 1)
|
|
131
131
|
# # ┌───────┐
|
|
132
|
-
# # │
|
|
132
|
+
# # │ line │
|
|
133
133
|
# # │ --- │
|
|
134
134
|
# # │ str │
|
|
135
135
|
# # ╞═══════╡
|
|
@@ -138,7 +138,7 @@ module Polars
|
|
|
138
138
|
# # └───────┘
|
|
139
139
|
def scan_lines(
|
|
140
140
|
source,
|
|
141
|
-
name: "
|
|
141
|
+
name: "line",
|
|
142
142
|
n_rows: nil,
|
|
143
143
|
row_index_name: nil,
|
|
144
144
|
row_index_offset: 0,
|
|
@@ -2,20 +2,22 @@ module Polars
|
|
|
2
2
|
module IO
|
|
3
3
|
# @private
|
|
4
4
|
class SinkOptions
|
|
5
|
-
attr_reader :mkdir, :maintain_order, :sync_on_close, :storage_options, :credential_provider
|
|
5
|
+
attr_reader :mkdir, :maintain_order, :sync_on_close, :storage_options, :credential_provider, :sinked_paths_callback
|
|
6
6
|
|
|
7
7
|
def initialize(
|
|
8
8
|
mkdir: nil,
|
|
9
9
|
maintain_order: nil,
|
|
10
10
|
sync_on_close: nil,
|
|
11
11
|
storage_options: nil,
|
|
12
|
-
credential_provider: nil
|
|
12
|
+
credential_provider: nil,
|
|
13
|
+
sinked_paths_callback: nil
|
|
13
14
|
)
|
|
14
15
|
@mkdir = mkdir
|
|
15
16
|
@maintain_order = maintain_order
|
|
16
17
|
@sync_on_close = sync_on_close
|
|
17
18
|
@storage_options = storage_options
|
|
18
19
|
@credential_provider = credential_provider
|
|
20
|
+
@sinked_paths_callback = sinked_paths_callback
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
end
|
data/lib/polars/lazy_frame.rb
CHANGED
|
@@ -1162,7 +1162,8 @@ module Polars
|
|
|
1162
1162
|
lazy: false,
|
|
1163
1163
|
arrow_schema: nil,
|
|
1164
1164
|
engine: "auto",
|
|
1165
|
-
optimizations: DEFAULT_QUERY_OPT_FLAGS
|
|
1165
|
+
optimizations: DEFAULT_QUERY_OPT_FLAGS,
|
|
1166
|
+
_sinked_paths_callback: nil
|
|
1166
1167
|
)
|
|
1167
1168
|
engine = _select_engine(engine)
|
|
1168
1169
|
|
|
@@ -1204,7 +1205,8 @@ module Polars
|
|
|
1204
1205
|
maintain_order: maintain_order,
|
|
1205
1206
|
sync_on_close: sync_on_close,
|
|
1206
1207
|
storage_options: storage_options,
|
|
1207
|
-
credential_provider: credential_provider_builder
|
|
1208
|
+
credential_provider: credential_provider_builder,
|
|
1209
|
+
sinked_paths_callback: _sinked_paths_callback
|
|
1208
1210
|
)
|
|
1209
1211
|
|
|
1210
1212
|
ldf_rb = _ldf.sink_parquet(
|
|
@@ -3479,6 +3481,78 @@ module Polars
|
|
|
3479
3481
|
)
|
|
3480
3482
|
end
|
|
3481
3483
|
|
|
3484
|
+
# Selects rows from this LazyFrame at the given indices.
|
|
3485
|
+
#
|
|
3486
|
+
# @note
|
|
3487
|
+
# This functionality is experimental. It may be
|
|
3488
|
+
# changed at any point without it being considered a breaking change.
|
|
3489
|
+
#
|
|
3490
|
+
# @param indices [Object]
|
|
3491
|
+
# The indices of the rows to select.
|
|
3492
|
+
#
|
|
3493
|
+
# Due to the lack of a `LazySeries` it's permitted to pass a single-width
|
|
3494
|
+
# `LazyFrame` as indices as well.
|
|
3495
|
+
# @param null_on_oob [Boolean]
|
|
3496
|
+
# If true when an index is out-of-bounds a null row will be generated
|
|
3497
|
+
# instead of raising an error.
|
|
3498
|
+
#
|
|
3499
|
+
# @return [LazyFrame]
|
|
3500
|
+
#
|
|
3501
|
+
# @example
|
|
3502
|
+
# lf = Polars::LazyFrame.new({"x" => [2, 1, 0], "s" => ["foo", "bar", "baz"]})
|
|
3503
|
+
# lf.gather([2, 0, 0]).collect
|
|
3504
|
+
# # =>
|
|
3505
|
+
# # shape: (3, 2)
|
|
3506
|
+
# # ┌─────┬─────┐
|
|
3507
|
+
# # │ x ┆ s │
|
|
3508
|
+
# # │ --- ┆ --- │
|
|
3509
|
+
# # │ i64 ┆ str │
|
|
3510
|
+
# # ╞═════╪═════╡
|
|
3511
|
+
# # │ 0 ┆ baz │
|
|
3512
|
+
# # │ 2 ┆ foo │
|
|
3513
|
+
# # │ 2 ┆ foo │
|
|
3514
|
+
# # └─────┴─────┘
|
|
3515
|
+
#
|
|
3516
|
+
# @example
|
|
3517
|
+
# lf.gather([0, 10, 1], null_on_oob: true).collect
|
|
3518
|
+
# # =>
|
|
3519
|
+
# # shape: (3, 2)
|
|
3520
|
+
# # ┌──────┬──────┐
|
|
3521
|
+
# # │ x ┆ s │
|
|
3522
|
+
# # │ --- ┆ --- │
|
|
3523
|
+
# # │ i64 ┆ str │
|
|
3524
|
+
# # ╞══════╪══════╡
|
|
3525
|
+
# # │ 2 ┆ foo │
|
|
3526
|
+
# # │ null ┆ null │
|
|
3527
|
+
# # │ 1 ┆ bar │
|
|
3528
|
+
# # └──────┴──────┘
|
|
3529
|
+
#
|
|
3530
|
+
# @example
|
|
3531
|
+
# idxs = Polars::LazyFrame.new({"i" => [1, 10, 0], "b" => [true, false, true]})
|
|
3532
|
+
# lf.gather(idxs.filter(Polars.col("b")).select(Polars.col("i"))).collect
|
|
3533
|
+
# # =>
|
|
3534
|
+
# # shape: (2, 2)
|
|
3535
|
+
# # ┌─────┬─────┐
|
|
3536
|
+
# # │ x ┆ s │
|
|
3537
|
+
# # │ --- ┆ --- │
|
|
3538
|
+
# # │ i64 ┆ str │
|
|
3539
|
+
# # ╞═════╪═════╡
|
|
3540
|
+
# # │ 1 ┆ bar │
|
|
3541
|
+
# # │ 2 ┆ foo │
|
|
3542
|
+
# # └─────┴─────┘
|
|
3543
|
+
def gather(indices, null_on_oob: false)
|
|
3544
|
+
if !indices.is_a?(LazyFrame)
|
|
3545
|
+
if indices.is_a?(::Array)
|
|
3546
|
+
indices_expr = F.lit(Series.new("", indices, dtype: Int64))
|
|
3547
|
+
else
|
|
3548
|
+
indices_expr = wrap_expr(Utils.parse_into_expression(indices))
|
|
3549
|
+
end
|
|
3550
|
+
indices = select(indices_expr)
|
|
3551
|
+
end
|
|
3552
|
+
|
|
3553
|
+
_from_rbldf(_ldf.gather(indices._ldf, null_on_oob))
|
|
3554
|
+
end
|
|
3555
|
+
|
|
3482
3556
|
# Add or overwrite multiple columns in a DataFrame.
|
|
3483
3557
|
#
|
|
3484
3558
|
# @param exprs [Object]
|
|
@@ -4643,6 +4717,8 @@ module Polars
|
|
|
4643
4717
|
# @param separator [String]
|
|
4644
4718
|
# Used as separator/delimiter in generated column names in case of multiple
|
|
4645
4719
|
# `values` columns.
|
|
4720
|
+
# @param column_naming ['auto', 'combine']
|
|
4721
|
+
# How resulting column names will be constructed.
|
|
4646
4722
|
#
|
|
4647
4723
|
# @return [LazyFrame]
|
|
4648
4724
|
#
|
|
@@ -4682,7 +4758,8 @@ module Polars
|
|
|
4682
4758
|
values: nil,
|
|
4683
4759
|
aggregate_function: nil,
|
|
4684
4760
|
maintain_order: false,
|
|
4685
|
-
separator: "_"
|
|
4761
|
+
separator: "_",
|
|
4762
|
+
column_naming: "auto"
|
|
4686
4763
|
)
|
|
4687
4764
|
if index.nil? && values.nil?
|
|
4688
4765
|
msg = "`pivot` needs either `index or `values` needs to be specified"
|
|
@@ -4756,7 +4833,8 @@ module Polars
|
|
|
4756
4833
|
values_selector._rbselector,
|
|
4757
4834
|
agg._rbexpr,
|
|
4758
4835
|
maintain_order,
|
|
4759
|
-
separator
|
|
4836
|
+
separator,
|
|
4837
|
+
column_naming
|
|
4760
4838
|
)
|
|
4761
4839
|
)
|
|
4762
4840
|
end
|
|
@@ -4772,7 +4850,8 @@ module Polars
|
|
|
4772
4850
|
#
|
|
4773
4851
|
# @param on [Object]
|
|
4774
4852
|
# Column(s) or selector(s) to use as values variables; if `on`
|
|
4775
|
-
# is empty
|
|
4853
|
+
# is empty no columns will be used. If set to `nil` (default)
|
|
4854
|
+
# all columns that are not in `index` will be used.
|
|
4776
4855
|
# @param index [Object]
|
|
4777
4856
|
# Column(s) or selector(s) to use as identifier variables.
|
|
4778
4857
|
# @param variable_name [String]
|
|
@@ -4820,12 +4899,12 @@ module Polars
|
|
|
4820
4899
|
warn "The `streamable` parameter for `LazyFrame.unpivot` is deprecated"
|
|
4821
4900
|
end
|
|
4822
4901
|
|
|
4823
|
-
selector_on = on.nil? ?
|
|
4902
|
+
selector_on = on.nil? ? nil : Utils.parse_list_into_selector(on)._rbselector
|
|
4824
4903
|
selector_index = index.nil? ? Selectors.empty : Utils.parse_list_into_selector(index)
|
|
4825
4904
|
|
|
4826
4905
|
_from_rbldf(
|
|
4827
4906
|
_ldf.unpivot(
|
|
4828
|
-
selector_on
|
|
4907
|
+
selector_on,
|
|
4829
4908
|
selector_index._rbselector,
|
|
4830
4909
|
value_name,
|
|
4831
4910
|
variable_name
|
|
@@ -4905,10 +4984,10 @@ module Polars
|
|
|
4905
4984
|
# # │ -2 ┆ 199998 │
|
|
4906
4985
|
# # └─────────┴────────┘
|
|
4907
4986
|
def map_batches(
|
|
4908
|
-
predicate_pushdown:
|
|
4909
|
-
projection_pushdown:
|
|
4910
|
-
slice_pushdown:
|
|
4911
|
-
no_optimizations:
|
|
4987
|
+
predicate_pushdown: false,
|
|
4988
|
+
projection_pushdown: false,
|
|
4989
|
+
slice_pushdown: false,
|
|
4990
|
+
no_optimizations: nil,
|
|
4912
4991
|
schema: nil,
|
|
4913
4992
|
validate_output_schema: true,
|
|
4914
4993
|
streamable: false,
|
|
@@ -5020,7 +5099,7 @@ module Polars
|
|
|
5020
5099
|
# # │ foo ┆ 1 ┆ a ┆ true ┆ [1, 2] ┆ baz │
|
|
5021
5100
|
# # │ bar ┆ 2 ┆ b ┆ null ┆ [3] ┆ womp │
|
|
5022
5101
|
# # └────────┴─────┴─────┴──────┴───────────┴───────┘
|
|
5023
|
-
def unnest(columns, *more_columns, separator: nil)
|
|
5102
|
+
def unnest(columns = nil, *more_columns, separator: nil)
|
|
5024
5103
|
subset = Utils.parse_list_into_selector(columns) | Utils.parse_list_into_selector(
|
|
5025
5104
|
more_columns
|
|
5026
5105
|
)
|
|
@@ -5039,6 +5118,10 @@ module Polars
|
|
|
5039
5118
|
# Other DataFrame that must be merged
|
|
5040
5119
|
# @param key [String]
|
|
5041
5120
|
# Key that is sorted.
|
|
5121
|
+
# @param maintain_order [Boolean]
|
|
5122
|
+
# If `true`, the output is guaranteed to have left-biased ordering
|
|
5123
|
+
# for equal keys: rows from the left frame appear before rows from
|
|
5124
|
+
# the right frame when their keys are equal.
|
|
5042
5125
|
#
|
|
5043
5126
|
# @return [LazyFrame]
|
|
5044
5127
|
#
|
|
@@ -5065,8 +5148,8 @@ module Polars
|
|
|
5065
5148
|
# # │ steve ┆ 42 │
|
|
5066
5149
|
# # │ elise ┆ 44 │
|
|
5067
5150
|
# # └────────┴─────┘
|
|
5068
|
-
def merge_sorted(other, key)
|
|
5069
|
-
_from_rbldf(_ldf.merge_sorted(other._ldf, key))
|
|
5151
|
+
def merge_sorted(other, key, maintain_order: false)
|
|
5152
|
+
_from_rbldf(_ldf.merge_sorted(other._ldf, key, maintain_order))
|
|
5070
5153
|
end
|
|
5071
5154
|
|
|
5072
5155
|
# Flag a column as sorted.
|