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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Cargo.lock +55 -48
  4. data/Cargo.toml +3 -0
  5. data/README.md +12 -0
  6. data/ext/polars/Cargo.toml +22 -11
  7. data/ext/polars/src/batched_csv.rs +4 -4
  8. data/ext/polars/src/catalog/unity.rs +96 -94
  9. data/ext/polars/src/conversion/any_value.rs +26 -30
  10. data/ext/polars/src/conversion/chunked_array.rs +32 -28
  11. data/ext/polars/src/conversion/datetime.rs +11 -0
  12. data/ext/polars/src/conversion/mod.rs +307 -34
  13. data/ext/polars/src/dataframe/construction.rs +4 -3
  14. data/ext/polars/src/dataframe/export.rs +17 -15
  15. data/ext/polars/src/dataframe/general.rs +15 -12
  16. data/ext/polars/src/dataframe/io.rs +1 -2
  17. data/ext/polars/src/dataframe/mod.rs +25 -1
  18. data/ext/polars/src/dataframe/serde.rs +23 -8
  19. data/ext/polars/src/exceptions.rs +8 -4
  20. data/ext/polars/src/expr/array.rs +73 -4
  21. data/ext/polars/src/expr/binary.rs +26 -1
  22. data/ext/polars/src/expr/bitwise.rs +39 -0
  23. data/ext/polars/src/expr/categorical.rs +20 -0
  24. data/ext/polars/src/expr/datatype.rs +24 -1
  25. data/ext/polars/src/expr/datetime.rs +58 -14
  26. data/ext/polars/src/expr/general.rs +87 -15
  27. data/ext/polars/src/expr/list.rs +32 -24
  28. data/ext/polars/src/expr/meta.rs +15 -6
  29. data/ext/polars/src/expr/mod.rs +3 -0
  30. data/ext/polars/src/expr/name.rs +19 -14
  31. data/ext/polars/src/expr/rolling.rs +20 -0
  32. data/ext/polars/src/expr/serde.rs +28 -0
  33. data/ext/polars/src/expr/string.rs +64 -10
  34. data/ext/polars/src/expr/struct.rs +9 -1
  35. data/ext/polars/src/file.rs +15 -9
  36. data/ext/polars/src/functions/business.rs +0 -1
  37. data/ext/polars/src/functions/io.rs +25 -3
  38. data/ext/polars/src/functions/lazy.rs +11 -6
  39. data/ext/polars/src/functions/meta.rs +3 -3
  40. data/ext/polars/src/functions/string_cache.rs +3 -3
  41. data/ext/polars/src/interop/arrow/to_ruby.rs +3 -3
  42. data/ext/polars/src/interop/numo/numo_rs.rs +4 -3
  43. data/ext/polars/src/io/mod.rs +6 -0
  44. data/ext/polars/src/lazyframe/general.rs +59 -9
  45. data/ext/polars/src/lazyframe/mod.rs +16 -1
  46. data/ext/polars/src/lazyframe/optflags.rs +58 -0
  47. data/ext/polars/src/lazyframe/serde.rs +27 -3
  48. data/ext/polars/src/lib.rs +261 -19
  49. data/ext/polars/src/map/dataframe.rs +20 -17
  50. data/ext/polars/src/map/lazy.rs +6 -5
  51. data/ext/polars/src/map/series.rs +8 -7
  52. data/ext/polars/src/on_startup.rs +12 -5
  53. data/ext/polars/src/rb_modules.rs +2 -2
  54. data/ext/polars/src/series/aggregation.rs +85 -28
  55. data/ext/polars/src/series/construction.rs +1 -0
  56. data/ext/polars/src/series/export.rs +37 -33
  57. data/ext/polars/src/series/general.rs +120 -21
  58. data/ext/polars/src/series/mod.rs +29 -4
  59. data/lib/polars/array_expr.rb +382 -3
  60. data/lib/polars/array_name_space.rb +281 -0
  61. data/lib/polars/binary_expr.rb +67 -0
  62. data/lib/polars/binary_name_space.rb +43 -0
  63. data/lib/polars/cat_expr.rb +224 -0
  64. data/lib/polars/cat_name_space.rb +138 -0
  65. data/lib/polars/config.rb +2 -2
  66. data/lib/polars/convert.rb +6 -6
  67. data/lib/polars/data_frame.rb +794 -27
  68. data/lib/polars/data_type_expr.rb +52 -0
  69. data/lib/polars/data_types.rb +26 -5
  70. data/lib/polars/date_time_expr.rb +252 -1
  71. data/lib/polars/date_time_name_space.rb +299 -0
  72. data/lib/polars/expr.rb +1248 -206
  73. data/lib/polars/functions/business.rb +95 -0
  74. data/lib/polars/functions/datatype.rb +21 -0
  75. data/lib/polars/functions/lazy.rb +14 -1
  76. data/lib/polars/io/csv.rb +1 -1
  77. data/lib/polars/io/iceberg.rb +27 -0
  78. data/lib/polars/io/json.rb +4 -4
  79. data/lib/polars/io/ndjson.rb +4 -4
  80. data/lib/polars/io/parquet.rb +32 -7
  81. data/lib/polars/io/scan_options.rb +4 -1
  82. data/lib/polars/lazy_frame.rb +1028 -28
  83. data/lib/polars/list_expr.rb +217 -17
  84. data/lib/polars/list_name_space.rb +231 -22
  85. data/lib/polars/meta_expr.rb +89 -0
  86. data/lib/polars/name_expr.rb +36 -0
  87. data/lib/polars/query_opt_flags.rb +50 -0
  88. data/lib/polars/scan_cast_options.rb +20 -1
  89. data/lib/polars/schema.rb +79 -3
  90. data/lib/polars/selector.rb +72 -0
  91. data/lib/polars/selectors.rb +3 -3
  92. data/lib/polars/series.rb +1053 -54
  93. data/lib/polars/string_expr.rb +436 -32
  94. data/lib/polars/string_name_space.rb +736 -50
  95. data/lib/polars/struct_expr.rb +103 -0
  96. data/lib/polars/struct_name_space.rb +19 -1
  97. data/lib/polars/utils/serde.rb +17 -0
  98. data/lib/polars/utils/various.rb +22 -1
  99. data/lib/polars/utils.rb +5 -1
  100. data/lib/polars/version.rb +1 -1
  101. data/lib/polars.rb +6 -0
  102. metadata +11 -1
