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
|
@@ -5,6 +5,7 @@ use std::sync::OnceLock;
|
|
|
5
5
|
|
|
6
6
|
use arrow::array::Array;
|
|
7
7
|
use magnus::{IntoValue, Ruby, Value, prelude::*, value::Opaque};
|
|
8
|
+
use polars::chunked_array::object::ObjectArray;
|
|
8
9
|
use polars::prelude::*;
|
|
9
10
|
use polars_core::chunked_array::object::builder::ObjectChunkedBuilder;
|
|
10
11
|
use polars_core::chunked_array::object::registry;
|
|
@@ -23,7 +24,7 @@ use crate::ruby::gvl::GvlExt;
|
|
|
23
24
|
use crate::ruby::ruby_convert_registry::{FromRubyConvertRegistry, RubyConvertRegistry};
|
|
24
25
|
use crate::ruby::ruby_udf;
|
|
25
26
|
use crate::ruby::thread::{is_non_ruby_thread, run_in_ruby_thread};
|
|
26
|
-
use crate::ruby::utils::to_pl_err;
|
|
27
|
+
use crate::ruby::utils::{TryIntoValue, to_pl_err};
|
|
27
28
|
use crate::series::RbSeries;
|
|
28
29
|
|
|
29
30
|
fn ruby_function_caller_series(
|
|
@@ -86,16 +87,23 @@ pub unsafe fn register_startup_deps(catch_keyboard_interrupt: bool) {
|
|
|
86
87
|
|
|
87
88
|
let object_converter = Arc::new(|av: AnyValue| {
|
|
88
89
|
let object = Ruby::attach(|rb| ObjectValue {
|
|
89
|
-
inner: Wrap(av).
|
|
90
|
+
inner: Wrap(av).try_into_value_with(rb).unwrap().into(),
|
|
90
91
|
});
|
|
91
92
|
Box::new(object) as Box<dyn Any>
|
|
92
93
|
});
|
|
93
94
|
let rbobject_converter = Arc::new(|av: AnyValue| {
|
|
94
|
-
let object = Ruby::attach(|rb| Wrap(av).
|
|
95
|
+
let object = Ruby::attach(|rb| Wrap(av).try_into_value_with(rb).unwrap());
|
|
95
96
|
Box::new(object) as Box<dyn Any>
|
|
96
97
|
});
|
|
97
|
-
fn object_array_getter(
|
|
98
|
-
|
|
98
|
+
fn object_array_getter(arr: &dyn Array, idx: usize) -> Option<AnyValue<'_>> {
|
|
99
|
+
let arr = arr
|
|
100
|
+
.as_any()
|
|
101
|
+
.downcast_ref::<ObjectArray<ObjectValue>>()
|
|
102
|
+
.unwrap();
|
|
103
|
+
arr.get(idx).map(|v| AnyValue::Object(v))
|
|
104
|
+
}
|
|
105
|
+
fn with_gil(f: &mut dyn FnMut()) {
|
|
106
|
+
Ruby::attach(|_| f())
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
crate::ruby::ruby_convert_registry::register_converters(RubyConvertRegistry {
|
|
@@ -170,13 +178,13 @@ pub unsafe fn register_startup_deps(catch_keyboard_interrupt: bool) {
|
|
|
170
178
|
}),
|
|
171
179
|
schema: Arc::new(|schema| {
|
|
172
180
|
Ruby::attach(|rb| {
|
|
173
|
-
|
|
181
|
+
Wrap(
|
|
174
182
|
schema
|
|
175
183
|
.downcast_ref::<polars_core::schema::Schema>()
|
|
176
184
|
.unwrap()
|
|
177
185
|
.clone(),
|
|
178
186
|
)
|
|
179
|
-
.
|
|
187
|
+
.try_into_value_with(rb)
|
|
180
188
|
})
|
|
181
189
|
}),
|
|
182
190
|
},
|
|
@@ -190,6 +198,7 @@ pub unsafe fn register_startup_deps(catch_keyboard_interrupt: bool) {
|
|
|
190
198
|
rbobject_converter,
|
|
191
199
|
physical_dtype,
|
|
192
200
|
Arc::new(object_array_getter),
|
|
201
|
+
Arc::new(with_gil),
|
|
193
202
|
);
|
|
194
203
|
|
|
195
204
|
// Register SERIES UDF.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
use std::any::Any;
|
|
2
|
+
use std::ffi::CString;
|
|
3
|
+
|
|
4
|
+
#[magnus::wrap(class = "Polars::Capsule")]
|
|
5
|
+
pub struct RbCapsule {
|
|
6
|
+
value: Box<dyn Any + Send>,
|
|
7
|
+
name: Option<CString>,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
impl RbCapsule {
|
|
11
|
+
pub fn new<T: 'static + Send>(value: T, name: Option<CString>) -> Self {
|
|
12
|
+
Self {
|
|
13
|
+
value: Box::new(value),
|
|
14
|
+
name,
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn to_i(&self) -> usize {
|
|
19
|
+
(&*self.value as *const dyn Any as *const ()) as usize
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// TODO use &CStr when Magnus supports it
|
|
23
|
+
// https://github.com/matsadler/magnus/pull/182
|
|
24
|
+
pub fn name(&self) -> Option<&str> {
|
|
25
|
+
self.name.as_deref().map(|v| v.to_str().unwrap())
|
|
26
|
+
}
|
|
27
|
+
}
|
data/ext/polars/src/ruby/mod.rs
CHANGED
data/ext/polars/src/ruby/numo.rs
CHANGED
|
@@ -40,14 +40,13 @@ where
|
|
|
40
40
|
pub struct RbArray1<T>(T);
|
|
41
41
|
|
|
42
42
|
impl<T: Element> RbArray1<T> {
|
|
43
|
-
pub fn from_iter<I>(values: I) -> RbResult<Value>
|
|
43
|
+
pub fn from_iter<I>(rb: &Ruby, values: I) -> RbResult<Value>
|
|
44
44
|
where
|
|
45
45
|
I: IntoIterator<Item = T>,
|
|
46
46
|
{
|
|
47
|
-
|
|
48
|
-
ruby.class_object()
|
|
47
|
+
rb.class_object()
|
|
49
48
|
.const_get::<_, RModule>("Numo")?
|
|
50
49
|
.const_get::<_, RClass>(T::class_name())?
|
|
51
|
-
.funcall("cast", (
|
|
50
|
+
.funcall("cast", (rb.ary_from_iter(values),))
|
|
52
51
|
}
|
|
53
52
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
use magnus::{Module, RClass, Ruby, value::Lazy};
|
|
2
2
|
|
|
3
|
-
static BIGDECIMAL: Lazy<RClass> =
|
|
4
|
-
Lazy::new(|rb| rb.class_object().const_get("BigDecimal").unwrap());
|
|
5
3
|
static DATE: Lazy<RClass> = Lazy::new(|rb| rb.class_object().const_get("Date").unwrap());
|
|
6
4
|
static DATETIME: Lazy<RClass> = Lazy::new(|rb| rb.class_object().const_get("DateTime").unwrap());
|
|
7
5
|
|
|
8
|
-
pub(crate) fn bigdecimal(rb: &Ruby) -> RClass {
|
|
9
|
-
rb.
|
|
6
|
+
pub(crate) fn bigdecimal(rb: &Ruby) -> Option<RClass> {
|
|
7
|
+
rb.class_object().const_get("BigDecimal").ok()
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
pub(crate) fn date(rb: &Ruby) -> RClass {
|
|
@@ -82,15 +82,13 @@ impl AnonymousColumnsUdf for RubyUdfExpression {
|
|
|
82
82
|
|
|
83
83
|
fn deep_clone(self: Arc<Self>) -> Arc<dyn AnonymousColumnsUdf> {
|
|
84
84
|
Arc::new(Self {
|
|
85
|
-
ruby_function: ArcValue::new(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.unwrap(),
|
|
93
|
-
),
|
|
85
|
+
ruby_function: ArcValue::new(Ruby::attach(|rb| {
|
|
86
|
+
// TODO fix
|
|
87
|
+
rb.get_inner(*self.ruby_function.0)
|
|
88
|
+
.funcall::<_, _, Value>("dup", ())
|
|
89
|
+
.map(Opaque::from)
|
|
90
|
+
.unwrap()
|
|
91
|
+
})),
|
|
94
92
|
output_type: self.output_type.clone(),
|
|
95
93
|
materialized_field: OnceLock::new(),
|
|
96
94
|
is_elementwise: self.is_elementwise,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
use std::sync::Arc;
|
|
2
2
|
|
|
3
|
-
use magnus::{Error, Ruby, Value, gc, value::Opaque};
|
|
3
|
+
use magnus::{Error, IntoValue, Ruby, Value, gc, value::Opaque};
|
|
4
4
|
use polars::error::PolarsError;
|
|
5
5
|
|
|
6
|
+
use crate::RbResult;
|
|
6
7
|
use crate::ruby::gvl::GvlExt;
|
|
7
8
|
|
|
8
9
|
pub(crate) fn to_pl_err(e: Error) -> PolarsError {
|
|
@@ -26,3 +27,13 @@ impl Drop for ArcValue {
|
|
|
26
27
|
Ruby::attach(|_| gc::unregister_address(&*self.0));
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
|
|
31
|
+
pub trait TryIntoValue {
|
|
32
|
+
fn try_into_value_with(self, ruby: &Ruby) -> RbResult<Value>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
impl<T: IntoValue> TryIntoValue for T {
|
|
36
|
+
fn try_into_value_with(self, ruby: &Ruby) -> RbResult<Value> {
|
|
37
|
+
Ok(self.into_value_with(ruby))
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -3,11 +3,12 @@ use magnus::{IntoValue, Ruby, Value};
|
|
|
3
3
|
use polars::prelude::*;
|
|
4
4
|
|
|
5
5
|
use crate::prelude::*;
|
|
6
|
+
use crate::ruby::utils::TryIntoValue;
|
|
6
7
|
use crate::utils::EnterPolarsExt;
|
|
7
8
|
use crate::{RbResult, RbSeries};
|
|
8
9
|
|
|
9
10
|
fn scalar_to_rb(scalar: RbResult<Scalar>, rb: &Ruby) -> RbResult<Value> {
|
|
10
|
-
|
|
11
|
+
Wrap(scalar?.as_any_value()).try_into_value_with(rb)
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
impl RbSeries {
|
|
@@ -35,6 +36,17 @@ impl RbSeries {
|
|
|
35
36
|
})
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
pub fn is_empty(rb: &Ruby, self_: &Self, ignore_nulls: bool) -> RbResult<bool> {
|
|
40
|
+
rb.enter_polars(|| {
|
|
41
|
+
let s = self_.series.read();
|
|
42
|
+
PolarsResult::Ok(if ignore_nulls {
|
|
43
|
+
s.is_full_null()
|
|
44
|
+
} else {
|
|
45
|
+
s.is_empty()
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
pub fn arg_max(rb: &Ruby, self_: &Self) -> RbResult<Option<usize>> {
|
|
39
51
|
rb.enter_polars_ok(|| self_.series.read().arg_max())
|
|
40
52
|
}
|
|
@@ -1,50 +1,51 @@
|
|
|
1
1
|
use magnus::{IntoValue, Ruby, Value, value::ReprValue};
|
|
2
2
|
use polars_core::prelude::*;
|
|
3
3
|
|
|
4
|
+
use crate::interop::arrow::to_rb::series_to_stream;
|
|
4
5
|
use crate::prelude::*;
|
|
6
|
+
use crate::ruby::utils::TryIntoValue;
|
|
5
7
|
use crate::{RbPolarsErr, RbResult, RbSeries};
|
|
6
8
|
|
|
7
9
|
impl RbSeries {
|
|
8
10
|
/// Convert this Series to a Ruby array.
|
|
9
11
|
/// This operation copies data.
|
|
10
|
-
pub fn to_a(&
|
|
11
|
-
let series = &
|
|
12
|
+
pub fn to_a(ruby: &Ruby, self_: &Self) -> RbResult<Value> {
|
|
13
|
+
let series = &self_.series.read();
|
|
12
14
|
|
|
13
|
-
fn to_a_recursive(series: &Series) -> RbResult<Value> {
|
|
14
|
-
let ruby = Ruby::get().unwrap();
|
|
15
|
+
fn to_a_recursive(ruby: &Ruby, series: &Series) -> RbResult<Value> {
|
|
15
16
|
let rblist = match series.dtype() {
|
|
16
17
|
DataType::Boolean => ruby
|
|
17
|
-
.ary_from_iter(series.bool().map_err(RbPolarsErr::from)
|
|
18
|
+
.ary_from_iter(series.bool().map_err(RbPolarsErr::from)?.iter())
|
|
18
19
|
.as_value(),
|
|
19
20
|
DataType::UInt8 => ruby
|
|
20
|
-
.ary_from_iter(series.u8().map_err(RbPolarsErr::from)
|
|
21
|
+
.ary_from_iter(series.u8().map_err(RbPolarsErr::from)?.iter())
|
|
21
22
|
.as_value(),
|
|
22
23
|
DataType::UInt16 => ruby
|
|
23
|
-
.ary_from_iter(series.u16().map_err(RbPolarsErr::from)
|
|
24
|
+
.ary_from_iter(series.u16().map_err(RbPolarsErr::from)?.iter())
|
|
24
25
|
.as_value(),
|
|
25
26
|
DataType::UInt32 => ruby
|
|
26
|
-
.ary_from_iter(series.u32().map_err(RbPolarsErr::from)
|
|
27
|
+
.ary_from_iter(series.u32().map_err(RbPolarsErr::from)?.iter())
|
|
27
28
|
.as_value(),
|
|
28
29
|
DataType::UInt64 => ruby
|
|
29
|
-
.ary_from_iter(series.u64().map_err(RbPolarsErr::from)
|
|
30
|
+
.ary_from_iter(series.u64().map_err(RbPolarsErr::from)?.iter())
|
|
30
31
|
.as_value(),
|
|
31
32
|
DataType::UInt128 => ruby
|
|
32
|
-
.ary_from_iter(series.u128().map_err(RbPolarsErr::from)
|
|
33
|
+
.ary_from_iter(series.u128().map_err(RbPolarsErr::from)?.iter())
|
|
33
34
|
.as_value(),
|
|
34
35
|
DataType::Int8 => ruby
|
|
35
|
-
.ary_from_iter(series.i8().map_err(RbPolarsErr::from)
|
|
36
|
+
.ary_from_iter(series.i8().map_err(RbPolarsErr::from)?.iter())
|
|
36
37
|
.as_value(),
|
|
37
38
|
DataType::Int16 => ruby
|
|
38
|
-
.ary_from_iter(series.i16().map_err(RbPolarsErr::from)
|
|
39
|
+
.ary_from_iter(series.i16().map_err(RbPolarsErr::from)?.iter())
|
|
39
40
|
.as_value(),
|
|
40
41
|
DataType::Int32 => ruby
|
|
41
|
-
.ary_from_iter(series.i32().map_err(RbPolarsErr::from)
|
|
42
|
+
.ary_from_iter(series.i32().map_err(RbPolarsErr::from)?.iter())
|
|
42
43
|
.as_value(),
|
|
43
44
|
DataType::Int64 => ruby
|
|
44
|
-
.ary_from_iter(series.i64().map_err(RbPolarsErr::from)
|
|
45
|
+
.ary_from_iter(series.i64().map_err(RbPolarsErr::from)?.iter())
|
|
45
46
|
.as_value(),
|
|
46
47
|
DataType::Int128 => ruby
|
|
47
|
-
.ary_from_iter(series.i128().map_err(RbPolarsErr::from)
|
|
48
|
+
.ary_from_iter(series.i128().map_err(RbPolarsErr::from)?.iter())
|
|
48
49
|
.as_value(),
|
|
49
50
|
DataType::Float16 => ruby
|
|
50
51
|
.ary_from_iter(
|
|
@@ -53,14 +54,15 @@ impl RbSeries {
|
|
|
53
54
|
.cast(&DataType::Float32)
|
|
54
55
|
.map_err(RbPolarsErr::from)?
|
|
55
56
|
.f32()
|
|
56
|
-
.map_err(RbPolarsErr::from)
|
|
57
|
+
.map_err(RbPolarsErr::from)?
|
|
58
|
+
.iter(),
|
|
57
59
|
)
|
|
58
60
|
.as_value(),
|
|
59
61
|
DataType::Float32 => ruby
|
|
60
|
-
.ary_from_iter(series.f32().map_err(RbPolarsErr::from)
|
|
62
|
+
.ary_from_iter(series.f32().map_err(RbPolarsErr::from)?.iter())
|
|
61
63
|
.as_value(),
|
|
62
64
|
DataType::Float64 => ruby
|
|
63
|
-
.ary_from_iter(series.f64().map_err(RbPolarsErr::from)
|
|
65
|
+
.ary_from_iter(series.f64().map_err(RbPolarsErr::from)?.iter())
|
|
64
66
|
.as_value(),
|
|
65
67
|
DataType::Categorical(_, _) | DataType::Enum(_, _) => {
|
|
66
68
|
with_match_categorical_physical_type!(series.dtype().cat_physical().unwrap(), |$C| {
|
|
@@ -71,10 +73,7 @@ impl RbSeries {
|
|
|
71
73
|
let v = ruby.ary_new_capa(series.len());
|
|
72
74
|
for i in 0..series.len() {
|
|
73
75
|
let obj: Option<&ObjectValue> = series.get_object(i).map(|any| any.into());
|
|
74
|
-
|
|
75
|
-
Some(val) => v.push(val.to_value()).unwrap(),
|
|
76
|
-
None => v.push(ruby.qnil()).unwrap(),
|
|
77
|
-
};
|
|
76
|
+
v.push(obj.cloned().into_value_with(ruby))?;
|
|
78
77
|
}
|
|
79
78
|
v.as_value()
|
|
80
79
|
}
|
|
@@ -87,7 +86,7 @@ impl RbSeries {
|
|
|
87
86
|
v.push(ruby.qnil()).unwrap();
|
|
88
87
|
}
|
|
89
88
|
Some(s) => {
|
|
90
|
-
let rblst = to_a_recursive(s.as_ref())?;
|
|
89
|
+
let rblst = to_a_recursive(ruby, s.as_ref())?;
|
|
91
90
|
v.push(rblst)?;
|
|
92
91
|
}
|
|
93
92
|
}
|
|
@@ -103,7 +102,7 @@ impl RbSeries {
|
|
|
103
102
|
v.push(ruby.qnil()).unwrap();
|
|
104
103
|
}
|
|
105
104
|
Some(s) => {
|
|
106
|
-
let rblst = to_a_recursive(s.as_ref())?;
|
|
105
|
+
let rblst = to_a_recursive(ruby, s.as_ref())?;
|
|
107
106
|
v.push(rblst)?;
|
|
108
107
|
}
|
|
109
108
|
}
|
|
@@ -112,35 +111,35 @@ impl RbSeries {
|
|
|
112
111
|
}
|
|
113
112
|
DataType::Date => {
|
|
114
113
|
let ca = series.date().map_err(RbPolarsErr::from)?;
|
|
115
|
-
return
|
|
114
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
116
115
|
}
|
|
117
116
|
DataType::Time => {
|
|
118
117
|
let ca = series.time().map_err(RbPolarsErr::from)?;
|
|
119
|
-
return
|
|
118
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
120
119
|
}
|
|
121
120
|
DataType::Datetime(_, _) => {
|
|
122
121
|
let ca = series.datetime().map_err(RbPolarsErr::from)?;
|
|
123
|
-
return
|
|
122
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
124
123
|
}
|
|
125
124
|
DataType::Decimal(_, _) => {
|
|
126
125
|
let ca = series.decimal().map_err(RbPolarsErr::from)?;
|
|
127
|
-
return
|
|
126
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
128
127
|
}
|
|
129
128
|
DataType::String => {
|
|
130
129
|
let ca = series.str().map_err(RbPolarsErr::from)?;
|
|
131
|
-
return
|
|
130
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
132
131
|
}
|
|
133
132
|
DataType::Struct(_) => {
|
|
134
133
|
let ca = series.struct_().map_err(RbPolarsErr::from)?;
|
|
135
|
-
return
|
|
134
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
136
135
|
}
|
|
137
136
|
DataType::Duration(_) => {
|
|
138
137
|
let ca = series.duration().map_err(RbPolarsErr::from)?;
|
|
139
|
-
return
|
|
138
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
140
139
|
}
|
|
141
140
|
DataType::Binary => {
|
|
142
141
|
let ca = series.binary().map_err(RbPolarsErr::from)?;
|
|
143
|
-
return
|
|
142
|
+
return Wrap(ca).try_into_value_with(ruby);
|
|
144
143
|
}
|
|
145
144
|
DataType::Null => {
|
|
146
145
|
let null: Option<u8> = None;
|
|
@@ -163,10 +162,7 @@ impl RbSeries {
|
|
|
163
162
|
}
|
|
164
163
|
impl ExactSizeIterator for NullIter {}
|
|
165
164
|
|
|
166
|
-
|
|
167
|
-
.unwrap()
|
|
168
|
-
.ary_from_iter(NullIter { iter, n })
|
|
169
|
-
.as_value()
|
|
165
|
+
ruby.ary_from_iter(NullIter { iter, n }).as_value()
|
|
170
166
|
}
|
|
171
167
|
DataType::Unknown(_) => {
|
|
172
168
|
panic!("to_a not implemented for unknown")
|
|
@@ -175,12 +171,16 @@ impl RbSeries {
|
|
|
175
171
|
unreachable!()
|
|
176
172
|
}
|
|
177
173
|
DataType::Extension(_, _) => {
|
|
178
|
-
return to_a_recursive(series.ext().unwrap().storage());
|
|
174
|
+
return to_a_recursive(ruby, series.ext().unwrap().storage());
|
|
179
175
|
}
|
|
180
176
|
};
|
|
181
177
|
Ok(rblist.as_value())
|
|
182
178
|
}
|
|
183
179
|
|
|
184
|
-
to_a_recursive(series)
|
|
180
|
+
to_a_recursive(ruby, series)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
pub fn __arrow_c_stream__(ruby: &Ruby, self_: &Self) -> RbResult<Value> {
|
|
184
|
+
series_to_stream(&self_.series.read(), ruby)
|
|
185
185
|
}
|
|
186
186
|
}
|
|
@@ -10,6 +10,7 @@ use crate::ruby::exceptions::{RbIndexError, RbRuntimeError, RbValueError};
|
|
|
10
10
|
use crate::ruby::gvl::GvlExt;
|
|
11
11
|
use crate::ruby::plan_callback::PlanCallbackExt;
|
|
12
12
|
use crate::ruby::ruby_function::RubyObject;
|
|
13
|
+
use crate::ruby::utils::TryIntoValue;
|
|
13
14
|
use crate::utils::EnterPolarsExt;
|
|
14
15
|
use crate::{RbDataFrame, RbErr, RbPolarsErr, RbResult, RbSeries};
|
|
15
16
|
|
|
@@ -112,7 +113,7 @@ impl RbSeries {
|
|
|
112
113
|
let rbseries = RbSeries::new(s);
|
|
113
114
|
rb_modules::pl_utils(ruby).funcall("wrap_s", (rbseries,))
|
|
114
115
|
}
|
|
115
|
-
_ =>
|
|
116
|
+
_ => Wrap(av).try_into_value_with(ruby),
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
119
|
|
|
@@ -156,8 +157,8 @@ impl RbSeries {
|
|
|
156
157
|
self.series.write().rename(name.into());
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
pub fn dtype(rb: &Ruby, self_: &Self) -> Value {
|
|
160
|
-
Wrap(self_.series.read().dtype().clone()).
|
|
160
|
+
pub fn dtype(rb: &Ruby, self_: &Self) -> RbResult<Value> {
|
|
161
|
+
Wrap(self_.series.read().dtype().clone()).try_into_value_with(rb)
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
pub fn set_sorted_flag(&self, descending: bool) -> Self {
|
|
@@ -4,6 +4,7 @@ use super::RbSeries;
|
|
|
4
4
|
use crate::map::series::ApplyLambdaGeneric;
|
|
5
5
|
use crate::prelude::*;
|
|
6
6
|
use crate::ruby::gvl::GvlExt;
|
|
7
|
+
use crate::ruby::utils::TryIntoValue;
|
|
7
8
|
use crate::series::construction::series_from_objects;
|
|
8
9
|
use crate::{RbPolarsErr, RbResult};
|
|
9
10
|
use crate::{apply_all_polars_dtypes, raise_err};
|
|
@@ -78,7 +79,7 @@ fn call_and_collect_objects<T, I>(
|
|
|
78
79
|
skip_nulls: bool,
|
|
79
80
|
) -> RbResult<Series>
|
|
80
81
|
where
|
|
81
|
-
T:
|
|
82
|
+
T: TryIntoValue,
|
|
82
83
|
I: Iterator<Item = Option<T>>,
|
|
83
84
|
{
|
|
84
85
|
let mut objects = Vec::with_capacity(len);
|
|
@@ -91,7 +92,7 @@ where
|
|
|
91
92
|
continue;
|
|
92
93
|
}
|
|
93
94
|
None => rb.qnil().into_value_with(rb),
|
|
94
|
-
Some(val) => val.
|
|
95
|
+
Some(val) => val.try_into_value_with(rb)?,
|
|
95
96
|
};
|
|
96
97
|
let out: Value = lambda.funcall("call", (arg,))?;
|
|
97
98
|
objects.push(ObjectValue {
|
|
@@ -139,23 +139,23 @@ fn scatter_impl(
|
|
|
139
139
|
with_match_physical_numeric_polars_type!(dt, |$T| {
|
|
140
140
|
let ca: &mut ChunkedArray<$T> = mutable_s.as_mut();
|
|
141
141
|
let values: &ChunkedArray<$T> = values.as_ref().as_ref();
|
|
142
|
-
ca.scatter(idx, values)
|
|
142
|
+
ca.scatter(idx, values.iter())
|
|
143
143
|
})
|
|
144
144
|
}
|
|
145
145
|
DataType::Boolean => {
|
|
146
146
|
let ca: &mut ChunkedArray<BooleanType> = mutable_s.as_mut();
|
|
147
147
|
let values = values.bool()?;
|
|
148
|
-
ca.scatter(idx, values)
|
|
148
|
+
ca.scatter(idx, values.iter())
|
|
149
149
|
}
|
|
150
150
|
DataType::Binary => {
|
|
151
151
|
let ca: &mut ChunkedArray<BinaryType> = mutable_s.as_mut();
|
|
152
152
|
let values = values.binary()?;
|
|
153
|
-
ca.scatter(idx, values)
|
|
153
|
+
ca.scatter(idx, values.iter())
|
|
154
154
|
}
|
|
155
155
|
DataType::String => {
|
|
156
156
|
let ca: &mut ChunkedArray<StringType> = mutable_s.as_mut();
|
|
157
157
|
let values = values.str()?;
|
|
158
|
-
ca.scatter(idx, values)
|
|
158
|
+
ca.scatter(idx, values.iter())
|
|
159
159
|
}
|
|
160
160
|
_ => Err(PolarsError::ComputeError(
|
|
161
161
|
format!("not yet implemented for dtype: {logical_dtype}").into(),
|
data/ext/polars/src/utils.rs
CHANGED
|
@@ -16,7 +16,6 @@ macro_rules! apply_all_polars_dtypes {
|
|
|
16
16
|
($self:expr, $method:ident, $($args:expr),*) => {
|
|
17
17
|
match $self.dtype() {
|
|
18
18
|
DataType::Boolean => $self.bool().unwrap().$method($($args),*),
|
|
19
|
-
DataType::String => $self.str().unwrap().$method($($args),*),
|
|
20
19
|
DataType::UInt8 => $self.u8().unwrap().$method($($args),*),
|
|
21
20
|
DataType::UInt16 => $self.u16().unwrap().$method($($args),*),
|
|
22
21
|
DataType::UInt32 => $self.u32().unwrap().$method($($args),*),
|
|
@@ -27,15 +26,40 @@ macro_rules! apply_all_polars_dtypes {
|
|
|
27
26
|
DataType::Int32 => $self.i32().unwrap().$method($($args),*),
|
|
28
27
|
DataType::Int64 => $self.i64().unwrap().$method($($args),*),
|
|
29
28
|
DataType::Int128 => $self.i128().unwrap().$method($($args),*),
|
|
30
|
-
DataType::Float16 =>
|
|
29
|
+
DataType::Float16 => $self.cast(&DataType::Float32).unwrap().f32().unwrap().$method($($args),*),
|
|
31
30
|
DataType::Float32 => $self.f32().unwrap().$method($($args),*),
|
|
32
31
|
DataType::Float64 => $self.f64().unwrap().$method($($args),*),
|
|
33
|
-
DataType::
|
|
34
|
-
DataType::
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
DataType::String => $self.str().unwrap().$method($($args),*),
|
|
33
|
+
DataType::Binary => $self.binary().unwrap().$method($($args),*),
|
|
34
|
+
DataType::Decimal(_, _) => $self.decimal().unwrap().$method($($args),*),
|
|
35
|
+
|
|
36
|
+
DataType::Date => $self.date().unwrap().$method($($args),*),
|
|
37
|
+
DataType::Datetime(_, _) => $self.datetime().unwrap().$method($($args),*),
|
|
38
|
+
DataType::Duration(_) => $self.duration().unwrap().$method($($args),*),
|
|
39
|
+
DataType::Time => $self.time().unwrap().$method($($args),*),
|
|
40
|
+
|
|
41
|
+
DataType::List(_) => $self.list().unwrap().$method($($args),*),
|
|
37
42
|
DataType::Struct(_) => $self.struct_().unwrap().$method($($args),*),
|
|
38
|
-
|
|
43
|
+
DataType::Array(_, _) => $self.array().unwrap().$method($($args),*),
|
|
44
|
+
|
|
45
|
+
dt @ (DataType::Categorical(_, _) | DataType::Enum(_, _)) => match dt.cat_physical().unwrap() {
|
|
46
|
+
CategoricalPhysical::U8 => $self.cat8().unwrap().$method($($args),*),
|
|
47
|
+
CategoricalPhysical::U16 => $self.cat16().unwrap().$method($($args),*),
|
|
48
|
+
CategoricalPhysical::U32 => $self.cat32().unwrap().$method($($args),*),
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
DataType::Object(_) => {
|
|
52
|
+
$self
|
|
53
|
+
.as_any()
|
|
54
|
+
.downcast_ref::<ObjectChunked<ObjectValue>>()
|
|
55
|
+
.unwrap()
|
|
56
|
+
.$method($($args),*)
|
|
57
|
+
},
|
|
58
|
+
DataType::Extension(_, _) => $self.ext().unwrap().$method($($args),*),
|
|
59
|
+
|
|
60
|
+
DataType::Null => $self.null().unwrap().$method($($args),*),
|
|
61
|
+
|
|
62
|
+
dt @ (DataType::BinaryOffset | DataType::Unknown(_)) => panic!("dtype {:?} not supported", dt)
|
|
39
63
|
}
|
|
40
64
|
}
|
|
41
65
|
}
|
data/lib/polars/array_expr.rb
CHANGED
|
@@ -377,7 +377,9 @@ module Polars
|
|
|
377
377
|
# # │ [1, 2] │
|
|
378
378
|
# # └───────────┘
|
|
379
379
|
def unique(maintain_order: false)
|
|
380
|
-
|
|
380
|
+
eval(
|
|
381
|
+
F.element.unique(maintain_order: maintain_order), as_list: true
|
|
382
|
+
)
|
|
381
383
|
end
|
|
382
384
|
|
|
383
385
|
# Count the number of unique values in every sub-arrays.
|
|
@@ -403,7 +405,7 @@ module Polars
|
|
|
403
405
|
# # │ [2, 3, 4] ┆ 3 │
|
|
404
406
|
# # └───────────────┴──────────┘
|
|
405
407
|
def n_unique
|
|
406
|
-
|
|
408
|
+
agg(F.element.n_unique)
|
|
407
409
|
end
|
|
408
410
|
|
|
409
411
|
# Convert an Array column into a List column with the same inner data type.
|
|
@@ -432,6 +434,13 @@ module Polars
|
|
|
432
434
|
|
|
433
435
|
# Evaluate whether any boolean value is true for every subarray.
|
|
434
436
|
#
|
|
437
|
+
# @param ignore_nulls [Boolean]
|
|
438
|
+
# * If set to `true` (default), null values are ignored. If there
|
|
439
|
+
# are no non-null values, the output is `false`.
|
|
440
|
+
# * If set to `false`, [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic) is used to deal with nulls:
|
|
441
|
+
# if the column contains any null values and no `true` values,
|
|
442
|
+
# the output is null.
|
|
443
|
+
#
|
|
435
444
|
# @return [Expr]
|
|
436
445
|
#
|
|
437
446
|
# @example
|
|
@@ -461,12 +470,19 @@ module Polars
|
|
|
461
470
|
# # │ [null, null] ┆ false │
|
|
462
471
|
# # │ null ┆ null │
|
|
463
472
|
# # └────────────────┴───────┘
|
|
464
|
-
def any
|
|
465
|
-
|
|
473
|
+
def any(ignore_nulls: true)
|
|
474
|
+
agg(F.element.any(ignore_nulls: ignore_nulls))
|
|
466
475
|
end
|
|
467
476
|
|
|
468
477
|
# Evaluate whether all boolean values are true for every subarray.
|
|
469
478
|
#
|
|
479
|
+
# @param ignore_nulls [Boolean]
|
|
480
|
+
# * If set to `true` (default), null values are ignored. If there
|
|
481
|
+
# are no non-null values, the output is `true`.
|
|
482
|
+
# * If set to `false`, [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic) is used to deal with nulls:
|
|
483
|
+
# if the column contains any null values and no `false` values,
|
|
484
|
+
# the output is null.
|
|
485
|
+
#
|
|
470
486
|
# @return [Expr]
|
|
471
487
|
#
|
|
472
488
|
# @example
|
|
@@ -496,8 +512,8 @@ module Polars
|
|
|
496
512
|
# # │ [null, null] ┆ true │
|
|
497
513
|
# # │ null ┆ null │
|
|
498
514
|
# # └────────────────┴───────┘
|
|
499
|
-
def all
|
|
500
|
-
|
|
515
|
+
def all(ignore_nulls: true)
|
|
516
|
+
agg(F.element.all(ignore_nulls: ignore_nulls))
|
|
501
517
|
end
|
|
502
518
|
|
|
503
519
|
# Sort the arrays in this column.
|
|
@@ -567,7 +583,7 @@ module Polars
|
|
|
567
583
|
# # │ [9, 1, 2] ┆ [2, 1, 9] │
|
|
568
584
|
# # └───────────────┴───────────────┘
|
|
569
585
|
def reverse
|
|
570
|
-
|
|
586
|
+
eval(F.element.reverse)
|
|
571
587
|
end
|
|
572
588
|
|
|
573
589
|
# Retrieve the index of the minimal value in every sub-array.
|
|
@@ -212,6 +212,13 @@ module Polars
|
|
|
212
212
|
|
|
213
213
|
# Evaluate whether any boolean value is true for every subarray.
|
|
214
214
|
#
|
|
215
|
+
# @param ignore_nulls [Boolean]
|
|
216
|
+
# * If set to `true` (default), null values are ignored. If there
|
|
217
|
+
# are no non-null values, the output is `false`.
|
|
218
|
+
# * If set to `false`, [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic) is used to deal with nulls:
|
|
219
|
+
# if the column contains any null values and no `true` values,
|
|
220
|
+
# the output is null.
|
|
221
|
+
#
|
|
215
222
|
# @return [Series]
|
|
216
223
|
#
|
|
217
224
|
# @example
|
|
@@ -230,7 +237,7 @@ module Polars
|
|
|
230
237
|
# # false
|
|
231
238
|
# # null
|
|
232
239
|
# # ]
|
|
233
|
-
def any
|
|
240
|
+
def any(ignore_nulls: true)
|
|
234
241
|
super
|
|
235
242
|
end
|
|
236
243
|
|
|
@@ -378,6 +385,13 @@ module Polars
|
|
|
378
385
|
|
|
379
386
|
# Evaluate whether all boolean values are true for every subarray.
|
|
380
387
|
#
|
|
388
|
+
# @param ignore_nulls [Boolean]
|
|
389
|
+
# * If set to `true` (default), null values are ignored. If there
|
|
390
|
+
# are no non-null values, the output is `true`.
|
|
391
|
+
# * If set to `false`, [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic) is used to deal with nulls:
|
|
392
|
+
# if the column contains any null values and no `false` values,
|
|
393
|
+
# the output is null.
|
|
394
|
+
#
|
|
381
395
|
# @return [Series]
|
|
382
396
|
#
|
|
383
397
|
# @example
|
|
@@ -396,7 +410,7 @@ module Polars
|
|
|
396
410
|
# # true
|
|
397
411
|
# # null
|
|
398
412
|
# # ]
|
|
399
|
-
def all
|
|
413
|
+
def all(ignore_nulls: true)
|
|
400
414
|
super
|
|
401
415
|
end
|
|
402
416
|
|