polars-df 0.4.0 → 0.5.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 +12 -0
- data/Cargo.lock +272 -191
- data/Cargo.toml +0 -1
- data/README.md +2 -2
- data/ext/polars/Cargo.toml +8 -4
- data/ext/polars/src/apply/dataframe.rs +2 -2
- data/ext/polars/src/{lazy/apply.rs → apply/lazy.rs} +1 -2
- data/ext/polars/src/apply/mod.rs +1 -0
- data/ext/polars/src/batched_csv.rs +7 -5
- data/ext/polars/src/conversion.rs +106 -4
- data/ext/polars/src/dataframe.rs +19 -17
- data/ext/polars/src/error.rs +0 -4
- data/ext/polars/src/expr/binary.rs +69 -0
- data/ext/polars/src/expr/categorical.rs +10 -0
- data/ext/polars/src/expr/datetime.rs +223 -0
- data/ext/polars/src/expr/general.rs +933 -0
- data/ext/polars/src/expr/list.rs +146 -0
- data/ext/polars/src/{lazy → expr}/meta.rs +16 -6
- data/ext/polars/src/expr/string.rs +313 -0
- data/ext/polars/src/expr/struct.rs +15 -0
- data/ext/polars/src/expr.rs +33 -0
- data/ext/polars/src/functions/eager.rs +93 -0
- data/ext/polars/src/functions/io.rs +34 -0
- data/ext/polars/src/functions/lazy.rs +209 -0
- data/ext/polars/src/functions/meta.rs +8 -0
- data/ext/polars/src/functions/mod.rs +5 -0
- data/ext/polars/src/functions/whenthen.rs +43 -0
- data/ext/polars/src/{lazy/dataframe.rs → lazyframe.rs} +12 -33
- data/ext/polars/src/lazygroupby.rs +29 -0
- data/ext/polars/src/lib.rs +205 -303
- data/ext/polars/src/rb_modules.rs +8 -0
- data/ext/polars/src/series/aggregation.rs +83 -0
- data/ext/polars/src/series/arithmetic.rs +88 -0
- data/ext/polars/src/series/comparison.rs +251 -0
- data/ext/polars/src/series/construction.rs +164 -0
- data/ext/polars/src/series.rs +99 -539
- data/lib/polars/convert.rb +2 -2
- data/lib/polars/data_frame.rb +201 -50
- data/lib/polars/data_types.rb +6 -4
- data/lib/polars/date_time_expr.rb +142 -2
- data/lib/polars/expr.rb +70 -10
- data/lib/polars/lazy_frame.rb +4 -3
- data/lib/polars/lazy_functions.rb +4 -1
- data/lib/polars/list_expr.rb +68 -19
- data/lib/polars/series.rb +181 -73
- data/lib/polars/string_expr.rb +149 -43
- data/lib/polars/string_name_space.rb +4 -4
- data/lib/polars/struct_name_space.rb +32 -0
- data/lib/polars/utils.rb +41 -7
- data/lib/polars/version.rb +1 -1
- data/lib/polars.rb +2 -2
- metadata +26 -11
- data/ext/polars/src/lazy/dsl.rs +0 -1775
- data/ext/polars/src/lazy/mod.rs +0 -5
- data/ext/polars/src/lazy/utils.rs +0 -13
- data/ext/polars/src/list_construction.rs +0 -100
- /data/ext/polars/src/{numo.rs → series/export.rs} +0 -0
- /data/ext/polars/src/{set.rs → series/set_at_idx.rs} +0 -0
data/Cargo.toml
CHANGED
@@ -3,7 +3,6 @@ members = ["ext/polars"]
|
|
3
3
|
|
4
4
|
[patch.crates-io]
|
5
5
|
jsonpath_lib = { git = "https://github.com/ritchie46/jsonpath", rev = "24eaf0b4416edff38a4d1b6b17bc4b9f3f047b4b" }
|
6
|
-
halfbrown = { git = "https://github.com/Licenser/halfbrown", rev = "952023c5dd6461b009bb5ba66b9aa979bd75949f" }
|
7
6
|
|
8
7
|
[profile.release]
|
9
8
|
strip = true
|
data/README.md
CHANGED
@@ -58,9 +58,9 @@ Polars.scan_parquet("file.parquet")
|
|
58
58
|
From Active Record
|
59
59
|
|
60
60
|
```ruby
|
61
|
-
Polars.
|
61
|
+
Polars.read_database(User.all)
|
62
62
|
# or
|
63
|
-
Polars.
|
63
|
+
Polars.read_database("SELECT * FROM users")
|
64
64
|
```
|
65
65
|
|
66
66
|
From JSON
|
data/ext/polars/Cargo.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[package]
|
2
2
|
name = "polars"
|
3
|
-
version = "0.
|
3
|
+
version = "0.5.0"
|
4
4
|
license = "MIT"
|
5
5
|
authors = ["Andrew Kane <andrew@ankane.org>"]
|
6
6
|
edition = "2021"
|
@@ -12,14 +12,15 @@ crate-type = ["cdylib"]
|
|
12
12
|
[dependencies]
|
13
13
|
ahash = "0.8"
|
14
14
|
magnus = "0.5"
|
15
|
-
polars-core = "0.
|
15
|
+
polars-core = "0.29.0"
|
16
16
|
serde_json = "1"
|
17
17
|
smartstring = "1"
|
18
18
|
|
19
19
|
[dependencies.polars]
|
20
|
-
version = "0.
|
20
|
+
version = "0.29.0"
|
21
21
|
features = [
|
22
22
|
"abs",
|
23
|
+
"approx_unique",
|
23
24
|
"arange",
|
24
25
|
"arg_where",
|
25
26
|
"asof_join",
|
@@ -27,7 +28,7 @@ features = [
|
|
27
28
|
"binary_encoding",
|
28
29
|
"concat_str",
|
29
30
|
"cse",
|
30
|
-
"csv
|
31
|
+
"csv",
|
31
32
|
"cum_agg",
|
32
33
|
"cumulative_eval",
|
33
34
|
"dataframe_arithmetic",
|
@@ -49,7 +50,9 @@ features = [
|
|
49
50
|
"json",
|
50
51
|
"lazy",
|
51
52
|
"lazy_regex",
|
53
|
+
"list_count",
|
52
54
|
"list_eval",
|
55
|
+
"list_take",
|
53
56
|
"list_to_struct",
|
54
57
|
"log",
|
55
58
|
"meta",
|
@@ -75,6 +78,7 @@ features = [
|
|
75
78
|
"serde-lazy",
|
76
79
|
"sign",
|
77
80
|
"string_encoding",
|
81
|
+
"string_from_radix",
|
78
82
|
"string_justify",
|
79
83
|
"strings",
|
80
84
|
"timezones",
|
@@ -202,8 +202,8 @@ pub fn apply_lambda_with_utf8_out_type(
|
|
202
202
|
}
|
203
203
|
|
204
204
|
/// Apply a lambda with list output type
|
205
|
-
pub fn apply_lambda_with_list_out_type
|
206
|
-
df: &
|
205
|
+
pub fn apply_lambda_with_list_out_type(
|
206
|
+
df: &DataFrame,
|
207
207
|
lambda: Value,
|
208
208
|
init_null_count: usize,
|
209
209
|
first_value: Option<&Series>,
|
data/ext/polars/src/apply/mod.rs
CHANGED
@@ -68,11 +68,13 @@ impl RbBatchedCsv {
|
|
68
68
|
};
|
69
69
|
|
70
70
|
let overwrite_dtype = overwrite_dtype.map(|overwrite_dtype| {
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
overwrite_dtype
|
72
|
+
.iter()
|
73
|
+
.map(|(name, dtype)| {
|
74
|
+
let dtype = dtype.0.clone();
|
75
|
+
Field::new(name, dtype)
|
76
|
+
})
|
77
|
+
.collect::<Schema>()
|
76
78
|
});
|
77
79
|
|
78
80
|
let overwrite_dtype_slice = overwrite_dtype_slice.map(|overwrite_dtype| {
|
@@ -5,6 +5,7 @@ use magnus::{
|
|
5
5
|
class, exception, r_hash::ForEach, ruby_handle::RubyHandle, Integer, IntoValue, Module, RArray,
|
6
6
|
RFloat, RHash, RString, Symbol, TryConvert, Value, QNIL,
|
7
7
|
};
|
8
|
+
use magnus::encoding::{EncodingCapable, Index};
|
8
9
|
use polars::chunked_array::object::PolarsObjectSafe;
|
9
10
|
use polars::chunked_array::ops::{FillNullLimit, FillNullStrategy};
|
10
11
|
use polars::datatypes::AnyValue;
|
@@ -15,6 +16,7 @@ use polars::prelude::*;
|
|
15
16
|
use polars::series::ops::NullBehavior;
|
16
17
|
use smartstring::alias::String as SmartString;
|
17
18
|
|
19
|
+
use crate::rb_modules::utils;
|
18
20
|
use crate::{RbDataFrame, RbLazyFrame, RbPolarsErr, RbResult, RbSeries, RbValueError};
|
19
21
|
|
20
22
|
pub(crate) fn slice_to_wrapped<T>(slice: &[T]) -> &[Wrap<T>] {
|
@@ -23,6 +25,12 @@ pub(crate) fn slice_to_wrapped<T>(slice: &[T]) -> &[Wrap<T>] {
|
|
23
25
|
unsafe { std::mem::transmute(slice) }
|
24
26
|
}
|
25
27
|
|
28
|
+
pub(crate) fn slice_extract_wrapped<T>(slice: &[Wrap<T>]) -> &[T] {
|
29
|
+
// Safety:
|
30
|
+
// Wrap is transparent.
|
31
|
+
unsafe { std::mem::transmute(slice) }
|
32
|
+
}
|
33
|
+
|
26
34
|
pub(crate) fn vec_extract_wrapped<T>(buf: Vec<Wrap<T>>) -> Vec<T> {
|
27
35
|
// Safety:
|
28
36
|
// Wrap is transparent.
|
@@ -180,7 +188,10 @@ impl IntoValue for Wrap<AnyValue<'_>> {
|
|
180
188
|
t.funcall::<_, _, Value>("utc", ()).unwrap()
|
181
189
|
}
|
182
190
|
}
|
183
|
-
AnyValue::Duration(
|
191
|
+
AnyValue::Duration(v, tu) => {
|
192
|
+
let tu = tu.to_ascii();
|
193
|
+
utils().funcall("_to_ruby_duration", (v, tu)).unwrap()
|
194
|
+
}
|
184
195
|
AnyValue::Time(_v) => todo!(),
|
185
196
|
AnyValue::List(v) => RbSeries::new(v).to_a().into_value(),
|
186
197
|
ref av @ AnyValue::Struct(_, _, flds) => struct_dict(av._iter_struct_av(), flds),
|
@@ -261,6 +272,75 @@ impl IntoValue for Wrap<DataType> {
|
|
261
272
|
}
|
262
273
|
}
|
263
274
|
|
275
|
+
impl IntoValue for Wrap<TimeUnit> {
|
276
|
+
fn into_value_with(self, _: &RubyHandle) -> Value {
|
277
|
+
let tu = match self.0 {
|
278
|
+
TimeUnit::Nanoseconds => "ns",
|
279
|
+
TimeUnit::Microseconds => "us",
|
280
|
+
TimeUnit::Milliseconds => "ms",
|
281
|
+
};
|
282
|
+
tu.into_value()
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
impl IntoValue for Wrap<&Utf8Chunked> {
|
287
|
+
fn into_value_with(self, _: &RubyHandle) -> Value {
|
288
|
+
let iter = self.0.into_iter();
|
289
|
+
RArray::from_iter(iter).into_value()
|
290
|
+
}
|
291
|
+
}
|
292
|
+
|
293
|
+
impl IntoValue for Wrap<&BinaryChunked> {
|
294
|
+
fn into_value_with(self, _: &RubyHandle) -> Value {
|
295
|
+
let iter = self
|
296
|
+
.0
|
297
|
+
.into_iter()
|
298
|
+
.map(|opt_bytes| opt_bytes.map(RString::from_slice));
|
299
|
+
RArray::from_iter(iter).into_value()
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
303
|
+
impl IntoValue for Wrap<&StructChunked> {
|
304
|
+
fn into_value_with(self, _: &RubyHandle) -> Value {
|
305
|
+
let s = self.0.clone().into_series();
|
306
|
+
// todo! iterate its chunks and flatten.
|
307
|
+
// make series::iter() accept a chunk index.
|
308
|
+
let s = s.rechunk();
|
309
|
+
let iter = s.iter().map(|av| {
|
310
|
+
if let AnyValue::Struct(_, _, flds) = av {
|
311
|
+
struct_dict(av._iter_struct_av(), flds)
|
312
|
+
} else {
|
313
|
+
unreachable!()
|
314
|
+
}
|
315
|
+
});
|
316
|
+
|
317
|
+
RArray::from_iter(iter).into_value()
|
318
|
+
}
|
319
|
+
}
|
320
|
+
|
321
|
+
impl IntoValue for Wrap<&DurationChunked> {
|
322
|
+
fn into_value_with(self, _: &RubyHandle) -> Value {
|
323
|
+
let utils = utils();
|
324
|
+
let tu = Wrap(self.0.time_unit()).into_value();
|
325
|
+
let iter = self.0.into_iter().map(|opt_v| {
|
326
|
+
opt_v.map(|v| {
|
327
|
+
utils
|
328
|
+
.funcall::<_, _, Value>("_to_ruby_duration", (v, tu))
|
329
|
+
.unwrap()
|
330
|
+
})
|
331
|
+
});
|
332
|
+
RArray::from_iter(iter).into_value()
|
333
|
+
}
|
334
|
+
}
|
335
|
+
|
336
|
+
impl TryConvert for Wrap<Field> {
|
337
|
+
fn try_convert(ob: Value) -> RbResult<Self> {
|
338
|
+
let name: String = ob.funcall("name", ())?;
|
339
|
+
let dtype: Wrap<DataType> = ob.funcall("dtype", ())?;
|
340
|
+
Ok(Wrap(Field::new(&name, dtype.0)))
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
264
344
|
impl TryConvert for Wrap<DataType> {
|
265
345
|
fn try_convert(ob: Value) -> RbResult<Self> {
|
266
346
|
let dtype = if ob.is_kind_of(class::class()) {
|
@@ -294,6 +374,20 @@ impl TryConvert for Wrap<DataType> {
|
|
294
374
|
)))
|
295
375
|
}
|
296
376
|
}
|
377
|
+
// TODO improve
|
378
|
+
} else if ob.try_convert::<String>().is_err() {
|
379
|
+
let name = unsafe { ob.class().name() }.into_owned();
|
380
|
+
match name.as_str() {
|
381
|
+
"Polars::Struct" => {
|
382
|
+
let arr: RArray = ob.funcall("fields", ())?;
|
383
|
+
let mut fields = Vec::with_capacity(arr.len());
|
384
|
+
for v in arr.each() {
|
385
|
+
fields.push(v?.try_convert::<Wrap<Field>>()?.0);
|
386
|
+
}
|
387
|
+
DataType::Struct(fields)
|
388
|
+
}
|
389
|
+
_ => todo!(),
|
390
|
+
}
|
297
391
|
} else {
|
298
392
|
match ob.try_convert::<String>()?.as_str() {
|
299
393
|
"u8" => DataType::UInt8,
|
@@ -339,7 +433,11 @@ impl<'s> TryConvert for Wrap<AnyValue<'s>> {
|
|
339
433
|
} else if let Some(v) = RFloat::from_value(ob) {
|
340
434
|
Ok(AnyValue::Float64(v.to_f64()).into())
|
341
435
|
} else if let Some(v) = RString::from_value(ob) {
|
342
|
-
|
436
|
+
if v.enc_get() == Index::utf8() {
|
437
|
+
Ok(AnyValue::Utf8Owned(v.to_string()?.into()).into())
|
438
|
+
} else {
|
439
|
+
Ok(AnyValue::BinaryOwned(unsafe { v.as_slice() }.to_vec()).into())
|
440
|
+
}
|
343
441
|
// call is_a? for ActiveSupport::TimeWithZone
|
344
442
|
} else if ob.funcall::<_, _, bool>("is_a?", (class::time(),))? {
|
345
443
|
let sec = ob.funcall::<_, _, i64>("to_i", ())?;
|
@@ -377,6 +475,10 @@ impl<'s> TryConvert for Wrap<AnyValue<'s>> {
|
|
377
475
|
.map_err(RbPolarsErr::from)?;
|
378
476
|
Ok(Wrap(AnyValue::List(s)))
|
379
477
|
}
|
478
|
+
} else if ob.is_kind_of(crate::rb_modules::datetime()) {
|
479
|
+
let sec: i64 = ob.funcall("to_i", ())?;
|
480
|
+
let nsec: i64 = ob.funcall("nsec", ())?;
|
481
|
+
Ok(Wrap(AnyValue::Datetime(sec * 1_000_000_000 + nsec, TimeUnit::Nanoseconds, &None)))
|
380
482
|
} else if ob.is_kind_of(crate::rb_modules::date()) {
|
381
483
|
// convert to DateTime for UTC
|
382
484
|
let v = ob
|
@@ -410,12 +512,12 @@ impl TryConvert for Wrap<Schema> {
|
|
410
512
|
|
411
513
|
let mut schema = Vec::new();
|
412
514
|
dict.foreach(|key: String, val: Wrap<DataType>| {
|
413
|
-
schema.push(Field::new(&key, val.0));
|
515
|
+
schema.push(Ok(Field::new(&key, val.0)));
|
414
516
|
Ok(ForEach::Continue)
|
415
517
|
})
|
416
518
|
.unwrap();
|
417
519
|
|
418
|
-
Ok(Wrap(schema.into_iter().
|
520
|
+
Ok(Wrap(schema.into_iter().collect::<RbResult<Schema>>()?))
|
419
521
|
}
|
420
522
|
}
|
421
523
|
|
data/ext/polars/src/dataframe.rs
CHANGED
@@ -48,20 +48,25 @@ impl RbDataFrame {
|
|
48
48
|
crate::object::register_object_builder();
|
49
49
|
|
50
50
|
let schema =
|
51
|
-
rows_to_schema_supertypes(&rows, infer_schema_length
|
51
|
+
rows_to_schema_supertypes(&rows, infer_schema_length.map(|n| std::cmp::max(1, n)))
|
52
|
+
.map_err(RbPolarsErr::from)?;
|
52
53
|
// replace inferred nulls with boolean
|
53
54
|
let fields = schema.iter_fields().map(|mut fld| match fld.data_type() {
|
54
55
|
DataType::Null => {
|
55
56
|
fld.coerce(DataType::Boolean);
|
56
57
|
fld
|
57
58
|
}
|
59
|
+
DataType::Decimal(_, _) => {
|
60
|
+
fld.coerce(DataType::Decimal(None, None));
|
61
|
+
fld
|
62
|
+
}
|
58
63
|
_ => fld,
|
59
64
|
});
|
60
|
-
let mut schema = Schema::
|
65
|
+
let mut schema = Schema::from_iter(fields);
|
61
66
|
|
62
67
|
if let Some(schema_overwrite) = schema_overwrite {
|
63
68
|
for (i, (name, dtype)) in schema_overwrite.into_iter().enumerate() {
|
64
|
-
if let Some((name_, dtype_)) = schema.
|
69
|
+
if let Some((name_, dtype_)) = schema.get_at_index_mut(i) {
|
65
70
|
*name_ = name;
|
66
71
|
|
67
72
|
// if user sets dtype unknown, we use the inferred datatype
|
@@ -139,11 +144,13 @@ impl RbDataFrame {
|
|
139
144
|
};
|
140
145
|
|
141
146
|
let overwrite_dtype = overwrite_dtype.map(|overwrite_dtype| {
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
+
overwrite_dtype
|
148
|
+
.iter()
|
149
|
+
.map(|(name, dtype)| {
|
150
|
+
let dtype = dtype.0.clone();
|
151
|
+
Field::new(name, dtype)
|
152
|
+
})
|
153
|
+
.collect::<Schema>()
|
147
154
|
});
|
148
155
|
|
149
156
|
let overwrite_dtype_slice = overwrite_dtype_slice.map(|overwrite_dtype| {
|
@@ -512,12 +519,10 @@ impl RbDataFrame {
|
|
512
519
|
}
|
513
520
|
}
|
514
521
|
}
|
515
|
-
let
|
522
|
+
let _st = st?;
|
516
523
|
|
517
|
-
|
518
|
-
|
519
|
-
_ => None,
|
520
|
-
}
|
524
|
+
// TODO
|
525
|
+
None
|
521
526
|
}
|
522
527
|
|
523
528
|
pub fn write_parquet(
|
@@ -914,10 +919,7 @@ impl RbDataFrame {
|
|
914
919
|
true => pivot_stable,
|
915
920
|
false => pivot,
|
916
921
|
};
|
917
|
-
let agg_expr =
|
918
|
-
Some(aggregate_expr) => Some(aggregate_expr.inner.clone()),
|
919
|
-
None => None,
|
920
|
-
};
|
922
|
+
let agg_expr = aggregate_expr.map(|aggregate_expr| aggregate_expr.inner.clone());
|
921
923
|
let df = fun(
|
922
924
|
&self.df.borrow(),
|
923
925
|
values,
|
data/ext/polars/src/error.rs
CHANGED
@@ -22,10 +22,6 @@ impl RbPolarsErr {
|
|
22
22
|
pub fn other(message: String) -> Error {
|
23
23
|
Error::new(exception::runtime_error(), message)
|
24
24
|
}
|
25
|
-
|
26
|
-
pub fn todo() -> Error {
|
27
|
-
Error::new(exception::runtime_error(), "not implemented yet")
|
28
|
-
}
|
29
25
|
}
|
30
26
|
|
31
27
|
pub struct RbValueError {}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
use polars::prelude::*;
|
2
|
+
|
3
|
+
use crate::RbExpr;
|
4
|
+
|
5
|
+
impl RbExpr {
|
6
|
+
pub fn bin_contains(&self, lit: Vec<u8>) -> Self {
|
7
|
+
self.inner.clone().binary().contains_literal(lit).into()
|
8
|
+
}
|
9
|
+
|
10
|
+
pub fn bin_ends_with(&self, sub: Vec<u8>) -> Self {
|
11
|
+
self.inner.clone().binary().ends_with(sub).into()
|
12
|
+
}
|
13
|
+
|
14
|
+
pub fn bin_starts_with(&self, sub: Vec<u8>) -> Self {
|
15
|
+
self.inner.clone().binary().starts_with(sub).into()
|
16
|
+
}
|
17
|
+
|
18
|
+
pub fn bin_hex_decode(&self, strict: bool) -> Self {
|
19
|
+
self.clone()
|
20
|
+
.inner
|
21
|
+
.map(
|
22
|
+
move |s| {
|
23
|
+
s.binary()?
|
24
|
+
.hex_decode(strict)
|
25
|
+
.map(|s| Some(s.into_series()))
|
26
|
+
},
|
27
|
+
GetOutput::same_type(),
|
28
|
+
)
|
29
|
+
.with_fmt("bin.hex_decode")
|
30
|
+
.into()
|
31
|
+
}
|
32
|
+
|
33
|
+
pub fn bin_base64_decode(&self, strict: bool) -> Self {
|
34
|
+
self.clone()
|
35
|
+
.inner
|
36
|
+
.map(
|
37
|
+
move |s| {
|
38
|
+
s.binary()?
|
39
|
+
.base64_decode(strict)
|
40
|
+
.map(|s| Some(s.into_series()))
|
41
|
+
},
|
42
|
+
GetOutput::same_type(),
|
43
|
+
)
|
44
|
+
.with_fmt("bin.base64_decode")
|
45
|
+
.into()
|
46
|
+
}
|
47
|
+
|
48
|
+
pub fn bin_hex_encode(&self) -> Self {
|
49
|
+
self.clone()
|
50
|
+
.inner
|
51
|
+
.map(
|
52
|
+
move |s| s.binary().map(|s| Some(s.hex_encode().into_series())),
|
53
|
+
GetOutput::same_type(),
|
54
|
+
)
|
55
|
+
.with_fmt("bin.hex_encode")
|
56
|
+
.into()
|
57
|
+
}
|
58
|
+
|
59
|
+
pub fn bin_base64_encode(&self) -> Self {
|
60
|
+
self.clone()
|
61
|
+
.inner
|
62
|
+
.map(
|
63
|
+
move |s| s.binary().map(|s| Some(s.base64_encode().into_series())),
|
64
|
+
GetOutput::same_type(),
|
65
|
+
)
|
66
|
+
.with_fmt("bin.base64_encode")
|
67
|
+
.into()
|
68
|
+
}
|
69
|
+
}
|
@@ -0,0 +1,223 @@
|
|
1
|
+
use polars::prelude::*;
|
2
|
+
|
3
|
+
use crate::conversion::Wrap;
|
4
|
+
use crate::RbExpr;
|
5
|
+
|
6
|
+
impl RbExpr {
|
7
|
+
pub fn dt_to_string(&self, format: String) -> Self {
|
8
|
+
self.inner.clone().dt().to_string(&format).into()
|
9
|
+
}
|
10
|
+
|
11
|
+
pub fn dt_offset_by(&self, by: String) -> Self {
|
12
|
+
let by = Duration::parse(&by);
|
13
|
+
self.inner.clone().dt().offset_by(by).into()
|
14
|
+
}
|
15
|
+
|
16
|
+
pub fn dt_epoch_seconds(&self) -> Self {
|
17
|
+
self.clone()
|
18
|
+
.inner
|
19
|
+
.map(
|
20
|
+
|s| {
|
21
|
+
s.timestamp(TimeUnit::Milliseconds)
|
22
|
+
.map(|ca| Some((ca / 1000).into_series()))
|
23
|
+
},
|
24
|
+
GetOutput::from_type(DataType::Int64),
|
25
|
+
)
|
26
|
+
.into()
|
27
|
+
}
|
28
|
+
|
29
|
+
pub fn dt_with_time_unit(&self, tu: Wrap<TimeUnit>) -> Self {
|
30
|
+
self.inner.clone().dt().with_time_unit(tu.0).into()
|
31
|
+
}
|
32
|
+
|
33
|
+
pub fn dt_convert_time_zone(&self, tz: TimeZone) -> Self {
|
34
|
+
self.inner.clone().dt().convert_time_zone(tz).into()
|
35
|
+
}
|
36
|
+
|
37
|
+
pub fn dt_cast_time_unit(&self, tu: Wrap<TimeUnit>) -> Self {
|
38
|
+
self.inner.clone().dt().cast_time_unit(tu.0).into()
|
39
|
+
}
|
40
|
+
|
41
|
+
pub fn dt_replace_time_zone(&self, tz: Option<String>, use_earliest: Option<bool>) -> Self {
|
42
|
+
self.inner
|
43
|
+
.clone()
|
44
|
+
.dt()
|
45
|
+
.replace_time_zone(tz, use_earliest)
|
46
|
+
.into()
|
47
|
+
}
|
48
|
+
|
49
|
+
#[allow(deprecated)]
|
50
|
+
pub fn dt_tz_localize(&self, tz: String) -> Self {
|
51
|
+
self.inner.clone().dt().tz_localize(tz).into()
|
52
|
+
}
|
53
|
+
|
54
|
+
pub fn dt_truncate(&self, every: String, offset: String) -> Self {
|
55
|
+
self.inner.clone().dt().truncate(&every, &offset).into()
|
56
|
+
}
|
57
|
+
|
58
|
+
pub fn dt_month_start(&self) -> Self {
|
59
|
+
self.inner.clone().dt().month_start().into()
|
60
|
+
}
|
61
|
+
|
62
|
+
pub fn dt_month_end(&self) -> Self {
|
63
|
+
self.inner.clone().dt().month_end().into()
|
64
|
+
}
|
65
|
+
|
66
|
+
pub fn dt_round(&self, every: String, offset: String) -> Self {
|
67
|
+
self.inner.clone().dt().round(&every, &offset).into()
|
68
|
+
}
|
69
|
+
|
70
|
+
pub fn dt_combine(&self, time: &Self, time_unit: Wrap<TimeUnit>) -> Self {
|
71
|
+
self.inner
|
72
|
+
.clone()
|
73
|
+
.dt()
|
74
|
+
.combine(time.inner.clone(), time_unit.0)
|
75
|
+
.into()
|
76
|
+
}
|
77
|
+
|
78
|
+
pub fn dt_year(&self) -> Self {
|
79
|
+
self.clone().inner.dt().year().into()
|
80
|
+
}
|
81
|
+
|
82
|
+
pub fn dt_is_leap_year(&self) -> Self {
|
83
|
+
self.clone().inner.dt().is_leap_year().into()
|
84
|
+
}
|
85
|
+
|
86
|
+
pub fn dt_iso_year(&self) -> Self {
|
87
|
+
self.clone().inner.dt().iso_year().into()
|
88
|
+
}
|
89
|
+
|
90
|
+
pub fn dt_quarter(&self) -> Self {
|
91
|
+
self.clone().inner.dt().quarter().into()
|
92
|
+
}
|
93
|
+
|
94
|
+
pub fn dt_month(&self) -> Self {
|
95
|
+
self.clone().inner.dt().month().into()
|
96
|
+
}
|
97
|
+
|
98
|
+
pub fn dt_week(&self) -> Self {
|
99
|
+
self.clone().inner.dt().week().into()
|
100
|
+
}
|
101
|
+
|
102
|
+
pub fn dt_weekday(&self) -> Self {
|
103
|
+
self.clone().inner.dt().weekday().into()
|
104
|
+
}
|
105
|
+
|
106
|
+
pub fn dt_day(&self) -> Self {
|
107
|
+
self.clone().inner.dt().day().into()
|
108
|
+
}
|
109
|
+
|
110
|
+
pub fn dt_ordinal_day(&self) -> Self {
|
111
|
+
self.clone().inner.dt().ordinal_day().into()
|
112
|
+
}
|
113
|
+
|
114
|
+
pub fn dt_time(&self) -> Self {
|
115
|
+
self.clone().inner.dt().time().into()
|
116
|
+
}
|
117
|
+
|
118
|
+
pub fn dt_date(&self) -> Self {
|
119
|
+
self.clone().inner.dt().date().into()
|
120
|
+
}
|
121
|
+
|
122
|
+
pub fn dt_datetime(&self) -> Self {
|
123
|
+
self.clone().inner.dt().datetime().into()
|
124
|
+
}
|
125
|
+
|
126
|
+
pub fn dt_hour(&self) -> Self {
|
127
|
+
self.clone().inner.dt().hour().into()
|
128
|
+
}
|
129
|
+
|
130
|
+
pub fn dt_minute(&self) -> Self {
|
131
|
+
self.clone().inner.dt().minute().into()
|
132
|
+
}
|
133
|
+
|
134
|
+
pub fn dt_second(&self) -> Self {
|
135
|
+
self.clone().inner.dt().second().into()
|
136
|
+
}
|
137
|
+
|
138
|
+
pub fn dt_millisecond(&self) -> Self {
|
139
|
+
self.clone().inner.dt().millisecond().into()
|
140
|
+
}
|
141
|
+
|
142
|
+
pub fn dt_microsecond(&self) -> Self {
|
143
|
+
self.clone().inner.dt().microsecond().into()
|
144
|
+
}
|
145
|
+
|
146
|
+
pub fn dt_nanosecond(&self) -> Self {
|
147
|
+
self.clone().inner.dt().nanosecond().into()
|
148
|
+
}
|
149
|
+
|
150
|
+
pub fn dt_timestamp(&self, tu: Wrap<TimeUnit>) -> Self {
|
151
|
+
self.inner.clone().dt().timestamp(tu.0).into()
|
152
|
+
}
|
153
|
+
|
154
|
+
pub fn duration_days(&self) -> Self {
|
155
|
+
self.inner
|
156
|
+
.clone()
|
157
|
+
.map(
|
158
|
+
|s| Ok(Some(s.duration()?.days().into_series())),
|
159
|
+
GetOutput::from_type(DataType::Int64),
|
160
|
+
)
|
161
|
+
.into()
|
162
|
+
}
|
163
|
+
|
164
|
+
pub fn duration_hours(&self) -> Self {
|
165
|
+
self.inner
|
166
|
+
.clone()
|
167
|
+
.map(
|
168
|
+
|s| Ok(Some(s.duration()?.hours().into_series())),
|
169
|
+
GetOutput::from_type(DataType::Int64),
|
170
|
+
)
|
171
|
+
.into()
|
172
|
+
}
|
173
|
+
|
174
|
+
pub fn duration_minutes(&self) -> Self {
|
175
|
+
self.inner
|
176
|
+
.clone()
|
177
|
+
.map(
|
178
|
+
|s| Ok(Some(s.duration()?.minutes().into_series())),
|
179
|
+
GetOutput::from_type(DataType::Int64),
|
180
|
+
)
|
181
|
+
.into()
|
182
|
+
}
|
183
|
+
|
184
|
+
pub fn duration_seconds(&self) -> Self {
|
185
|
+
self.inner
|
186
|
+
.clone()
|
187
|
+
.map(
|
188
|
+
|s| Ok(Some(s.duration()?.seconds().into_series())),
|
189
|
+
GetOutput::from_type(DataType::Int64),
|
190
|
+
)
|
191
|
+
.into()
|
192
|
+
}
|
193
|
+
|
194
|
+
pub fn duration_milliseconds(&self) -> Self {
|
195
|
+
self.inner
|
196
|
+
.clone()
|
197
|
+
.map(
|
198
|
+
|s| Ok(Some(s.duration()?.milliseconds().into_series())),
|
199
|
+
GetOutput::from_type(DataType::Int64),
|
200
|
+
)
|
201
|
+
.into()
|
202
|
+
}
|
203
|
+
|
204
|
+
pub fn duration_microseconds(&self) -> Self {
|
205
|
+
self.inner
|
206
|
+
.clone()
|
207
|
+
.map(
|
208
|
+
|s| Ok(Some(s.duration()?.microseconds().into_series())),
|
209
|
+
GetOutput::from_type(DataType::Int64),
|
210
|
+
)
|
211
|
+
.into()
|
212
|
+
}
|
213
|
+
|
214
|
+
pub fn duration_nanoseconds(&self) -> Self {
|
215
|
+
self.inner
|
216
|
+
.clone()
|
217
|
+
.map(
|
218
|
+
|s| Ok(Some(s.duration()?.nanoseconds().into_series())),
|
219
|
+
GetOutput::from_type(DataType::Int64),
|
220
|
+
)
|
221
|
+
.into()
|
222
|
+
}
|
223
|
+
}
|