@@ -4,10 +4,14 @@ mod general;
4
4
  mod io;
5
5
  mod serde;
6
6
 
7
+ use magnus::{DataTypeFunctions, TypedData, gc};
7
8
  use polars::prelude::*;
8
9
  use std::cell::RefCell;
9
10
 
10
- #[magnus::wrap(class = "Polars::RbDataFrame")]
11
+ use crate::series::mark_series;
12
+
13
+ #[derive(TypedData)]
14
+ #[magnus(class = "Polars::RbDataFrame", mark)]
11
15
  pub struct RbDataFrame {
12
16
  pub df: RefCell<DataFrame>,
13
17
  }
@@ -25,3 +29,23 @@ impl RbDataFrame {
25
29
  }
26
30
  }
27
31
  }
32
+
33
+ impl DataTypeFunctions for RbDataFrame {
34
+ fn mark(&self, marker: &gc::Marker) {
35
+ // this is really, really not ideal, as objects will not be marked if unable to borrow
36
+ // currently, this should only happen for write_* methods,
37
+ // which should refuse to write Object datatype, and therefore be safe,
38
+ // since GC will not have a chance to run
39
+ if let Ok(df) = self.df.try_borrow() {
40
+ for column in df.get_columns() {
41
+ if let DataType::Object(_) = column.dtype() {
42
+ match column {
43
+ Column::Series(s) => mark_series(marker, s),
44
+ Column::Partitioned(s) => mark_series(marker, s.partitions()),
45
+ Column::Scalar(s) => mark_series(marker, &s.as_single_value_series()),
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
@@ -1,15 +1,30 @@
1
- use crate::exceptions::ComputeError;
1
+ use std::io::{BufReader, BufWriter};
2
+
3
+ use polars::prelude::*;
4
+
2
5
  use crate::file::get_file_like;
3
- use crate::{RbDataFrame, RbResult};
6
+ use crate::utils::to_rb_err;
7
+ use crate::{RbDataFrame, RbPolarsErr, RbResult};
4
8
  use magnus::Value;
5
- use std::io::BufWriter;
6
9
 
7
10
  impl RbDataFrame {
8
- // TODO add to Ruby
9
- pub fn serialize_json(&self, rb_f: Value) -> RbResult<()> {
11
+ pub fn serialize_binary(&self, rb_f: Value) -> RbResult<()> {
10
12
  let file = get_file_like(rb_f, true)?;
11
- let writer = BufWriter::new(file);
12
- serde_json::to_writer(writer, &self.df)
13
- .map_err(|err| ComputeError::new_err(err.to_string()))
13
+ let mut writer = BufWriter::new(file);
14
+
15
+ Ok(self
16
+ .df
17
+ .borrow_mut()
18
+ .serialize_into_writer(&mut writer)
19
+ .map_err(RbPolarsErr::from)?)
20
+ }
21
+
22
+ pub fn deserialize_binary(rb_f: Value) -> RbResult<Self> {
23
+ let file = get_file_like(rb_f, false)?;
24
+ let mut file = BufReader::new(file);
25
+
26
+ DataFrame::deserialize_from_reader(&mut file)
27
+ .map(|v| v.into())
28
+ .map_err(to_rb_err)
14
29
  }
15
30
  }
@@ -1,5 +1,5 @@
1
1
  use crate::rb_modules;
2
- use magnus::{Error, exception};
2
+ use magnus::{Error, Ruby};
3
3
  use std::borrow::Cow;
4
4
 
5
5
  macro_rules! create_exception {
@@ -17,8 +17,12 @@ macro_rules! create_exception {
17
17
  };
18
18
  }
19
19
 
20
- create_exception!(RbTypeError, exception::type_error());
21
- create_exception!(RbValueError, exception::arg_error());
22
- create_exception!(RbOverflowError, exception::range_error());
20
+ create_exception!(RbTypeError, Ruby::get().unwrap().exception_type_error());
21
+ create_exception!(RbValueError, Ruby::get().unwrap().exception_arg_error());
22
+ create_exception!(
23
+ RbOverflowError,
24
+ Ruby::get().unwrap().exception_range_error()
25
+ );
26
+ create_exception!(RbIndexError, Ruby::get().unwrap().exception_index_error());
23
27
  create_exception!(ComputeError, rb_modules::compute_error());
24
28
  create_exception!(InvalidOperationError, rb_modules::invalid_operation_error());
@@ -1,20 +1,41 @@
1
+ use magnus::Value;
1
2
  use polars::prelude::*;
2
3
 
3
- use crate::RbExpr;
4
+ use crate::{RbExpr, RbPolarsErr, RbResult};
4
5
 
5
6
  impl RbExpr {
6
- pub fn array_max(&self) -> Self {
7
+ pub fn arr_len(&self) -> Self {
8
+ self.inner.clone().arr().len().into()
9
+ }
10
+
11
+ pub fn arr_max(&self) -> Self {
7
12
  self.inner.clone().arr().max().into()
8
13
  }
9
14
 
10
- pub fn array_min(&self) -> Self {
15
+ pub fn arr_min(&self) -> Self {
11
16
  self.inner.clone().arr().min().into()
12
17
  }
13
18
 
14
- pub fn array_sum(&self) -> Self {
19
+ pub fn arr_sum(&self) -> Self {
15
20
  self.inner.clone().arr().sum().into()
16
21
  }
17
22
 
23
+ pub fn arr_std(&self, ddof: u8) -> Self {
24
+ self.inner.clone().arr().std(ddof).into()
25
+ }
26
+
27
+ pub fn arr_var(&self, ddof: u8) -> Self {
28
+ self.inner.clone().arr().var(ddof).into()
29
+ }
30
+
31
+ pub fn arr_mean(&self) -> Self {
32
+ self.inner.clone().arr().mean().into()
33
+ }
34
+
35
+ pub fn arr_median(&self) -> Self {
36
+ self.inner.clone().arr().median().into()
37
+ }
38
+
18
39
  pub fn arr_unique(&self, maintain_order: bool) -> Self {
19
40
  if maintain_order {
20
41
  self.inner.clone().arr().unique_stable().into()
@@ -23,6 +44,10 @@ impl RbExpr {
23
44
  }
24
45
  }
25
46
 
47
+ pub fn arr_n_unique(&self) -> Self {
48
+ self.inner.clone().arr().n_unique().into()
49
+ }
50
+
26
51
  pub fn arr_to_list(&self) -> Self {
27
52
  self.inner.clone().arr().to_list().into()
28
53
  }
@@ -90,4 +115,48 @@ impl RbExpr {
90
115
  .count_matches(expr.inner.clone())
91
116
  .into()
92
117
  }
118
+
119
+ pub fn arr_to_struct(&self, name_gen: Option<Value>) -> Self {
120
+ if name_gen.is_some() {
121
+ todo!();
122
+ }
123
+ self.inner.clone().arr().to_struct(None).into()
124
+ }
125
+
126
+ pub fn arr_slice(
127
+ &self,
128
+ offset: &RbExpr,
129
+ length: Option<&RbExpr>,
130
+ as_array: bool,
131
+ ) -> RbResult<Self> {
132
+ let length = match length {
133
+ Some(i) => i.inner.clone(),
134
+ None => lit(i64::MAX),
135
+ };
136
+ Ok(self
137
+ .inner
138
+ .clone()
139
+ .arr()
140
+ .slice(offset.inner.clone(), length, as_array)
141
+ .map_err(RbPolarsErr::from)?
142
+ .into())
143
+ }
144
+
145
+ pub fn arr_tail(&self, n: &RbExpr, as_array: bool) -> RbResult<Self> {
146
+ Ok(self
147
+ .inner
148
+ .clone()
149
+ .arr()
150
+ .tail(n.inner.clone(), as_array)
151
+ .map_err(RbPolarsErr::from)?
152
+ .into())
153
+ }
154
+
155
+ pub fn arr_shift(&self, n: &RbExpr) -> Self {
156
+ self.inner.clone().arr().shift(n.inner.clone()).into()
157
+ }
158
+
159
+ pub fn arr_explode(&self) -> Self {
160
+ self.inner.clone().arr().explode().into()
161
+ }
93
162
  }
@@ -1,4 +1,5 @@
1
- use crate::RbExpr;
1
+ use crate::expr::datatype::RbDataTypeExpr;
2
+ use crate::{RbExpr, RbResult};
2
3
 
3
4
  impl RbExpr {
4
5
  pub fn bin_contains(&self, lit: &RbExpr) -> Self {
@@ -40,4 +41,28 @@ impl RbExpr {
40
41
  pub fn bin_base64_encode(&self) -> Self {
41
42
  self.inner.clone().binary().base64_encode().into()
42
43
  }
44
+
45
+ pub fn bin_reinterpret(&self, dtype: &RbDataTypeExpr, kind: String) -> RbResult<Self> {
46
+ use crate::RbValueError;
47
+
48
+ let is_little_endian = match kind.to_lowercase().as_str() {
49
+ "little" => true,
50
+ "big" => false,
51
+ _ => {
52
+ return Err(RbValueError::new_err(format!(
53
+ "Invalid endianness: {kind}. Valid values are \"little\" or \"big\"."
54
+ )));
55
+ }
56
+ };
57
+ Ok(self
58
+ .inner
59
+ .clone()
60
+ .binary()
61
+ .reinterpret(dtype.inner.clone(), is_little_endian)
62
+ .into())
63
+ }
64
+
65
+ pub fn bin_size_bytes(&self) -> Self {
66
+ self.inner.clone().binary().size_bytes().into()
67
+ }
43
68
  }
@@ -0,0 +1,39 @@
1
+ use crate::RbExpr;
2
+
3
+ impl RbExpr {
4
+ pub fn bitwise_count_ones(&self) -> Self {
5
+ self.inner.clone().bitwise_count_ones().into()
6
+ }
7
+
8
+ pub fn bitwise_count_zeros(&self) -> Self {
9
+ self.inner.clone().bitwise_count_zeros().into()
10
+ }
11
+
12
+ pub fn bitwise_leading_ones(&self) -> Self {
13
+ self.inner.clone().bitwise_leading_ones().into()
14
+ }
15
+
16
+ pub fn bitwise_leading_zeros(&self) -> Self {
17
+ self.inner.clone().bitwise_leading_zeros().into()
18
+ }
19
+
20
+ pub fn bitwise_trailing_ones(&self) -> Self {
21
+ self.inner.clone().bitwise_trailing_ones().into()
22
+ }
23
+
24
+ pub fn bitwise_trailing_zeros(&self) -> Self {
25
+ self.inner.clone().bitwise_trailing_zeros().into()
26
+ }
27
+
28
+ pub fn bitwise_and(&self) -> Self {
29
+ self.inner.clone().bitwise_and().into()
30
+ }
31
+
32
+ pub fn bitwise_or(&self) -> Self {
33
+ self.inner.clone().bitwise_or().into()
34
+ }
35
+
36
+ pub fn bitwise_xor(&self) -> Self {
37
+ self.inner.clone().bitwise_xor().into()
38
+ }
39
+ }
@@ -4,4 +4,24 @@ impl RbExpr {
4
4
  pub fn cat_get_categories(&self) -> Self {
5
5
  self.inner.clone().cat().get_categories().into()
6
6
  }
7
+
8
+ pub fn cat_len_bytes(&self) -> Self {
9
+ self.inner.clone().cat().len_bytes().into()
10
+ }
11
+
12
+ pub fn cat_len_chars(&self) -> Self {
13
+ self.inner.clone().cat().len_chars().into()
14
+ }
15
+
16
+ pub fn cat_starts_with(&self, prefix: String) -> Self {
17
+ self.inner.clone().cat().starts_with(prefix).into()
18
+ }
19
+
20
+ pub fn cat_ends_with(&self, suffix: String) -> Self {
21
+ self.inner.clone().cat().ends_with(suffix).into()
22
+ }
23
+
24
+ pub fn cat_slice(&self, offset: i64, length: Option<usize>) -> Self {
25
+ self.inner.clone().cat().slice(offset, length).into()
26
+ }
7
27
  }
@@ -1,4 +1,8 @@
1
- use polars::prelude::DataTypeExpr;
1
+ use magnus::{IntoValue, Ruby, Value};
2
+ use polars::prelude::{DataType, DataTypeExpr, Schema};
3
+
4
+ use crate::prelude::Wrap;
5
+ use crate::{RbExpr, RbPolarsErr, RbResult};
2
6
 
3
7
  #[magnus::wrap(class = "Polars::RbDataTypeExpr")]
4
8
  #[repr(transparent)]
@@ -12,3 +16,22 @@ impl From<DataTypeExpr> for RbDataTypeExpr {
12
16
  RbDataTypeExpr { inner: expr }
13
17
  }
14
18
  }
19
+
20
+ impl RbDataTypeExpr {
21
+ pub fn from_dtype(datatype: Wrap<DataType>) -> Self {
22
+ DataTypeExpr::Literal(datatype.0).into()
23
+ }
24
+
25
+ pub fn of_expr(expr: &RbExpr) -> Self {
26
+ DataTypeExpr::OfExpr(Box::new(expr.inner.clone())).into()
27
+ }
28
+
29
+ pub fn collect_dtype(ruby: &Ruby, rb_self: &Self, schema: Wrap<Schema>) -> RbResult<Value> {
30
+ let dtype = rb_self
31
+ .clone()
32
+ .inner
33
+ .into_datatype(&schema.0)
34
+ .map_err(RbPolarsErr::from)?;
35
+ Ok(Wrap(dtype).into_value_with(ruby))
36
+ }
37
+ }
@@ -4,6 +4,20 @@ use crate::conversion::Wrap;
4
4
  use crate::{RbExpr, RbPolarsErr, RbResult};
5
5
 
6
6
  impl RbExpr {
7
+ pub fn dt_add_business_days(
8
+ &self,
9
+ n: &RbExpr,
10
+ week_mask: [bool; 7],
11
+ holidays: Vec<i32>,
12
+ roll: Wrap<Roll>,
13
+ ) -> Self {
14
+ self.inner
15
+ .clone()
16
+ .dt()
17
+ .add_business_days(n.inner.clone(), week_mask, holidays, roll.0)
18
+ .into()
19
+ }
20
+
7
21
  pub fn dt_to_string(&self, format: String) -> Self {
8
22
  self.inner.clone().dt().to_string(&format).into()
9
23
  }
@@ -12,20 +26,6 @@ impl RbExpr {
12
26
  self.inner.clone().dt().offset_by(by.inner.clone()).into()
13
27
  }
14
28
 
15
- pub fn dt_epoch_seconds(&self) -> Self {
16
- self.inner
17
- .clone()
18
- .map(
19
- |s| {
20
- s.take_materialized_series()
21
- .timestamp(TimeUnit::Milliseconds)
22
- .map(|ca| Some((ca / 1000).into_column()))
23
- },
24
- GetOutput::from_type(DataType::Int64),
25
- )
26
- .into()
27
- }
28
-
29
29
  pub fn dt_with_time_unit(&self, tu: Wrap<TimeUnit>) -> Self {
30
30
  self.inner.clone().dt().with_time_unit(tu.0).into()
31
31
  }
@@ -90,6 +90,34 @@ impl RbExpr {
90
90
  self.inner.clone().dt().round(every.inner.clone()).into()
91
91
  }
92
92
 
93
+ #[allow(clippy::too_many_arguments)]
94
+ pub fn dt_replace(
95
+ &self,
96
+ year: &Self,
97
+ month: &Self,
98
+ day: &Self,
99
+ hour: &Self,
100
+ minute: &Self,
101
+ second: &Self,
102
+ microsecond: &Self,
103
+ ambiguous: &Self,
104
+ ) -> Self {
105
+ self.inner
106
+ .clone()
107
+ .dt()
108
+ .replace(
109
+ year.inner.clone(),
110
+ month.inner.clone(),
111
+ day.inner.clone(),
112
+ hour.inner.clone(),
113
+ minute.inner.clone(),
114
+ second.inner.clone(),
115
+ microsecond.inner.clone(),
116
+ ambiguous.inner.clone(),
117
+ )
118
+ .into()
119
+ }
120
+
93
121
  pub fn dt_combine(&self, time: &Self, time_unit: Wrap<TimeUnit>) -> Self {
94
122
  self.inner
95
123
  .clone()
@@ -98,10 +126,26 @@ impl RbExpr {
98
126
  .into()
99
127
  }
100
128
 
129
+ pub fn dt_millennium(&self) -> Self {
130
+ self.inner.clone().dt().millennium().into()
131
+ }
132
+
133
+ pub fn dt_century(&self) -> Self {
134
+ self.inner.clone().dt().century().into()
135
+ }
136
+
101
137
  pub fn dt_year(&self) -> Self {
102
138
  self.clone().inner.dt().year().into()
103
139
  }
104
140
 
141
+ pub fn dt_is_business_day(&self, week_mask: [bool; 7], holidays: Vec<i32>) -> Self {
142
+ self.inner
143
+ .clone()
144
+ .dt()
145
+ .is_business_day(week_mask, holidays)
146
+ .into()
147
+ }
148
+
105
149
  pub fn dt_is_leap_year(&self) -> Self {
106
150
  self.clone().inner.dt().is_leap_year().into()
107
151
  }
@@ -323,6 +323,10 @@ impl RbExpr {
323
323
  self.inner.clone().arg_min().into()
324
324
  }
325
325
 
326
+ pub fn index_of(&self, element: &Self) -> Self {
327
+ self.inner.clone().index_of(element.inner.clone()).into()
328
+ }
329
+
326
330
  pub fn search_sorted(
327
331
  &self,
328
332
  element: &Self,
@@ -429,6 +433,13 @@ impl RbExpr {
429
433
  .into()
430
434
  }
431
435
 
436
+ pub fn is_close(&self, other: &Self, abs_tol: f64, rel_tol: f64, nans_equal: bool) -> Self {
437
+ self.inner
438
+ .clone()
439
+ .is_close(other.inner.clone(), abs_tol, rel_tol, nans_equal)
440
+ .into()
441
+ }
442
+
432
443
  pub fn approx_n_unique(&self) -> Self {
433
444
  self.inner.clone().approx_n_unique().into()
434
445
  }
@@ -472,16 +483,17 @@ impl RbExpr {
472
483
  }
473
484
 
474
485
  pub fn rechunk(&self) -> Self {
475
- self.inner
476
- .clone()
477
- .map(|s| Ok(Some(s.rechunk())), GetOutput::same_type())
478
- .into()
486
+ self.inner.clone().rechunk().into()
479
487
  }
480
488
 
481
489
  pub fn round(&self, decimals: u32, mode: Wrap<RoundMode>) -> Self {
482
490
  self.inner.clone().round(decimals, mode.0).into()
483
491
  }
484
492
 
493
+ pub fn round_sig_figs(&self, digits: i32) -> Self {
494
+ self.clone().inner.round_sig_figs(digits).into()
495
+ }
496
+
485
497
  pub fn floor(&self) -> Self {
486
498
  self.inner.clone().floor().into()
487
499
  }
@@ -517,6 +529,10 @@ impl RbExpr {
517
529
  self.inner.clone().tan().into()
518
530
  }
519
531
 
532
+ pub fn cot(&self) -> Self {
533
+ self.inner.clone().cot().into()
534
+ }
535
+
520
536
  pub fn arcsin(&self) -> Self {
521
537
  self.inner.clone().arcsin().into()
522
538
  }
@@ -553,6 +569,14 @@ impl RbExpr {
553
569
  self.inner.clone().arctanh().into()
554
570
  }
555
571
 
572
+ pub fn degrees(&self) -> Self {
573
+ self.inner.clone().degrees().into()
574
+ }
575
+
576
+ pub fn radians(&self) -> Self {
577
+ self.inner.clone().radians().into()
578
+ }
579
+
556
580
  pub fn sign(&self) -> Self {
557
581
  self.inner.clone().sign().into()
558
582
  }
@@ -566,18 +590,35 @@ impl RbExpr {
566
590
  Ok(self.inner.clone().over(partition_by).into())
567
591
  }
568
592
 
569
- pub fn _and(&self, expr: &Self) -> Self {
570
- self.inner.clone().and(expr.inner.clone()).into()
593
+ pub fn rolling(
594
+ &self,
595
+ index_column: String,
596
+ period: String,
597
+ offset: String,
598
+ closed: Wrap<ClosedWindow>,
599
+ ) -> RbResult<Self> {
600
+ let options = RollingGroupOptions {
601
+ index_column: index_column.into(),
602
+ period: Duration::try_parse(&period).map_err(RbPolarsErr::from)?,
603
+ offset: Duration::try_parse(&offset).map_err(RbPolarsErr::from)?,
604
+ closed_window: closed.0,
605
+ };
606
+
607
+ Ok(self.inner.clone().rolling(options).into())
571
608
  }
572
609
 
573
- pub fn _xor(&self, expr: &Self) -> Self {
574
- self.inner.clone().xor(expr.inner.clone()).into()
610
+ pub fn and_(&self, expr: &Self) -> Self {
611
+ self.inner.clone().and(expr.inner.clone()).into()
575
612
  }
576
613
 
577
- pub fn _or(&self, expr: &Self) -> Self {
614
+ pub fn or_(&self, expr: &Self) -> Self {
578
615
  self.inner.clone().or(expr.inner.clone()).into()
579
616
  }
580
617
 
618
+ pub fn xor_(&self, expr: &Self) -> Self {
619
+ self.inner.clone().xor(expr.inner.clone()).into()
620
+ }
621
+
581
622
  pub fn is_in(&self, expr: &Self, nulls_equal: bool) -> Self {
582
623
  self.inner
583
624
  .clone()
@@ -593,6 +634,14 @@ impl RbExpr {
593
634
  self.inner.clone().pow(exponent.inner.clone()).into()
594
635
  }
595
636
 
637
+ pub fn sqrt(&self) -> Self {
638
+ self.inner.clone().sqrt().into()
639
+ }
640
+
641
+ pub fn cbrt(&self) -> Self {
642
+ self.inner.clone().cbrt().into()
643
+ }
644
+
596
645
  pub fn cum_sum(&self, reverse: bool) -> Self {
597
646
  self.inner.clone().cum_sum(reverse).into()
598
647
  }
@@ -613,10 +662,6 @@ impl RbExpr {
613
662
  self.inner.clone().product().into()
614
663
  }
615
664
 
616
- pub fn shrink_dtype(&self) -> Self {
617
- self.inner.clone().shrink_dtype().into()
618
- }
619
-
620
665
  pub fn map_batches(
621
666
  &self,
622
667
  lambda: Value,
@@ -756,6 +801,15 @@ impl RbExpr {
756
801
  self.inner.clone().ewm_mean(options).into()
757
802
  }
758
803
 
804
+ pub fn ewm_mean_by(&self, times: &RbExpr, half_life: String) -> RbResult<Self> {
805
+ let half_life = Duration::try_parse(&half_life).map_err(RbPolarsErr::from)?;
806
+ Ok(self
807
+ .inner
808
+ .clone()
809
+ .ewm_mean_by(times.inner.clone(), half_life)
810
+ .into())
811
+ }
812
+
759
813
  pub fn ewm_std(
760
814
  &self,
761
815
  alpha: f64,
@@ -807,8 +861,12 @@ impl RbExpr {
807
861
  self.inner.clone().all(drop_nulls).into()
808
862
  }
809
863
 
810
- pub fn log(&self, base: f64) -> Self {
811
- self.inner.clone().log(base).into()
864
+ pub fn log(&self, base: &RbExpr) -> Self {
865
+ self.inner.clone().log(base.inner.clone()).into()
866
+ }
867
+
868
+ pub fn log1p(&self) -> Self {
869
+ self.inner.clone().log1p().into()
812
870
  }
813
871
 
814
872
  pub fn exp(&self) -> Self {
@@ -857,6 +915,20 @@ impl RbExpr {
857
915
  .into()
858
916
  }
859
917
 
918
+ pub fn hist(
919
+ &self,
920
+ bins: Option<&RbExpr>,
921
+ bin_count: Option<usize>,
922
+ include_category: bool,
923
+ include_breakpoint: bool,
924
+ ) -> Self {
925
+ let bins = bins.map(|e| e.inner.clone());
926
+ self.inner
927
+ .clone()
928
+ .hist(bins, bin_count, include_category, include_breakpoint)
929
+ .into()
930
+ }
931
+
860
932
  #[allow(clippy::wrong_self_convention)]
861
933
  pub fn into_selector(&self) -> RbResult<RbSelector> {
862
934
  Ok(self