polars-df 0.21.0 → 0.22.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 +27 -0
- data/Cargo.lock +55 -48
- data/Cargo.toml +3 -0
- data/README.md +12 -0
- data/ext/polars/Cargo.toml +22 -11
- data/ext/polars/src/batched_csv.rs +4 -4
- data/ext/polars/src/catalog/unity.rs +96 -94
- data/ext/polars/src/conversion/any_value.rs +26 -30
- data/ext/polars/src/conversion/chunked_array.rs +32 -28
- data/ext/polars/src/conversion/datetime.rs +11 -0
- data/ext/polars/src/conversion/mod.rs +307 -34
- data/ext/polars/src/dataframe/construction.rs +4 -3
- data/ext/polars/src/dataframe/export.rs +17 -15
- data/ext/polars/src/dataframe/general.rs +15 -12
- data/ext/polars/src/dataframe/io.rs +1 -2
- data/ext/polars/src/dataframe/mod.rs +25 -1
- data/ext/polars/src/dataframe/serde.rs +23 -8
- data/ext/polars/src/exceptions.rs +8 -4
- data/ext/polars/src/expr/array.rs +73 -4
- data/ext/polars/src/expr/binary.rs +26 -1
- data/ext/polars/src/expr/bitwise.rs +39 -0
- data/ext/polars/src/expr/categorical.rs +20 -0
- data/ext/polars/src/expr/datatype.rs +24 -1
- data/ext/polars/src/expr/datetime.rs +58 -14
- data/ext/polars/src/expr/general.rs +87 -15
- data/ext/polars/src/expr/list.rs +32 -24
- data/ext/polars/src/expr/meta.rs +15 -6
- data/ext/polars/src/expr/mod.rs +3 -0
- data/ext/polars/src/expr/name.rs +19 -14
- data/ext/polars/src/expr/rolling.rs +20 -0
- data/ext/polars/src/expr/serde.rs +28 -0
- data/ext/polars/src/expr/string.rs +64 -10
- data/ext/polars/src/expr/struct.rs +9 -1
- data/ext/polars/src/file.rs +15 -9
- data/ext/polars/src/functions/business.rs +0 -1
- data/ext/polars/src/functions/io.rs +25 -3
- data/ext/polars/src/functions/lazy.rs +11 -6
- data/ext/polars/src/functions/meta.rs +3 -3
- data/ext/polars/src/functions/string_cache.rs +3 -3
- data/ext/polars/src/interop/arrow/to_ruby.rs +3 -3
- data/ext/polars/src/interop/numo/numo_rs.rs +4 -3
- data/ext/polars/src/io/mod.rs +6 -0
- data/ext/polars/src/lazyframe/general.rs +59 -9
- data/ext/polars/src/lazyframe/mod.rs +16 -1
- data/ext/polars/src/lazyframe/optflags.rs +58 -0
- data/ext/polars/src/lazyframe/serde.rs +27 -3
- data/ext/polars/src/lib.rs +261 -19
- data/ext/polars/src/map/dataframe.rs +20 -17
- data/ext/polars/src/map/lazy.rs +6 -5
- data/ext/polars/src/map/series.rs +8 -7
- data/ext/polars/src/on_startup.rs +12 -5
- data/ext/polars/src/rb_modules.rs +2 -2
- data/ext/polars/src/series/aggregation.rs +85 -28
- data/ext/polars/src/series/construction.rs +1 -0
- data/ext/polars/src/series/export.rs +37 -33
- data/ext/polars/src/series/general.rs +120 -21
- data/ext/polars/src/series/mod.rs +29 -4
- data/lib/polars/array_expr.rb +382 -3
- data/lib/polars/array_name_space.rb +281 -0
- data/lib/polars/binary_expr.rb +67 -0
- data/lib/polars/binary_name_space.rb +43 -0
- data/lib/polars/cat_expr.rb +224 -0
- data/lib/polars/cat_name_space.rb +138 -0
- data/lib/polars/config.rb +2 -2
- data/lib/polars/convert.rb +6 -6
- data/lib/polars/data_frame.rb +794 -27
- data/lib/polars/data_type_expr.rb +52 -0
- data/lib/polars/data_types.rb +26 -5
- data/lib/polars/date_time_expr.rb +252 -1
- data/lib/polars/date_time_name_space.rb +299 -0
- data/lib/polars/expr.rb +1248 -206
- data/lib/polars/functions/business.rb +95 -0
- data/lib/polars/functions/datatype.rb +21 -0
- data/lib/polars/functions/lazy.rb +14 -1
- data/lib/polars/io/csv.rb +1 -1
- data/lib/polars/io/iceberg.rb +27 -0
- data/lib/polars/io/json.rb +4 -4
- data/lib/polars/io/ndjson.rb +4 -4
- data/lib/polars/io/parquet.rb +32 -7
- data/lib/polars/io/scan_options.rb +4 -1
- data/lib/polars/lazy_frame.rb +1028 -28
- data/lib/polars/list_expr.rb +217 -17
- data/lib/polars/list_name_space.rb +231 -22
- data/lib/polars/meta_expr.rb +89 -0
- data/lib/polars/name_expr.rb +36 -0
- data/lib/polars/query_opt_flags.rb +50 -0
- data/lib/polars/scan_cast_options.rb +20 -1
- data/lib/polars/schema.rb +79 -3
- data/lib/polars/selector.rb +72 -0
- data/lib/polars/selectors.rb +3 -3
- data/lib/polars/series.rb +1053 -54
- data/lib/polars/string_expr.rb +436 -32
- data/lib/polars/string_name_space.rb +736 -50
- data/lib/polars/struct_expr.rb +103 -0
- data/lib/polars/struct_name_space.rb +19 -1
- data/lib/polars/utils/serde.rb +17 -0
- data/lib/polars/utils/various.rb +22 -1
- data/lib/polars/utils.rb +5 -1
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +6 -0
- metadata +11 -1
@@ -1,4 +1,4 @@
|
|
1
|
-
use magnus::{IntoValue, RArray, TryConvert, Value,
|
1
|
+
use magnus::{IntoValue, RArray, Ruby, TryConvert, Value, prelude::*, typed_data::Obj};
|
2
2
|
use polars::prelude::*;
|
3
3
|
use polars_core::frame::row::{Row, rows_to_schema_first_non_null};
|
4
4
|
use polars_core::series::SeriesIter;
|
@@ -6,14 +6,14 @@ use polars_core::series::SeriesIter;
|
|
6
6
|
use super::*;
|
7
7
|
use crate::{RbDataFrame, RbPolarsErr, RbSeries, Wrap};
|
8
8
|
|
9
|
-
fn get_iters(df: &DataFrame) -> Vec<SeriesIter
|
9
|
+
fn get_iters(df: &DataFrame) -> Vec<SeriesIter<'_>> {
|
10
10
|
df.get_columns()
|
11
11
|
.iter()
|
12
12
|
.map(|s| s.as_materialized_series().iter())
|
13
13
|
.collect()
|
14
14
|
}
|
15
15
|
|
16
|
-
fn get_iters_skip(df: &DataFrame, skip: usize) -> Vec<std::iter::Skip<SeriesIter
|
16
|
+
fn get_iters_skip(df: &DataFrame, skip: usize) -> Vec<std::iter::Skip<SeriesIter<'_>>> {
|
17
17
|
df.get_columns()
|
18
18
|
.iter()
|
19
19
|
.map(|s| s.as_materialized_series().iter().skip(skip))
|
@@ -25,32 +25,35 @@ pub fn apply_lambda_unknown<'a>(
|
|
25
25
|
lambda: Value,
|
26
26
|
inference_size: usize,
|
27
27
|
) -> RbResult<(Value, bool)> {
|
28
|
+
let ruby = Ruby::get_with(lambda);
|
28
29
|
let mut null_count = 0;
|
29
30
|
let mut iters = get_iters(df);
|
30
31
|
|
31
32
|
for _ in 0..df.height() {
|
32
33
|
let iter = iters.iter_mut().map(|it| Wrap(it.next().unwrap()));
|
33
|
-
let arg = (
|
34
|
+
let arg = (ruby.ary_from_iter(iter),);
|
34
35
|
let out: Value = lambda.funcall("call", arg)?;
|
35
36
|
|
36
37
|
if out.is_nil() {
|
37
38
|
null_count += 1;
|
38
39
|
continue;
|
39
|
-
} else if out.is_kind_of(
|
40
|
+
} else if out.is_kind_of(ruby.class_true_class())
|
41
|
+
|| out.is_kind_of(ruby.class_false_class())
|
42
|
+
{
|
40
43
|
let first_value = bool::try_convert(out).ok();
|
41
44
|
return Ok((
|
42
|
-
|
45
|
+
ruby.obj_wrap(RbSeries::new(
|
43
46
|
apply_lambda_with_bool_out_type(df, lambda, null_count, first_value)
|
44
47
|
.into_series(),
|
45
48
|
))
|
46
49
|
.as_value(),
|
47
50
|
false,
|
48
51
|
));
|
49
|
-
} else if out.is_kind_of(
|
52
|
+
} else if out.is_kind_of(ruby.class_float()) {
|
50
53
|
let first_value = f64::try_convert(out).ok();
|
51
54
|
|
52
55
|
return Ok((
|
53
|
-
|
56
|
+
ruby.obj_wrap(RbSeries::new(
|
54
57
|
apply_lambda_with_primitive_out_type::<Float64Type>(
|
55
58
|
df,
|
56
59
|
lambda,
|
@@ -62,10 +65,10 @@ pub fn apply_lambda_unknown<'a>(
|
|
62
65
|
.as_value(),
|
63
66
|
false,
|
64
67
|
));
|
65
|
-
} else if out.is_kind_of(
|
68
|
+
} else if out.is_kind_of(ruby.class_integer()) {
|
66
69
|
let first_value = i64::try_convert(out).ok();
|
67
70
|
return Ok((
|
68
|
-
|
71
|
+
ruby.obj_wrap(RbSeries::new(
|
69
72
|
apply_lambda_with_primitive_out_type::<Int64Type>(
|
70
73
|
df,
|
71
74
|
lambda,
|
@@ -77,7 +80,7 @@ pub fn apply_lambda_unknown<'a>(
|
|
77
80
|
.as_value(),
|
78
81
|
false,
|
79
82
|
));
|
80
|
-
// } else if out.is_kind_of(
|
83
|
+
// } else if out.is_kind_of(ruby.class_string()) {
|
81
84
|
// let first_value = String::try_convert(out).ok();
|
82
85
|
// return Ok((
|
83
86
|
// RbSeries::new(
|
@@ -92,7 +95,7 @@ pub fn apply_lambda_unknown<'a>(
|
|
92
95
|
let series = rb_rbseries.series.borrow();
|
93
96
|
let dt = series.dtype();
|
94
97
|
return Ok((
|
95
|
-
|
98
|
+
ruby.obj_wrap(RbSeries::new(
|
96
99
|
apply_lambda_with_list_out_type(df, lambda, null_count, Some(&series), dt)?
|
97
100
|
.into_series(),
|
98
101
|
))
|
@@ -102,7 +105,7 @@ pub fn apply_lambda_unknown<'a>(
|
|
102
105
|
} else if Wrap::<Row<'a>>::try_convert(out).is_ok() {
|
103
106
|
let first_value = Wrap::<Row<'a>>::try_convert(out).unwrap().0;
|
104
107
|
return Ok((
|
105
|
-
|
108
|
+
ruby.obj_wrap(RbDataFrame::from(
|
106
109
|
apply_lambda_with_rows_output(
|
107
110
|
df,
|
108
111
|
lambda,
|
@@ -115,7 +118,7 @@ pub fn apply_lambda_unknown<'a>(
|
|
115
118
|
.as_value(),
|
116
119
|
true,
|
117
120
|
));
|
118
|
-
} else if out.is_kind_of(
|
121
|
+
} else if out.is_kind_of(ruby.class_array()) {
|
119
122
|
return Err(RbPolarsErr::Other(
|
120
123
|
"A list output type is invalid. Do you mean to create polars List Series?\
|
121
124
|
Then return a Series object."
|
@@ -141,7 +144,7 @@ where
|
|
141
144
|
let mut iters = get_iters_skip(df, init_null_count + skip);
|
142
145
|
((init_null_count + skip)..df.height()).map(move |_| {
|
143
146
|
let iter = iters.iter_mut().map(|it| Wrap(it.next().unwrap()));
|
144
|
-
let tpl = (
|
147
|
+
let tpl = (Ruby::get_with(lambda).ary_from_iter(iter),);
|
145
148
|
match lambda.funcall::<_, _, Value>("call", tpl) {
|
146
149
|
Ok(val) => T::try_convert(val).ok(),
|
147
150
|
Err(e) => panic!("ruby function failed {e}"),
|
@@ -237,7 +240,7 @@ pub fn apply_lambda_with_list_out_type(
|
|
237
240
|
let mut iters = get_iters_skip(df, init_null_count + skip);
|
238
241
|
let iter = ((init_null_count + skip)..df.height()).map(|_| {
|
239
242
|
let iter = iters.iter_mut().map(|it| Wrap(it.next().unwrap()));
|
240
|
-
let tpl = (
|
243
|
+
let tpl = (Ruby::get_with(lambda).ary_from_iter(iter),);
|
241
244
|
match lambda.funcall::<_, _, Value>("call", tpl) {
|
242
245
|
Ok(val) => match val.funcall::<_, _, Value>("_s", ()) {
|
243
246
|
Ok(val) => Obj::<RbSeries>::try_convert(val)
|
@@ -281,7 +284,7 @@ pub fn apply_lambda_with_rows_output<'a>(
|
|
281
284
|
let mut iters = get_iters_skip(df, init_null_count + skip);
|
282
285
|
let mut row_iter = ((init_null_count + skip)..df.height()).map(|_| {
|
283
286
|
let iter = iters.iter_mut().map(|it| Wrap(it.next().unwrap()));
|
284
|
-
let tpl = (
|
287
|
+
let tpl = (Ruby::get_with(lambda).ary_from_iter(iter),);
|
285
288
|
match lambda.funcall::<_, _, Value>("call", tpl) {
|
286
289
|
Ok(val) => {
|
287
290
|
match RArray::try_convert(val).ok() {
|
data/ext/polars/src/map/lazy.rs
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
use magnus::{
|
1
|
+
use magnus::{Ruby, Value, prelude::*};
|
2
2
|
use polars::prelude::*;
|
3
3
|
|
4
4
|
use crate::rb_modules::*;
|
5
5
|
use crate::{RbExpr, RbSeries, Wrap};
|
6
6
|
|
7
7
|
fn to_series(v: Value, name: &str) -> PolarsResult<Series> {
|
8
|
+
let ruby = Ruby::get_with(v);
|
8
9
|
let rb_rbseries = match v.funcall("_s", ()) {
|
9
10
|
Ok(s) => s,
|
10
11
|
// the lambda did not return a series, we try to create a new Ruby Series
|
11
12
|
_ => {
|
12
|
-
let data =
|
13
|
+
let data = ruby.ary_new();
|
13
14
|
data.push(v).unwrap();
|
14
|
-
let res =
|
15
|
+
let res = pl_series().funcall::<_, _, Value>("new", (name.to_string(), data));
|
15
16
|
|
16
17
|
match res {
|
17
18
|
Ok(ruby_s) => ruby_s.funcall::<_, _, &RbSeries>("_s", ()).unwrap(),
|
@@ -34,8 +35,8 @@ pub fn binary_lambda(lambda: Value, a: Series, b: Series) -> PolarsResult<Option
|
|
34
35
|
let rbseries_b = RbSeries::new(b);
|
35
36
|
|
36
37
|
// Wrap this RbSeries object in the Ruby side Series wrapper
|
37
|
-
let ruby_series_wrapper_a: Value =
|
38
|
-
let ruby_series_wrapper_b: Value =
|
38
|
+
let ruby_series_wrapper_a: Value = pl_utils().funcall("wrap_s", (rbseries_a,)).unwrap();
|
39
|
+
let ruby_series_wrapper_b: Value = pl_utils().funcall("wrap_s", (rbseries_b,)).unwrap();
|
39
40
|
|
40
41
|
// call the lambda and get a Ruby side Series wrapper
|
41
42
|
let result_series_wrapper: Value =
|
@@ -1,4 +1,4 @@
|
|
1
|
-
use magnus::{IntoValue, TryConvert, Value,
|
1
|
+
use magnus::{IntoValue, Ruby, TryConvert, Value, prelude::*, typed_data::Obj};
|
2
2
|
use polars::prelude::*;
|
3
3
|
|
4
4
|
use super::*;
|
@@ -12,12 +12,13 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
|
|
12
12
|
out: Value,
|
13
13
|
null_count: usize,
|
14
14
|
) -> RbResult<RbSeries> {
|
15
|
-
|
15
|
+
let ruby = Ruby::get_with(lambda);
|
16
|
+
if out.is_kind_of(ruby.class_true_class()) || out.is_kind_of(ruby.class_false_class()) {
|
16
17
|
let first_value = bool::try_convert(out).unwrap();
|
17
18
|
applyer
|
18
19
|
.apply_lambda_with_bool_out_type(lambda, null_count, Some(first_value))
|
19
20
|
.map(|ca| ca.into_series().into())
|
20
|
-
} else if out.is_kind_of(
|
21
|
+
} else if out.is_kind_of(ruby.class_float()) {
|
21
22
|
let first_value = f64::try_convert(out).unwrap();
|
22
23
|
applyer
|
23
24
|
.apply_lambda_with_primitive_out_type::<Float64Type>(
|
@@ -26,7 +27,7 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
|
|
26
27
|
Some(first_value),
|
27
28
|
)
|
28
29
|
.map(|ca| ca.into_series().into())
|
29
|
-
} else if out.is_kind_of(
|
30
|
+
} else if out.is_kind_of(ruby.class_string()) {
|
30
31
|
let first_value = String::try_convert(out).unwrap();
|
31
32
|
applyer
|
32
33
|
.apply_lambda_with_utf8_out_type(lambda, null_count, Some(first_value.as_str()))
|
@@ -38,9 +39,9 @@ fn infer_and_finish<'a, A: ApplyLambda<'a>>(
|
|
38
39
|
applyer
|
39
40
|
.apply_lambda_with_list_out_type(lambda, null_count, &series, dt)
|
40
41
|
.map(|ca| ca.into_series().into())
|
41
|
-
} else if out.is_kind_of(
|
42
|
+
} else if out.is_kind_of(ruby.class_array()) {
|
42
43
|
todo!()
|
43
|
-
} else if out.is_kind_of(
|
44
|
+
} else if out.is_kind_of(ruby.class_hash()) {
|
44
45
|
let first = Wrap::<AnyValue<'_>>::try_convert(out)?;
|
45
46
|
applyer.apply_into_struct(lambda, null_count, first.0)
|
46
47
|
}
|
@@ -999,7 +1000,7 @@ impl<'a> ApplyLambda<'a> for StringChunked {
|
|
999
1000
|
}
|
1000
1001
|
}
|
1001
1002
|
|
1002
|
-
fn iter_struct(ca: &StructChunked) -> impl Iterator<Item = AnyValue
|
1003
|
+
fn iter_struct(ca: &StructChunked) -> impl Iterator<Item = AnyValue<'_>> {
|
1003
1004
|
(0..ca.len()).map(|i| unsafe { ca.get_any_value_unchecked(i) })
|
1004
1005
|
}
|
1005
1006
|
|
@@ -2,15 +2,23 @@ use std::any::Any;
|
|
2
2
|
use std::sync::Arc;
|
3
3
|
use std::sync::OnceLock;
|
4
4
|
|
5
|
-
use magnus::IntoValue;
|
5
|
+
use magnus::{IntoValue, Ruby, Value, prelude::*};
|
6
6
|
use polars::prelude::*;
|
7
7
|
use polars_core::chunked_array::object::builder::ObjectChunkedBuilder;
|
8
8
|
use polars_core::chunked_array::object::registry;
|
9
9
|
use polars_core::chunked_array::object::registry::AnonymousObjectBuilder;
|
10
10
|
use polars_core::prelude::AnyValue;
|
11
|
+
use polars_error::PolarsWarning;
|
11
12
|
|
12
13
|
use crate::Wrap;
|
13
14
|
use crate::prelude::ObjectValue;
|
15
|
+
use crate::rb_modules::pl_utils;
|
16
|
+
|
17
|
+
fn warning_function(msg: &str, _warning: PolarsWarning) {
|
18
|
+
if let Err(e) = pl_utils().funcall::<_, _, Value>("_polars_warn", (msg.to_string(),)) {
|
19
|
+
eprintln!("{e}")
|
20
|
+
}
|
21
|
+
}
|
14
22
|
|
15
23
|
static POLARS_REGISTRY_INIT_LOCK: OnceLock<()> = OnceLock::new();
|
16
24
|
|
@@ -23,12 +31,12 @@ pub(crate) fn register_startup_deps() {
|
|
23
31
|
|
24
32
|
let object_converter = Arc::new(|av: AnyValue| {
|
25
33
|
let object = ObjectValue {
|
26
|
-
inner: Wrap(av).
|
34
|
+
inner: Wrap(av).into_value_with(&Ruby::get().unwrap()).into(),
|
27
35
|
};
|
28
36
|
Box::new(object) as Box<dyn Any>
|
29
37
|
});
|
30
38
|
let rbobject_converter = Arc::new(|av: AnyValue| {
|
31
|
-
let object = Wrap(av).
|
39
|
+
let object = Wrap(av).into_value_with(&Ruby::get().unwrap());
|
32
40
|
Box::new(object) as Box<dyn Any>
|
33
41
|
});
|
34
42
|
|
@@ -40,8 +48,7 @@ pub(crate) fn register_startup_deps() {
|
|
40
48
|
rbobject_converter,
|
41
49
|
physical_dtype,
|
42
50
|
);
|
43
|
-
// TODO
|
44
51
|
// Register warning function for `polars_warn!`.
|
45
|
-
|
52
|
+
polars_error::set_warning_function(warning_function);
|
46
53
|
});
|
47
54
|
}
|
@@ -9,13 +9,13 @@ pub(crate) fn polars() -> RModule {
|
|
9
9
|
static SERIES: Lazy<RClass> =
|
10
10
|
Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Series").unwrap());
|
11
11
|
|
12
|
-
pub(crate) fn
|
12
|
+
pub(crate) fn pl_series() -> RClass {
|
13
13
|
Ruby::get().unwrap().get_inner(&SERIES)
|
14
14
|
}
|
15
15
|
|
16
16
|
static UTILS: Lazy<RModule> = Lazy::new(|ruby| ruby.get_inner(&POLARS).const_get("Utils").unwrap());
|
17
17
|
|
18
|
-
pub(crate) fn
|
18
|
+
pub(crate) fn pl_utils() -> RModule {
|
19
19
|
Ruby::get().unwrap().get_inner(&UTILS)
|
20
20
|
}
|
21
21
|
|
@@ -1,7 +1,12 @@
|
|
1
1
|
use crate::error::RbPolarsErr;
|
2
2
|
use crate::prelude::*;
|
3
3
|
use crate::{RbResult, RbSeries};
|
4
|
-
use magnus::{IntoValue, Value};
|
4
|
+
use magnus::{IntoValue, Ruby, Value};
|
5
|
+
|
6
|
+
fn scalar_to_rb(scalar: RbResult<Scalar>) -> RbResult<Value> {
|
7
|
+
let ruby = Ruby::get().unwrap();
|
8
|
+
Ok(Wrap(scalar?.as_any_value()).into_value_with(&ruby))
|
9
|
+
}
|
5
10
|
|
6
11
|
impl RbSeries {
|
7
12
|
pub fn any(&self, ignore_nulls: bool) -> RbResult<Option<bool>> {
|
@@ -32,40 +37,44 @@ impl RbSeries {
|
|
32
37
|
self.series.borrow().arg_min()
|
33
38
|
}
|
34
39
|
|
35
|
-
pub fn max(&
|
40
|
+
pub fn max(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
36
41
|
Ok(Wrap(
|
37
|
-
|
42
|
+
rb_self
|
43
|
+
.series
|
38
44
|
.borrow()
|
39
45
|
.max_reduce()
|
40
46
|
.map_err(RbPolarsErr::from)?
|
41
47
|
.as_any_value(),
|
42
48
|
)
|
43
|
-
.
|
49
|
+
.into_value_with(ruby))
|
44
50
|
}
|
45
51
|
|
46
|
-
pub fn mean(&
|
47
|
-
match
|
52
|
+
pub fn mean(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
53
|
+
match rb_self.series.borrow().dtype() {
|
48
54
|
DataType::Boolean => Ok(Wrap(
|
49
|
-
|
55
|
+
rb_self
|
56
|
+
.series
|
50
57
|
.borrow()
|
51
58
|
.cast(&DataType::UInt8)
|
52
59
|
.unwrap()
|
53
60
|
.mean_reduce()
|
54
61
|
.as_any_value(),
|
55
62
|
)
|
56
|
-
.
|
63
|
+
.into_value_with(ruby)),
|
57
64
|
// For non-numeric output types we require mean_reduce.
|
58
|
-
dt if dt.is_temporal() =>
|
59
|
-
|
60
|
-
|
61
|
-
|
65
|
+
dt if dt.is_temporal() => Ok(Wrap(
|
66
|
+
rb_self.series.borrow().mean_reduce().as_any_value(),
|
67
|
+
)
|
68
|
+
.into_value_with(ruby)),
|
69
|
+
_ => Ok(rb_self.series.borrow().mean().into_value_with(ruby)),
|
62
70
|
}
|
63
71
|
}
|
64
72
|
|
65
|
-
pub fn median(&
|
66
|
-
match
|
73
|
+
pub fn median(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
74
|
+
match rb_self.series.borrow().dtype() {
|
67
75
|
DataType::Boolean => Ok(Wrap(
|
68
|
-
|
76
|
+
rb_self
|
77
|
+
.series
|
69
78
|
.borrow()
|
70
79
|
.cast(&DataType::UInt8)
|
71
80
|
.unwrap()
|
@@ -73,49 +82,97 @@ impl RbSeries {
|
|
73
82
|
.map_err(RbPolarsErr::from)?
|
74
83
|
.as_any_value(),
|
75
84
|
)
|
76
|
-
.
|
85
|
+
.into_value_with(ruby)),
|
77
86
|
// For non-numeric output types we require median_reduce.
|
78
87
|
dt if dt.is_temporal() => Ok(Wrap(
|
79
|
-
|
88
|
+
rb_self
|
89
|
+
.series
|
80
90
|
.borrow()
|
81
91
|
.median_reduce()
|
82
92
|
.map_err(RbPolarsErr::from)?
|
83
93
|
.as_any_value(),
|
84
94
|
)
|
85
|
-
.
|
86
|
-
_ => Ok(
|
95
|
+
.into_value_with(ruby)),
|
96
|
+
_ => Ok(rb_self.series.borrow().median().into_value_with(ruby)),
|
87
97
|
}
|
88
98
|
}
|
89
99
|
|
90
|
-
pub fn min(&
|
100
|
+
pub fn min(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
91
101
|
Ok(Wrap(
|
92
|
-
|
102
|
+
rb_self
|
103
|
+
.series
|
93
104
|
.borrow()
|
94
105
|
.min_reduce()
|
95
106
|
.map_err(RbPolarsErr::from)?
|
96
107
|
.as_any_value(),
|
97
108
|
)
|
98
|
-
.
|
109
|
+
.into_value_with(ruby))
|
99
110
|
}
|
100
111
|
|
101
|
-
pub fn quantile(
|
102
|
-
|
112
|
+
pub fn quantile(
|
113
|
+
ruby: &Ruby,
|
114
|
+
rb_self: &Self,
|
115
|
+
quantile: f64,
|
116
|
+
interpolation: Wrap<QuantileMethod>,
|
117
|
+
) -> RbResult<Value> {
|
118
|
+
let bind = rb_self
|
103
119
|
.series
|
104
120
|
.borrow()
|
105
121
|
.quantile_reduce(quantile, interpolation.0);
|
106
122
|
let sc = bind.map_err(RbPolarsErr::from)?;
|
107
123
|
|
108
|
-
Ok(Wrap(sc.as_any_value()).
|
124
|
+
Ok(Wrap(sc.as_any_value()).into_value_with(ruby))
|
109
125
|
}
|
110
126
|
|
111
|
-
pub fn sum(&
|
127
|
+
pub fn sum(ruby: &Ruby, rb_self: &Self) -> RbResult<Value> {
|
112
128
|
Ok(Wrap(
|
113
|
-
|
129
|
+
rb_self
|
130
|
+
.series
|
114
131
|
.borrow()
|
115
132
|
.sum_reduce()
|
116
133
|
.map_err(RbPolarsErr::from)?
|
117
134
|
.as_any_value(),
|
118
135
|
)
|
119
|
-
.
|
136
|
+
.into_value_with(ruby))
|
137
|
+
}
|
138
|
+
|
139
|
+
pub fn first(&self) -> RbResult<Value> {
|
140
|
+
scalar_to_rb(Ok(self.series.borrow().first()))
|
141
|
+
}
|
142
|
+
|
143
|
+
pub fn last(&self) -> RbResult<Value> {
|
144
|
+
scalar_to_rb(Ok(self.series.borrow().last()))
|
145
|
+
}
|
146
|
+
|
147
|
+
pub fn approx_n_unique(&self) -> RbResult<IdxSize> {
|
148
|
+
Ok(self
|
149
|
+
.series
|
150
|
+
.borrow()
|
151
|
+
.approx_n_unique()
|
152
|
+
.map_err(RbPolarsErr::from)?)
|
153
|
+
}
|
154
|
+
|
155
|
+
pub fn bitwise_and(&self) -> RbResult<Value> {
|
156
|
+
scalar_to_rb(Ok(self
|
157
|
+
.series
|
158
|
+
.borrow()
|
159
|
+
.and_reduce()
|
160
|
+
.map_err(RbPolarsErr::from)?))
|
161
|
+
}
|
162
|
+
|
163
|
+
pub fn bitwise_or(&self) -> RbResult<Value> {
|
164
|
+
scalar_to_rb(Ok(self
|
165
|
+
.series
|
166
|
+
.borrow()
|
167
|
+
.or_reduce()
|
168
|
+
.map_err(RbPolarsErr::from)?))
|
169
|
+
}
|
170
|
+
|
171
|
+
pub fn bitwise_xor(&self) -> RbResult<Value> {
|
172
|
+
scalar_to_rb(Ok(self
|
173
|
+
.series
|
174
|
+
.borrow()
|
175
|
+
.xor_reduce()
|
176
|
+
.map_err(RbPolarsErr::from)?))
|
120
177
|
}
|
121
178
|
}
|
@@ -79,6 +79,7 @@ init_method_opt!(new_opt_i8, Int8Type, i8);
|
|
79
79
|
init_method_opt!(new_opt_i16, Int16Type, i16);
|
80
80
|
init_method_opt!(new_opt_i32, Int32Type, i32);
|
81
81
|
init_method_opt!(new_opt_i64, Int64Type, i64);
|
82
|
+
init_method_opt!(new_opt_i128, Int128Type, i128);
|
82
83
|
init_method_opt!(new_opt_f32, Float32Type, f32);
|
83
84
|
init_method_opt!(new_opt_f64, Float64Type, f64);
|
84
85
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
use magnus::{IntoValue,
|
1
|
+
use magnus::{IntoValue, Ruby, Value, value::ReprValue};
|
2
2
|
use polars_core::prelude::*;
|
3
3
|
|
4
4
|
use crate::RbSeries;
|
@@ -11,42 +11,43 @@ impl RbSeries {
|
|
11
11
|
let series = &self.series.borrow();
|
12
12
|
|
13
13
|
fn to_a_recursive(series: &Series) -> Value {
|
14
|
+
let ruby = Ruby::get().unwrap();
|
14
15
|
let rblist = match series.dtype() {
|
15
|
-
DataType::Boolean =>
|
16
|
-
DataType::UInt8 =>
|
17
|
-
DataType::UInt16 =>
|
18
|
-
DataType::UInt32 =>
|
19
|
-
DataType::UInt64 =>
|
20
|
-
DataType::Int8 =>
|
21
|
-
DataType::Int16 =>
|
22
|
-
DataType::Int32 =>
|
23
|
-
DataType::Int64 =>
|
24
|
-
DataType::Int128 =>
|
25
|
-
DataType::Float32 =>
|
26
|
-
DataType::Float64 =>
|
16
|
+
DataType::Boolean => ruby.ary_from_iter(series.bool().unwrap()).as_value(),
|
17
|
+
DataType::UInt8 => ruby.ary_from_iter(series.u8().unwrap()).as_value(),
|
18
|
+
DataType::UInt16 => ruby.ary_from_iter(series.u16().unwrap()).as_value(),
|
19
|
+
DataType::UInt32 => ruby.ary_from_iter(series.u32().unwrap()).as_value(),
|
20
|
+
DataType::UInt64 => ruby.ary_from_iter(series.u64().unwrap()).as_value(),
|
21
|
+
DataType::Int8 => ruby.ary_from_iter(series.i8().unwrap()).as_value(),
|
22
|
+
DataType::Int16 => ruby.ary_from_iter(series.i16().unwrap()).as_value(),
|
23
|
+
DataType::Int32 => ruby.ary_from_iter(series.i32().unwrap()).as_value(),
|
24
|
+
DataType::Int64 => ruby.ary_from_iter(series.i64().unwrap()).as_value(),
|
25
|
+
DataType::Int128 => ruby.ary_from_iter(series.i128().unwrap()).as_value(),
|
26
|
+
DataType::Float32 => ruby.ary_from_iter(series.f32().unwrap()).as_value(),
|
27
|
+
DataType::Float64 => ruby.ary_from_iter(series.f64().unwrap()).as_value(),
|
27
28
|
DataType::Categorical(_, _) | DataType::Enum(_, _) => {
|
28
29
|
with_match_categorical_physical_type!(series.dtype().cat_physical().unwrap(), |$C| {
|
29
|
-
|
30
|
+
ruby.ary_from_iter(series.cat::<$C>().unwrap().iter_str()).as_value()
|
30
31
|
})
|
31
32
|
}
|
32
33
|
DataType::Object(_) => {
|
33
|
-
let v =
|
34
|
+
let v = ruby.ary_new_capa(series.len());
|
34
35
|
for i in 0..series.len() {
|
35
36
|
let obj: Option<&ObjectValue> = series.get_object(i).map(|any| any.into());
|
36
37
|
match obj {
|
37
38
|
Some(val) => v.push(val.to_value()).unwrap(),
|
38
|
-
None => v.push(qnil()).unwrap(),
|
39
|
+
None => v.push(ruby.qnil()).unwrap(),
|
39
40
|
};
|
40
41
|
}
|
41
|
-
v.
|
42
|
+
v.as_value()
|
42
43
|
}
|
43
44
|
DataType::List(_) => {
|
44
|
-
let v =
|
45
|
+
let v = ruby.ary_new();
|
45
46
|
let ca = series.list().unwrap();
|
46
47
|
for opt_s in ca.amortized_iter() {
|
47
48
|
match opt_s {
|
48
49
|
None => {
|
49
|
-
v.push(qnil()).unwrap();
|
50
|
+
v.push(ruby.qnil()).unwrap();
|
50
51
|
}
|
51
52
|
Some(s) => {
|
52
53
|
let rblst = to_a_recursive(s.as_ref());
|
@@ -54,15 +55,15 @@ impl RbSeries {
|
|
54
55
|
}
|
55
56
|
}
|
56
57
|
}
|
57
|
-
v.
|
58
|
+
v.as_value()
|
58
59
|
}
|
59
60
|
DataType::Array(_, _) => {
|
60
|
-
let v =
|
61
|
+
let v = ruby.ary_new();
|
61
62
|
let ca = series.array().unwrap();
|
62
63
|
for opt_s in ca.amortized_iter() {
|
63
64
|
match opt_s {
|
64
65
|
None => {
|
65
|
-
v.push(qnil()).unwrap();
|
66
|
+
v.push(ruby.qnil()).unwrap();
|
66
67
|
}
|
67
68
|
Some(s) => {
|
68
69
|
let rblst = to_a_recursive(s.as_ref());
|
@@ -70,39 +71,39 @@ impl RbSeries {
|
|
70
71
|
}
|
71
72
|
}
|
72
73
|
}
|
73
|
-
v.
|
74
|
+
v.as_value()
|
74
75
|
}
|
75
76
|
DataType::Date => {
|
76
77
|
let ca = series.date().unwrap();
|
77
|
-
return Wrap(ca).
|
78
|
+
return Wrap(ca).into_value_with(&ruby);
|
78
79
|
}
|
79
80
|
DataType::Time => {
|
80
81
|
let ca = series.time().unwrap();
|
81
|
-
return Wrap(ca).
|
82
|
+
return Wrap(ca).into_value_with(&ruby);
|
82
83
|
}
|
83
84
|
DataType::Datetime(_, _) => {
|
84
85
|
let ca = series.datetime().unwrap();
|
85
|
-
return Wrap(ca).
|
86
|
+
return Wrap(ca).into_value_with(&ruby);
|
86
87
|
}
|
87
88
|
DataType::Decimal(_, _) => {
|
88
89
|
let ca = series.decimal().unwrap();
|
89
|
-
return Wrap(ca).
|
90
|
+
return Wrap(ca).into_value_with(&ruby);
|
90
91
|
}
|
91
92
|
DataType::String => {
|
92
93
|
let ca = series.str().unwrap();
|
93
|
-
return Wrap(ca).
|
94
|
+
return Wrap(ca).into_value_with(&ruby);
|
94
95
|
}
|
95
96
|
DataType::Struct(_) => {
|
96
97
|
let ca = series.struct_().unwrap();
|
97
|
-
return Wrap(ca).
|
98
|
+
return Wrap(ca).into_value_with(&ruby);
|
98
99
|
}
|
99
100
|
DataType::Duration(_) => {
|
100
101
|
let ca = series.duration().unwrap();
|
101
|
-
return Wrap(ca).
|
102
|
+
return Wrap(ca).into_value_with(&ruby);
|
102
103
|
}
|
103
104
|
DataType::Binary => {
|
104
105
|
let ca = series.binary().unwrap();
|
105
|
-
return Wrap(ca).
|
106
|
+
return Wrap(ca).into_value_with(&ruby);
|
106
107
|
}
|
107
108
|
DataType::Null => {
|
108
109
|
let null: Option<u8> = None;
|
@@ -125,7 +126,10 @@ impl RbSeries {
|
|
125
126
|
}
|
126
127
|
impl ExactSizeIterator for NullIter {}
|
127
128
|
|
128
|
-
|
129
|
+
Ruby::get()
|
130
|
+
.unwrap()
|
131
|
+
.ary_from_iter(NullIter { iter, n })
|
132
|
+
.as_value()
|
129
133
|
}
|
130
134
|
DataType::Unknown(_) => {
|
131
135
|
panic!("to_a not implemented for unknown")
|
@@ -134,7 +138,7 @@ impl RbSeries {
|
|
134
138
|
unreachable!()
|
135
139
|
}
|
136
140
|
};
|
137
|
-
rblist.
|
141
|
+
rblist.as_value()
|
138
142
|
}
|
139
143
|
|
140
144
|
to_a_recursive(series)
|