polars-df 0.26.1 → 0.27.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 +5 -0
- data/Cargo.lock +290 -130
- data/LICENSE.txt +1 -1
- data/ext/polars/Cargo.toml +16 -16
- data/ext/polars/src/conversion/mod.rs +47 -103
- data/ext/polars/src/dataframe/general.rs +15 -2
- data/ext/polars/src/dataframe/io.rs +104 -97
- data/ext/polars/src/expr/general.rs +6 -2
- data/ext/polars/src/expr/list.rs +2 -2
- data/ext/polars/src/file.rs +8 -9
- data/ext/polars/src/functions/io.rs +2 -1
- data/ext/polars/src/interop/arrow/to_rb.rs +4 -19
- data/ext/polars/src/lazyframe/general.rs +6 -1
- data/ext/polars/src/lazyframe/sink.rs +1 -1
- data/ext/polars/src/lib.rs +2 -5
- data/ext/polars/src/on_startup.rs +2 -2
- data/ext/polars/src/ruby/capsule.rs +13 -1
- data/ext/polars/src/utils.rs +7 -3
- data/lib/polars/array_expr.rb +11 -3
- data/lib/polars/array_name_space.rb +2 -2
- data/lib/polars/data_frame.rb +47 -2
- data/lib/polars/expr.rb +74 -6
- data/lib/polars/functions/eager.rb +2 -2
- data/lib/polars/iceberg_dataset.rb +27 -153
- data/lib/polars/lazy_frame.rb +11 -3
- data/lib/polars/list_expr.rb +10 -2
- data/lib/polars/list_name_space.rb +2 -2
- data/lib/polars/series.rb +3 -3
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +2 -10
- metadata +1 -1
data/ext/polars/src/file.rs
CHANGED
|
@@ -6,9 +6,8 @@ use std::path::PathBuf;
|
|
|
6
6
|
use magnus::{Error, RString, Ruby, Value, prelude::*, value::Opaque};
|
|
7
7
|
use polars::io::mmap::MmapBytesReader;
|
|
8
8
|
use polars::prelude::PlRefPath;
|
|
9
|
-
use polars::prelude::file::{
|
|
9
|
+
use polars::prelude::file::{Writable, WritableTrait};
|
|
10
10
|
use polars_buffer::Buffer;
|
|
11
|
-
use polars_utils::create_file;
|
|
12
11
|
|
|
13
12
|
use crate::error::RbPolarsErr;
|
|
14
13
|
use crate::prelude::resolve_homedir;
|
|
@@ -23,7 +22,7 @@ pub struct RbFileLikeObject {
|
|
|
23
22
|
has_flush: bool,
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
impl
|
|
25
|
+
impl WritableTrait for RbFileLikeObject {
|
|
27
26
|
fn close(&mut self) -> io::Result<()> {
|
|
28
27
|
Ok(())
|
|
29
28
|
}
|
|
@@ -192,7 +191,7 @@ impl Seek for RbFileLikeObject {
|
|
|
192
191
|
}
|
|
193
192
|
}
|
|
194
193
|
|
|
195
|
-
pub trait FileLike: Read + Write + Seek {}
|
|
194
|
+
pub trait FileLike: Read + Write + Seek + Sync + Send {}
|
|
196
195
|
|
|
197
196
|
impl FileLike for File {}
|
|
198
197
|
impl FileLike for RbFileLikeObject {}
|
|
@@ -217,10 +216,10 @@ impl EitherRustRubyFile {
|
|
|
217
216
|
}
|
|
218
217
|
}
|
|
219
218
|
|
|
220
|
-
pub(crate) fn
|
|
219
|
+
pub(crate) fn into_writable(self) -> Writable {
|
|
221
220
|
match self {
|
|
222
|
-
Self::Rb(f) =>
|
|
223
|
-
Self::Rust(f) =>
|
|
221
|
+
Self::Rb(f) => Writable::Dyn(Box::new(f)),
|
|
222
|
+
Self::Rust(f) => Writable::Local(f),
|
|
224
223
|
}
|
|
225
224
|
}
|
|
226
225
|
}
|
|
@@ -272,9 +271,9 @@ pub fn get_either_buffer_or_path(
|
|
|
272
271
|
let file_path = std::path::Path::new(&s);
|
|
273
272
|
let file_path = resolve_homedir(&file_path);
|
|
274
273
|
let f = if write {
|
|
275
|
-
create_file(&file_path).map_err(RbPolarsErr::from)?
|
|
274
|
+
polars_utils::io::create_file(&file_path).map_err(RbPolarsErr::from)?
|
|
276
275
|
} else {
|
|
277
|
-
polars_utils::open_file(&file_path).map_err(RbPolarsErr::from)?
|
|
276
|
+
polars_utils::io::open_file(&file_path).map_err(RbPolarsErr::from)?
|
|
278
277
|
};
|
|
279
278
|
Ok((EitherRustRubyFile::Rust(f), Some(file_path.into_owned())))
|
|
280
279
|
} else {
|
|
@@ -62,7 +62,8 @@ pub fn read_parquet_metadata(
|
|
|
62
62
|
})
|
|
63
63
|
.map_err(RbPolarsErr::from)?
|
|
64
64
|
} else {
|
|
65
|
-
let file =
|
|
65
|
+
let file =
|
|
66
|
+
polars_utils::io::open_file(p.as_std_path()).map_err(RbPolarsErr::from)?;
|
|
66
67
|
read_metadata(&mut BufReader::new(file)).map_err(RbPolarsErr::from)?
|
|
67
68
|
}
|
|
68
69
|
}
|
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
use arrow::datatypes::ArrowDataType;
|
|
2
2
|
use arrow::ffi;
|
|
3
|
-
use magnus::{
|
|
3
|
+
use magnus::{Ruby, Value};
|
|
4
4
|
use polars::datatypes::CompatLevel;
|
|
5
5
|
use polars::frame::DataFrame;
|
|
6
6
|
use polars::prelude::{ArrayRef, ArrowField, PlSmallStr, PolarsResult, SchemaExt};
|
|
7
7
|
use polars::series::Series;
|
|
8
8
|
use polars_core::utils::arrow;
|
|
9
|
-
use std::ffi::CString;
|
|
10
9
|
|
|
11
10
|
use crate::RbResult;
|
|
12
11
|
use crate::ruby::capsule::RbCapsule;
|
|
13
12
|
|
|
14
|
-
// TODO switch to RbCapsule in 0.27.0
|
|
15
|
-
#[magnus::wrap(class = "Polars::ArrowSchema")]
|
|
16
|
-
pub struct RbArrowSchema {
|
|
17
|
-
pub(crate) schema: ffi::ArrowSchema,
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
impl RbArrowSchema {
|
|
21
|
-
pub fn to_i(&self) -> usize {
|
|
22
|
-
(&self.schema as *const _) as usize
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
13
|
pub(crate) fn series_to_stream(series: &Series, ruby: &Ruby) -> RbResult<Value> {
|
|
27
14
|
let field = series.field().to_arrow(CompatLevel::newest());
|
|
28
15
|
let series = series.clone();
|
|
@@ -31,16 +18,14 @@ pub(crate) fn series_to_stream(series: &Series, ruby: &Ruby) -> RbResult<Value>
|
|
|
31
18
|
) as _;
|
|
32
19
|
|
|
33
20
|
let stream = ffi::export_iterator(iter, field);
|
|
34
|
-
|
|
35
|
-
Ok(RbCapsule::new(stream, Some(stream_capsule_name)).into_value_with(ruby))
|
|
21
|
+
RbCapsule::new_with_value(ruby, stream, c"arrow_array_stream")
|
|
36
22
|
}
|
|
37
23
|
|
|
38
24
|
pub(crate) fn dataframe_to_stream(df: &DataFrame, ruby: &Ruby) -> RbResult<Value> {
|
|
39
25
|
let iter = Box::new(DataFrameStreamIterator::new(df));
|
|
40
26
|
let field = iter.field();
|
|
41
27
|
let stream = ffi::export_iterator(iter, field);
|
|
42
|
-
|
|
43
|
-
Ok(RbCapsule::new(stream, Some(stream_capsule_name)).into_value_with(ruby))
|
|
28
|
+
RbCapsule::new_with_value(ruby, stream, c"arrow_array_stream")
|
|
44
29
|
}
|
|
45
30
|
|
|
46
31
|
pub(crate) fn polars_schema_to_rbcapsule(
|
|
@@ -59,7 +44,7 @@ pub(crate) fn polars_schema_to_rbcapsule(
|
|
|
59
44
|
false,
|
|
60
45
|
));
|
|
61
46
|
|
|
62
|
-
|
|
47
|
+
RbCapsule::new_with_value(ruby, schema, c"arrow_schema")
|
|
63
48
|
}
|
|
64
49
|
|
|
65
50
|
pub struct DataFrameStreamIterator {
|
|
@@ -1224,7 +1224,12 @@ impl RbLazyFrame {
|
|
|
1224
1224
|
ldf.count().into()
|
|
1225
1225
|
}
|
|
1226
1226
|
|
|
1227
|
-
pub fn merge_sorted(
|
|
1227
|
+
pub fn merge_sorted(
|
|
1228
|
+
&self,
|
|
1229
|
+
other: &Self,
|
|
1230
|
+
key: Vec<String>,
|
|
1231
|
+
maintain_order: bool,
|
|
1232
|
+
) -> RbResult<Self> {
|
|
1228
1233
|
let out = self
|
|
1229
1234
|
.ldf
|
|
1230
1235
|
.read()
|
data/ext/polars/src/lib.rs
CHANGED
|
@@ -37,7 +37,6 @@ use expr::RbExpr;
|
|
|
37
37
|
use expr::datatype::RbDataTypeExpr;
|
|
38
38
|
use expr::selector::RbSelector;
|
|
39
39
|
use functions::whenthen::{RbChainedThen, RbChainedWhen, RbThen, RbWhen};
|
|
40
|
-
use interop::arrow::to_rb::RbArrowSchema;
|
|
41
40
|
use lazyframe::{RbCollectBatches, RbInProcessQuery, RbLazyFrame, RbOptFlags};
|
|
42
41
|
use lazygroupby::RbLazyGroupBy;
|
|
43
42
|
use magnus::{Ruby, function, method, prelude::*};
|
|
@@ -138,6 +137,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
|
|
|
138
137
|
class.define_method("tail", method!(RbDataFrame::tail, 1))?;
|
|
139
138
|
class.define_method("is_unique", method!(RbDataFrame::is_unique, 0))?;
|
|
140
139
|
class.define_method("is_duplicated", method!(RbDataFrame::is_duplicated, 0))?;
|
|
140
|
+
class.define_method("is_sorted", method!(RbDataFrame::is_sorted, 3))?;
|
|
141
141
|
class.define_method("equals", method!(RbDataFrame::equals, 2))?;
|
|
142
142
|
class.define_method("with_row_index", method!(RbDataFrame::with_row_index, 2))?;
|
|
143
143
|
class.define_method(
|
|
@@ -252,6 +252,7 @@ fn init(ruby: &Ruby) -> RbResult<()> {
|
|
|
252
252
|
class.define_method("is_unique", method!(RbExpr::is_unique, 0))?;
|
|
253
253
|
class.define_method("is_between", method!(RbExpr::is_between, 3))?;
|
|
254
254
|
class.define_method("is_close", method!(RbExpr::is_close, 4))?;
|
|
255
|
+
class.define_method("is_sorted", method!(RbExpr::is_sorted, 2))?;
|
|
255
256
|
class.define_method("approx_n_unique", method!(RbExpr::approx_n_unique, 0))?;
|
|
256
257
|
class.define_method("is_first_distinct", method!(RbExpr::is_first_distinct, 0))?;
|
|
257
258
|
class.define_method("is_last_distinct", method!(RbExpr::is_last_distinct, 0))?;
|
|
@@ -1347,10 +1348,6 @@ fn init(ruby: &Ruby) -> RbResult<()> {
|
|
|
1347
1348
|
class.define_method("to_i", method!(RbCapsule::to_i, 0))?;
|
|
1348
1349
|
class.define_method("name", method!(RbCapsule::name, 0))?;
|
|
1349
1350
|
|
|
1350
|
-
// arrow schema
|
|
1351
|
-
let class = module.define_class("ArrowSchema", ruby.class_object())?;
|
|
1352
|
-
class.define_method("to_i", method!(RbArrowSchema::to_i, 0))?;
|
|
1353
|
-
|
|
1354
1351
|
// catalog
|
|
1355
1352
|
let class = module.define_class("RbCatalogClient", ruby.class_object())?;
|
|
1356
1353
|
class.define_singleton_method("new", function!(RbCatalogClient::new, 2))?;
|
|
@@ -12,7 +12,7 @@ use polars_core::chunked_array::object::registry;
|
|
|
12
12
|
use polars_core::chunked_array::object::registry::AnonymousObjectBuilder;
|
|
13
13
|
use polars_core::prelude::AnyValue;
|
|
14
14
|
use polars_error::PolarsWarning;
|
|
15
|
-
use polars_error::
|
|
15
|
+
use polars_error::abort::register_polars_abort_mechanism;
|
|
16
16
|
|
|
17
17
|
use crate::Wrap;
|
|
18
18
|
use crate::dataframe::RbDataFrame;
|
|
@@ -209,7 +209,7 @@ pub unsafe fn register_startup_deps(catch_keyboard_interrupt: bool) {
|
|
|
209
209
|
polars_error::set_warning_function(warning_function);
|
|
210
210
|
|
|
211
211
|
if catch_keyboard_interrupt {
|
|
212
|
-
|
|
212
|
+
register_polars_abort_mechanism();
|
|
213
213
|
}
|
|
214
214
|
});
|
|
215
215
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
use std::any::Any;
|
|
2
|
-
use std::ffi::CString;
|
|
2
|
+
use std::ffi::{CStr, CString};
|
|
3
|
+
|
|
4
|
+
use magnus::{IntoValue, Ruby, Value};
|
|
5
|
+
|
|
6
|
+
use crate::RbResult;
|
|
3
7
|
|
|
4
8
|
#[magnus::wrap(class = "Polars::Capsule")]
|
|
5
9
|
pub struct RbCapsule {
|
|
@@ -8,6 +12,14 @@ pub struct RbCapsule {
|
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
impl RbCapsule {
|
|
15
|
+
pub fn new_with_value<T: 'static + Send>(
|
|
16
|
+
ruby: &Ruby,
|
|
17
|
+
value: T,
|
|
18
|
+
name: &CStr,
|
|
19
|
+
) -> RbResult<Value> {
|
|
20
|
+
Ok(Self::new(value, Some(name.into())).into_value_with(ruby))
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
pub fn new<T: 'static + Send>(value: T, name: Option<CString>) -> Self {
|
|
12
24
|
Self {
|
|
13
25
|
value: Box::new(value),
|
data/ext/polars/src/utils.rs
CHANGED
|
@@ -4,7 +4,7 @@ use magnus::Ruby;
|
|
|
4
4
|
use polars::frame::DataFrame;
|
|
5
5
|
use polars::series::IntoSeries;
|
|
6
6
|
use polars_error::PolarsResult;
|
|
7
|
-
use polars_error::
|
|
7
|
+
use polars_error::abort::{QueryAborted, catch_polars_abort};
|
|
8
8
|
|
|
9
9
|
use crate::ruby::exceptions::RbKeyboardInterrupt;
|
|
10
10
|
use crate::ruby::gvl::GvlExt;
|
|
@@ -114,12 +114,16 @@ impl EnterPolarsExt for &Ruby {
|
|
|
114
114
|
E: Send + Into<RbPolarsErr>,
|
|
115
115
|
{
|
|
116
116
|
let timeout = schedule_polars_timeout();
|
|
117
|
-
let ret = self.detach(||
|
|
117
|
+
let ret = self.detach(|| catch_polars_abort(AssertUnwindSafe(f)));
|
|
118
118
|
cancel_polars_timeout(timeout);
|
|
119
119
|
match ret {
|
|
120
120
|
Ok(Ok(ret)) => Ok(ret),
|
|
121
121
|
Ok(Err(err)) => Err(RbErr::from(err.into())),
|
|
122
|
-
Err(KeyboardInterrupt) => Err(RbKeyboardInterrupt::new_err("")),
|
|
122
|
+
Err(QueryAborted::KeyboardInterrupt) => Err(RbKeyboardInterrupt::new_err("")),
|
|
123
|
+
Err(QueryAborted::OocOutOfDisk) => Err(RbPolarsErr::Other(
|
|
124
|
+
"query aborted, raise POLARS_OOC_DISK_BUDGET_MB".to_string(),
|
|
125
|
+
)
|
|
126
|
+
.into()),
|
|
123
127
|
}
|
|
124
128
|
}
|
|
125
129
|
}
|
data/lib/polars/array_expr.rb
CHANGED
|
@@ -776,7 +776,7 @@ module Polars
|
|
|
776
776
|
# df = Polars::DataFrame.new(
|
|
777
777
|
# {"a" => [[1, 2, 3], [4, 5, 6]]}, schema: {"a" => Polars::Array.new(Polars::Int64, 3)}
|
|
778
778
|
# )
|
|
779
|
-
# df.select(Polars.col("a").arr.explode)
|
|
779
|
+
# df.select(Polars.col("a").arr.explode(empty_as_null: false))
|
|
780
780
|
# # =>
|
|
781
781
|
# # shape: (6, 1)
|
|
782
782
|
# # ┌─────┐
|
|
@@ -791,8 +791,16 @@ module Polars
|
|
|
791
791
|
# # │ 5 │
|
|
792
792
|
# # │ 6 │
|
|
793
793
|
# # └─────┘
|
|
794
|
-
def explode(empty_as_null:
|
|
795
|
-
|
|
794
|
+
def explode(empty_as_null: OMITTED, keep_nulls: true)
|
|
795
|
+
if empty_as_null == OMITTED
|
|
796
|
+
Utils.issue_deprecation_warning(
|
|
797
|
+
"The default behavior for `empty_as_null` will change to `false`. " +
|
|
798
|
+
"To keep the current behavior, explicitly set `empty_as_null: true`."
|
|
799
|
+
)
|
|
800
|
+
empty_as_null = true
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
Utils.wrap_expr(_rbexpr.arr_explode(empty_as_null, keep_nulls))
|
|
796
804
|
end
|
|
797
805
|
|
|
798
806
|
# Check if sub-arrays contain the given item.
|
|
@@ -614,7 +614,7 @@ module Polars
|
|
|
614
614
|
#
|
|
615
615
|
# @example
|
|
616
616
|
# s = Polars::Series.new("a", [[1, 2, 3], [4, 5, 6]], dtype: Polars::Array.new(Polars::Int64, 3))
|
|
617
|
-
# s.arr.explode
|
|
617
|
+
# s.arr.explode(empty_as_null: false)
|
|
618
618
|
# # =>
|
|
619
619
|
# # shape: (6,)
|
|
620
620
|
# # Series: 'a' [i64]
|
|
@@ -626,7 +626,7 @@ module Polars
|
|
|
626
626
|
# # 5
|
|
627
627
|
# # 6
|
|
628
628
|
# # ]
|
|
629
|
-
def explode(empty_as_null:
|
|
629
|
+
def explode(empty_as_null: nil, keep_nulls: true)
|
|
630
630
|
super
|
|
631
631
|
end
|
|
632
632
|
|
data/lib/polars/data_frame.rb
CHANGED
|
@@ -4535,7 +4535,7 @@ module Polars
|
|
|
4535
4535
|
# "numbers" => [[1], [2, 3], [4, 5], [6, 7, 8]]
|
|
4536
4536
|
# }
|
|
4537
4537
|
# )
|
|
4538
|
-
# df.explode("numbers")
|
|
4538
|
+
# df.explode("numbers", empty_as_null: false)
|
|
4539
4539
|
# # =>
|
|
4540
4540
|
# # shape: (8, 2)
|
|
4541
4541
|
# # ┌─────────┬─────────┐
|
|
@@ -4555,7 +4555,7 @@ module Polars
|
|
|
4555
4555
|
def explode(
|
|
4556
4556
|
columns,
|
|
4557
4557
|
*more_columns,
|
|
4558
|
-
empty_as_null:
|
|
4558
|
+
empty_as_null: OMITTED,
|
|
4559
4559
|
keep_nulls: true
|
|
4560
4560
|
)
|
|
4561
4561
|
lazy
|
|
@@ -4970,6 +4970,51 @@ module Polars
|
|
|
4970
4970
|
lazy.shift(n, fill_value: fill_value).collect(optimizations: QueryOptFlags._eager)
|
|
4971
4971
|
end
|
|
4972
4972
|
|
|
4973
|
+
# Check whether the DataFrame is sorted by the given columns.
|
|
4974
|
+
#
|
|
4975
|
+
# @param by [Object]
|
|
4976
|
+
# Column name(s) to check.
|
|
4977
|
+
# @param more_by [Array]
|
|
4978
|
+
# Additional column names.
|
|
4979
|
+
# @param descending [Boolean]
|
|
4980
|
+
# Sort in descending order. When sorting by multiple columns, can be
|
|
4981
|
+
# specified per column by passing a sequence of booleans.
|
|
4982
|
+
# @param nulls_last [Boolean]
|
|
4983
|
+
# Place null values last. When sorting by multiple columns, can be
|
|
4984
|
+
# specified per column by passing a sequence of booleans.
|
|
4985
|
+
#
|
|
4986
|
+
# @return [Boolean]
|
|
4987
|
+
#
|
|
4988
|
+
# @example
|
|
4989
|
+
# df = Polars::DataFrame.new({"a" => [1, 2, 3], "b" => [5, 4, 3]})
|
|
4990
|
+
# df.is_sorted("a")
|
|
4991
|
+
# # => true
|
|
4992
|
+
#
|
|
4993
|
+
# @example
|
|
4994
|
+
# df.is_sorted("b", descending: true)
|
|
4995
|
+
# # => true
|
|
4996
|
+
#
|
|
4997
|
+
# @example
|
|
4998
|
+
# df.is_sorted("a", "b")
|
|
4999
|
+
# # => true
|
|
5000
|
+
def is_sorted(
|
|
5001
|
+
by,
|
|
5002
|
+
*more_by,
|
|
5003
|
+
descending: false,
|
|
5004
|
+
nulls_last: false
|
|
5005
|
+
)
|
|
5006
|
+
by = Array(by)
|
|
5007
|
+
by.concat(more_by)
|
|
5008
|
+
n = by.length
|
|
5009
|
+
if Utils.bool?(descending)
|
|
5010
|
+
descending = [descending] * n
|
|
5011
|
+
end
|
|
5012
|
+
if Utils.bool?(nulls_last)
|
|
5013
|
+
nulls_last = [nulls_last] * n
|
|
5014
|
+
end
|
|
5015
|
+
_df.is_sorted(by, descending, nulls_last)
|
|
5016
|
+
end
|
|
5017
|
+
|
|
4973
5018
|
# Get a mask of all duplicated rows in this DataFrame.
|
|
4974
5019
|
#
|
|
4975
5020
|
# @return [Series]
|
data/lib/polars/expr.rb
CHANGED
|
@@ -1576,7 +1576,7 @@ module Polars
|
|
|
1576
1576
|
# @example Get the top 2 rows by column `a` in each group.
|
|
1577
1577
|
# df.group_by("c", maintain_order: true)
|
|
1578
1578
|
# .agg(Polars.all.top_k_by("a", k: 2))
|
|
1579
|
-
# .explode(Polars.all.exclude("c"))
|
|
1579
|
+
# .explode(Polars.all.exclude("c"), empty_as_null: false)
|
|
1580
1580
|
# # =>
|
|
1581
1581
|
# # shape: (5, 3)
|
|
1582
1582
|
# # ┌────────┬─────┬─────┐
|
|
@@ -1721,7 +1721,7 @@ module Polars
|
|
|
1721
1721
|
# @example Get the bottom 2 rows by column `a` in each group.
|
|
1722
1722
|
# df.group_by("c", maintain_order: true)
|
|
1723
1723
|
# .agg(Polars.all.bottom_k_by("a", k: 2))
|
|
1724
|
-
# .explode(Polars.all.exclude("c"))
|
|
1724
|
+
# .explode(Polars.all.exclude("c"), empty_as_null: false)
|
|
1725
1725
|
# # =>
|
|
1726
1726
|
# # shape: (5, 3)
|
|
1727
1727
|
# # ┌────────┬─────┬─────┐
|
|
@@ -3677,7 +3677,7 @@ module Polars
|
|
|
3677
3677
|
#
|
|
3678
3678
|
# @example
|
|
3679
3679
|
# df = Polars::DataFrame.new({"b" => [[1, 2, 3], [4, 5, 6]]})
|
|
3680
|
-
# df.select(Polars.col("b").explode)
|
|
3680
|
+
# df.select(Polars.col("b").explode(empty_as_null: false))
|
|
3681
3681
|
# # =>
|
|
3682
3682
|
# # shape: (6, 1)
|
|
3683
3683
|
# # ┌─────┐
|
|
@@ -3692,7 +3692,15 @@ module Polars
|
|
|
3692
3692
|
# # │ 5 │
|
|
3693
3693
|
# # │ 6 │
|
|
3694
3694
|
# # └─────┘
|
|
3695
|
-
def explode(empty_as_null:
|
|
3695
|
+
def explode(empty_as_null: OMITTED, keep_nulls: true)
|
|
3696
|
+
if empty_as_null == OMITTED
|
|
3697
|
+
Utils.issue_deprecation_warning(
|
|
3698
|
+
"The default behavior for `empty_as_null` will change to `false`. " +
|
|
3699
|
+
"To keep the current behavior, explicitly set `empty_as_null: true`."
|
|
3700
|
+
)
|
|
3701
|
+
empty_as_null = true
|
|
3702
|
+
end
|
|
3703
|
+
|
|
3696
3704
|
wrap_expr(_rbexpr.explode(empty_as_null, keep_nulls))
|
|
3697
3705
|
end
|
|
3698
3706
|
|
|
@@ -4604,6 +4612,66 @@ module Polars
|
|
|
4604
4612
|
wrap_expr(_rbexpr.is_close(other, abs_tol, rel_tol, nans_equal))
|
|
4605
4613
|
end
|
|
4606
4614
|
|
|
4615
|
+
# Checks if an expression is sorted.
|
|
4616
|
+
#
|
|
4617
|
+
# If `descending` and/or `nulls_last` are nil, it will check `true` and `false`
|
|
4618
|
+
# for the unspecified option(s), and return `true` if the expression is sorted
|
|
4619
|
+
# under any combination of those settings.
|
|
4620
|
+
#
|
|
4621
|
+
# @param descending [Boolean]
|
|
4622
|
+
# Checks if the expression is sorted in descending order.
|
|
4623
|
+
# Defaults to false.
|
|
4624
|
+
# @param nulls_last [Boolean]
|
|
4625
|
+
# Consider null values as being ordered last when checking sortedness.
|
|
4626
|
+
# Defaults to false.
|
|
4627
|
+
#
|
|
4628
|
+
# @return [Expr]
|
|
4629
|
+
#
|
|
4630
|
+
# @example Check if a column is sorted in ascending order.
|
|
4631
|
+
# df = Polars::DataFrame.new({"a" => [1, 2, 3, 4]})
|
|
4632
|
+
# df.select(Polars.col("a").is_sorted)
|
|
4633
|
+
# # =>
|
|
4634
|
+
# # shape: (1, 1)
|
|
4635
|
+
# # ┌──────┐
|
|
4636
|
+
# # │ a │
|
|
4637
|
+
# # │ --- │
|
|
4638
|
+
# # │ bool │
|
|
4639
|
+
# # ╞══════╡
|
|
4640
|
+
# # │ true │
|
|
4641
|
+
# # └──────┘
|
|
4642
|
+
#
|
|
4643
|
+
# @example Check if a column is sorted in descending order.
|
|
4644
|
+
# df = Polars::DataFrame.new({"a" => [4, 3, 2, 1]})
|
|
4645
|
+
# df.select(Polars.col("a").is_sorted(descending: true))
|
|
4646
|
+
# # =>
|
|
4647
|
+
# # shape: (1, 1)
|
|
4648
|
+
# # ┌──────┐
|
|
4649
|
+
# # │ a │
|
|
4650
|
+
# # │ --- │
|
|
4651
|
+
# # │ bool │
|
|
4652
|
+
# # ╞══════╡
|
|
4653
|
+
# # │ true │
|
|
4654
|
+
# # └──────┘
|
|
4655
|
+
#
|
|
4656
|
+
# @example Check if a column is sorted in either direction.
|
|
4657
|
+
# df = Polars::DataFrame.new({"a" => [4, 3, 2, 1]})
|
|
4658
|
+
# df.select(Polars.col("a").is_sorted(descending: nil))
|
|
4659
|
+
# # =>
|
|
4660
|
+
# # shape: (1, 1)
|
|
4661
|
+
# # ┌──────┐
|
|
4662
|
+
# # │ a │
|
|
4663
|
+
# # │ --- │
|
|
4664
|
+
# # │ bool │
|
|
4665
|
+
# # ╞══════╡
|
|
4666
|
+
# # │ true │
|
|
4667
|
+
# # └──────┘
|
|
4668
|
+
def is_sorted(
|
|
4669
|
+
descending: false,
|
|
4670
|
+
nulls_last: false
|
|
4671
|
+
)
|
|
4672
|
+
wrap_expr(_rbexpr.is_sorted(descending, nulls_last))
|
|
4673
|
+
end
|
|
4674
|
+
|
|
4607
4675
|
# Hash the elements in the selection.
|
|
4608
4676
|
#
|
|
4609
4677
|
# The hash value is of type `UInt64`.
|
|
@@ -7583,7 +7651,7 @@ module Polars
|
|
|
7583
7651
|
# # │ --- │
|
|
7584
7652
|
# # │ f64 │
|
|
7585
7653
|
# # ╞══════════╡
|
|
7586
|
-
# # │
|
|
7654
|
+
# # │ null │
|
|
7587
7655
|
# # │ 0.707107 │
|
|
7588
7656
|
# # │ 0.963624 │
|
|
7589
7657
|
# # └──────────┘
|
|
@@ -7615,7 +7683,7 @@ module Polars
|
|
|
7615
7683
|
# # │ --- │
|
|
7616
7684
|
# # │ f64 │
|
|
7617
7685
|
# # ╞══════════╡
|
|
7618
|
-
# # │
|
|
7686
|
+
# # │ null │
|
|
7619
7687
|
# # │ 0.5 │
|
|
7620
7688
|
# # │ 0.928571 │
|
|
7621
7689
|
# # └──────────┘
|
|
@@ -95,7 +95,7 @@ module Polars
|
|
|
95
95
|
# # │ 2 ┆ 4 ┆ 5 ┆ null │
|
|
96
96
|
# # │ 3 ┆ null ┆ 6 ┆ 8 │
|
|
97
97
|
# # └─────┴──────┴──────┴──────┘
|
|
98
|
-
def concat(items, rechunk: false, how: "vertical", parallel: true, strict:
|
|
98
|
+
def concat(items, rechunk: false, how: "vertical", parallel: true, strict: nil)
|
|
99
99
|
elems = items.to_a
|
|
100
100
|
|
|
101
101
|
if elems.empty?
|
|
@@ -303,7 +303,7 @@ module Polars
|
|
|
303
303
|
def union(
|
|
304
304
|
items,
|
|
305
305
|
how: "vertical",
|
|
306
|
-
strict:
|
|
306
|
+
strict: nil
|
|
307
307
|
)
|
|
308
308
|
elems = items.to_a
|
|
309
309
|
|