polars-df 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Cargo.toml ADDED
@@ -0,0 +1,5 @@
1
+ [workspace]
2
+ members = ["ext/polars"]
3
+
4
+ [profile.release]
5
+ strip = true
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "polars"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  authors = ["Andrew Kane <andrew@ankane.org>"]
5
5
  edition = "2021"
6
6
  publish = false
@@ -15,21 +15,51 @@ serde_json = "1"
15
15
  [dependencies.polars]
16
16
  version = "0.25.1"
17
17
  features = [
18
+ "abs",
18
19
  "arange",
20
+ "concat_str",
19
21
  "csv-file",
20
22
  "cum_agg",
23
+ "cumulative_eval",
24
+ "date_offset",
21
25
  "diagonal_concat",
26
+ "diff",
27
+ "dot_product",
22
28
  "dtype-full",
29
+ "dynamic_groupby",
30
+ "ewma",
23
31
  "fmt",
24
32
  "horizontal_concat",
25
33
  "interpolate",
26
34
  "ipc",
35
+ "is_first",
36
+ "is_in",
27
37
  "json",
28
38
  "lazy",
29
39
  "lazy_regex",
40
+ "list_eval",
41
+ "log",
42
+ "meta",
43
+ "mode",
44
+ "moment",
30
45
  "parquet",
46
+ "partition_by",
47
+ "pct_change",
48
+ "product",
49
+ "random",
50
+ "rank",
51
+ "repeat_by",
52
+ "rolling_window",
53
+ "round_series",
54
+ "search_sorted",
31
55
  "semi_anti_join",
32
56
  "serde-lazy",
57
+ "sign",
58
+ "string_justify",
33
59
  "strings",
60
+ "timezones",
61
+ "to_dummies",
62
+ "top_k",
34
63
  "trigonometry",
64
+ "unique_counts",
35
65
  ]
@@ -1,27 +1,245 @@
1
- use magnus::{Value, QNIL};
1
+ use magnus::{TryConvert, Value, QNIL};
2
2
  use polars::chunked_array::ops::{FillNullLimit, FillNullStrategy};
3
3
  use polars::datatypes::AnyValue;
4
4
  use polars::frame::DataFrame;
5
5
  use polars::prelude::*;
6
+ use polars::series::ops::NullBehavior;
6
7
 
7
- use crate::{RbDataFrame, RbResult, RbValueError};
8
-
9
- pub fn wrap(val: AnyValue) -> Value {
10
- match val {
11
- AnyValue::UInt8(v) => Value::from(v),
12
- AnyValue::UInt16(v) => Value::from(v),
13
- AnyValue::UInt32(v) => Value::from(v),
14
- AnyValue::UInt64(v) => Value::from(v),
15
- AnyValue::Int8(v) => Value::from(v),
16
- AnyValue::Int16(v) => Value::from(v),
17
- AnyValue::Int32(v) => Value::from(v),
18
- AnyValue::Int64(v) => Value::from(v),
19
- AnyValue::Float32(v) => Value::from(v),
20
- AnyValue::Float64(v) => Value::from(v),
21
- AnyValue::Null => *QNIL,
22
- AnyValue::Boolean(v) => Value::from(v),
23
- AnyValue::Utf8(v) => Value::from(v),
24
- _ => todo!(),
8
+ use crate::{RbDataFrame, RbPolarsErr, RbResult, RbValueError};
9
+
10
+ pub struct Wrap<T>(pub T);
11
+
12
+ impl<T> From<T> for Wrap<T> {
13
+ fn from(t: T) -> Self {
14
+ Wrap(t)
15
+ }
16
+ }
17
+
18
+ pub fn get_df(obj: Value) -> RbResult<DataFrame> {
19
+ let rbdf = obj.funcall::<_, _, &RbDataFrame>("_df", ())?;
20
+ Ok(rbdf.df.borrow().clone())
21
+ }
22
+
23
+ impl Into<Value> for Wrap<AnyValue<'_>> {
24
+ fn into(self) -> Value {
25
+ match self.0 {
26
+ AnyValue::UInt8(v) => Value::from(v),
27
+ AnyValue::UInt16(v) => Value::from(v),
28
+ AnyValue::UInt32(v) => Value::from(v),
29
+ AnyValue::UInt64(v) => Value::from(v),
30
+ AnyValue::Int8(v) => Value::from(v),
31
+ AnyValue::Int16(v) => Value::from(v),
32
+ AnyValue::Int32(v) => Value::from(v),
33
+ AnyValue::Int64(v) => Value::from(v),
34
+ AnyValue::Float32(v) => Value::from(v),
35
+ AnyValue::Float64(v) => Value::from(v),
36
+ AnyValue::Null => *QNIL,
37
+ AnyValue::Boolean(v) => Value::from(v),
38
+ AnyValue::Utf8(v) => Value::from(v),
39
+ _ => todo!(),
40
+ }
41
+ }
42
+ }
43
+
44
+ impl TryConvert for Wrap<DataType> {
45
+ fn try_convert(ob: Value) -> RbResult<Self> {
46
+ let dtype = match ob.try_convert::<String>()?.as_str() {
47
+ "u8" => DataType::UInt8,
48
+ "u16" => DataType::UInt16,
49
+ "u32" => DataType::UInt32,
50
+ "u64" => DataType::UInt64,
51
+ "i8" => DataType::Int8,
52
+ "i16" => DataType::Int16,
53
+ "i32" => DataType::Int32,
54
+ "i64" => DataType::Int64,
55
+ "str" => DataType::Utf8,
56
+ "bool" => DataType::Boolean,
57
+ "f32" => DataType::Float32,
58
+ "f64" => DataType::Float64,
59
+ "date" => DataType::Date,
60
+ _ => {
61
+ return Err(RbValueError::new_err(format!(
62
+ "{} is not a supported DataType.",
63
+ ob
64
+ )))
65
+ }
66
+ };
67
+ Ok(Wrap(dtype))
68
+ }
69
+ }
70
+
71
+ impl<'s> TryConvert for Wrap<AnyValue<'s>> {
72
+ fn try_convert(ob: Value) -> RbResult<Self> {
73
+ // TODO improve
74
+ if let Ok(v) = ob.try_convert::<i64>() {
75
+ Ok(AnyValue::Int64(v).into())
76
+ } else if let Ok(v) = ob.try_convert::<f64>() {
77
+ Ok(AnyValue::Float64(v).into())
78
+ } else {
79
+ Err(RbPolarsErr::other(format!(
80
+ "object type not supported {:?}",
81
+ ob
82
+ )))
83
+ }
84
+ }
85
+ }
86
+
87
+ impl TryConvert for Wrap<CategoricalOrdering> {
88
+ fn try_convert(ob: Value) -> RbResult<Self> {
89
+ let parsed = match ob.try_convert::<String>()?.as_str() {
90
+ "physical" => CategoricalOrdering::Physical,
91
+ "lexical" => CategoricalOrdering::Lexical,
92
+ v => {
93
+ return Err(RbValueError::new_err(format!(
94
+ "ordering must be one of {{'physical', 'lexical'}}, got {}",
95
+ v
96
+ )))
97
+ }
98
+ };
99
+ Ok(Wrap(parsed))
100
+ }
101
+ }
102
+
103
+ impl TryConvert for Wrap<ClosedWindow> {
104
+ fn try_convert(ob: Value) -> RbResult<Self> {
105
+ let parsed = match ob.try_convert::<String>()?.as_str() {
106
+ "left" => ClosedWindow::Left,
107
+ "right" => ClosedWindow::Right,
108
+ "both" => ClosedWindow::Both,
109
+ "none" => ClosedWindow::None,
110
+ v => {
111
+ return Err(RbValueError::new_err(format!(
112
+ "closed must be one of {{'left', 'right', 'both', 'none'}}, got {}",
113
+ v
114
+ )))
115
+ }
116
+ };
117
+ Ok(Wrap(parsed))
118
+ }
119
+ }
120
+
121
+ impl TryConvert for Wrap<JoinType> {
122
+ fn try_convert(ob: Value) -> RbResult<Self> {
123
+ let parsed = match ob.try_convert::<String>()?.as_str() {
124
+ "inner" => JoinType::Inner,
125
+ "left" => JoinType::Left,
126
+ "outer" => JoinType::Outer,
127
+ "semi" => JoinType::Semi,
128
+ "anti" => JoinType::Anti,
129
+ // #[cfg(feature = "cross_join")]
130
+ // "cross" => JoinType::Cross,
131
+ v => {
132
+ return Err(RbValueError::new_err(format!(
133
+ "how must be one of {{'inner', 'left', 'outer', 'semi', 'anti', 'cross'}}, got {}",
134
+ v
135
+ )))
136
+ }
137
+ };
138
+ Ok(Wrap(parsed))
139
+ }
140
+ }
141
+
142
+ impl TryConvert for Wrap<NullBehavior> {
143
+ fn try_convert(ob: Value) -> RbResult<Self> {
144
+ let parsed = match ob.try_convert::<String>()?.as_str() {
145
+ "drop" => NullBehavior::Drop,
146
+ "ignore" => NullBehavior::Ignore,
147
+ v => {
148
+ return Err(RbValueError::new_err(format!(
149
+ "null behavior must be one of {{'drop', 'ignore'}}, got {}",
150
+ v
151
+ )))
152
+ }
153
+ };
154
+ Ok(Wrap(parsed))
155
+ }
156
+ }
157
+
158
+ impl TryConvert for Wrap<NullStrategy> {
159
+ fn try_convert(ob: Value) -> RbResult<Self> {
160
+ let parsed = match ob.try_convert::<String>()?.as_str() {
161
+ "ignore" => NullStrategy::Ignore,
162
+ "propagate" => NullStrategy::Propagate,
163
+ v => {
164
+ return Err(RbValueError::new_err(format!(
165
+ "null strategy must be one of {{'ignore', 'propagate'}}, got {}",
166
+ v
167
+ )))
168
+ }
169
+ };
170
+ Ok(Wrap(parsed))
171
+ }
172
+ }
173
+
174
+ impl TryConvert for Wrap<QuantileInterpolOptions> {
175
+ fn try_convert(ob: Value) -> RbResult<Self> {
176
+ let parsed = match ob.try_convert::<String>()?.as_str() {
177
+ "lower" => QuantileInterpolOptions::Lower,
178
+ "higher" => QuantileInterpolOptions::Higher,
179
+ "nearest" => QuantileInterpolOptions::Nearest,
180
+ "linear" => QuantileInterpolOptions::Linear,
181
+ "midpoint" => QuantileInterpolOptions::Midpoint,
182
+ v => {
183
+ return Err(RbValueError::new_err(format!(
184
+ "interpolation must be one of {{'lower', 'higher', 'nearest', 'linear', 'midpoint'}}, got {}",
185
+ v
186
+ )))
187
+ }
188
+ };
189
+ Ok(Wrap(parsed))
190
+ }
191
+ }
192
+
193
+ impl TryConvert for Wrap<RankMethod> {
194
+ fn try_convert(ob: Value) -> RbResult<Self> {
195
+ let parsed = match ob.try_convert::<String>()?.as_str() {
196
+ "min" => RankMethod::Min,
197
+ "max" => RankMethod::Max,
198
+ "average" => RankMethod::Average,
199
+ "dense" => RankMethod::Dense,
200
+ "ordinal" => RankMethod::Ordinal,
201
+ "random" => RankMethod::Random,
202
+ v => {
203
+ return Err(RbValueError::new_err(format!(
204
+ "method must be one of {{'min', 'max', 'average', 'dense', 'ordinal', 'random'}}, got {}",
205
+ v
206
+ )))
207
+ }
208
+ };
209
+ Ok(Wrap(parsed))
210
+ }
211
+ }
212
+
213
+ impl TryConvert for Wrap<TimeUnit> {
214
+ fn try_convert(ob: Value) -> RbResult<Self> {
215
+ let parsed = match ob.try_convert::<String>()?.as_str() {
216
+ "ns" => TimeUnit::Nanoseconds,
217
+ "us" => TimeUnit::Microseconds,
218
+ "ms" => TimeUnit::Milliseconds,
219
+ v => {
220
+ return Err(RbValueError::new_err(format!(
221
+ "time unit must be one of {{'ns', 'us', 'ms'}}, got {}",
222
+ v
223
+ )))
224
+ }
225
+ };
226
+ Ok(Wrap(parsed))
227
+ }
228
+ }
229
+
230
+ impl TryConvert for Wrap<UniqueKeepStrategy> {
231
+ fn try_convert(ob: Value) -> RbResult<Self> {
232
+ let parsed = match ob.try_convert::<String>()?.as_str() {
233
+ "first" => UniqueKeepStrategy::First,
234
+ "last" => UniqueKeepStrategy::Last,
235
+ v => {
236
+ return Err(RbValueError::new_err(format!(
237
+ "keep must be one of {{'first', 'last'}}, got {}",
238
+ v
239
+ )))
240
+ }
241
+ };
242
+ Ok(Wrap(parsed))
25
243
  }
26
244
  }
27
245
 
@@ -47,30 +265,6 @@ pub fn parse_fill_null_strategy(
47
265
  Ok(parsed)
48
266
  }
49
267
 
50
- pub fn wrap_join_type(ob: &str) -> RbResult<JoinType> {
51
- let parsed = match ob {
52
- "inner" => JoinType::Inner,
53
- "left" => JoinType::Left,
54
- "outer" => JoinType::Outer,
55
- "semi" => JoinType::Semi,
56
- "anti" => JoinType::Anti,
57
- // #[cfg(feature = "cross_join")]
58
- // "cross" => JoinType::Cross,
59
- v => {
60
- return Err(RbValueError::new_err(format!(
61
- "how must be one of {{'inner', 'left', 'outer', 'semi', 'anti', 'cross'}}, got {}",
62
- v
63
- )))
64
- }
65
- };
66
- Ok(parsed)
67
- }
68
-
69
- pub fn get_df(obj: Value) -> RbResult<DataFrame> {
70
- let rbdf = obj.funcall::<_, _, &RbDataFrame>("_df", ())?;
71
- Ok(rbdf.df.borrow().clone())
72
- }
73
-
74
268
  pub fn parse_parquet_compression(
75
269
  compression: &str,
76
270
  compression_level: Option<i32>,
@@ -7,8 +7,9 @@ use std::io::{BufReader, BufWriter, Cursor};
7
7
  use std::ops::Deref;
8
8
  use std::path::PathBuf;
9
9
 
10
- use crate::conversion::parse_parquet_compression;
10
+ use crate::conversion::*;
11
11
  use crate::file::{get_file_like, get_mmap_bytes_reader};
12
+ use crate::series::to_rbseries_collection;
12
13
  use crate::{series, RbLazyFrame, RbPolarsErr, RbResult, RbSeries};
13
14
 
14
15
  #[magnus::wrap(class = "Polars::RbDataFrame")]
@@ -38,6 +39,10 @@ impl RbDataFrame {
38
39
  Ok(RbDataFrame::new(df))
39
40
  }
40
41
 
42
+ pub fn estimated_size(&self) -> usize {
43
+ self.df.borrow().estimated_size()
44
+ }
45
+
41
46
  pub fn read_csv(rb_f: Value, has_header: bool) -> RbResult<Self> {
42
47
  let mmap_bytes_r = get_mmap_bytes_reader(rb_f)?;
43
48
  let df = CsvReader::new(mmap_bytes_r)
@@ -213,6 +218,11 @@ impl RbDataFrame {
213
218
  format!("{}", self.df.borrow())
214
219
  }
215
220
 
221
+ pub fn get_columns(&self) -> Vec<RbSeries> {
222
+ let cols = self.df.borrow().get_columns().clone();
223
+ to_rbseries_collection(cols)
224
+ }
225
+
216
226
  pub fn columns(&self) -> Vec<String> {
217
227
  self.df
218
228
  .borrow()
@@ -222,6 +232,14 @@ impl RbDataFrame {
222
232
  .collect()
223
233
  }
224
234
 
235
+ pub fn set_column_names(&self, names: Vec<String>) -> RbResult<()> {
236
+ self.df
237
+ .borrow_mut()
238
+ .set_column_names(&names)
239
+ .map_err(RbPolarsErr::from)?;
240
+ Ok(())
241
+ }
242
+
225
243
  pub fn dtypes(&self) -> Vec<String> {
226
244
  self.df
227
245
  .borrow()
@@ -230,6 +248,11 @@ impl RbDataFrame {
230
248
  .collect()
231
249
  }
232
250
 
251
+ pub fn n_chunks(&self) -> RbResult<usize> {
252
+ let n = self.df.borrow().n_chunks().map_err(RbPolarsErr::from)?;
253
+ Ok(n)
254
+ }
255
+
233
256
  pub fn shape(&self) -> (usize, usize) {
234
257
  self.df.borrow().shape()
235
258
  }
@@ -258,6 +281,28 @@ impl RbDataFrame {
258
281
  .map_err(RbPolarsErr::from)
259
282
  }
260
283
 
284
+ pub fn select(&self, selection: Vec<String>) -> RbResult<Self> {
285
+ let df = self
286
+ .df
287
+ .borrow()
288
+ .select(selection)
289
+ .map_err(RbPolarsErr::from)?;
290
+ Ok(RbDataFrame::new(df))
291
+ }
292
+
293
+ pub fn take(&self, indices: Vec<IdxSize>) -> RbResult<Self> {
294
+ let indices = IdxCa::from_vec("", indices);
295
+ let df = self.df.borrow().take(&indices).map_err(RbPolarsErr::from)?;
296
+ Ok(RbDataFrame::new(df))
297
+ }
298
+
299
+ pub fn take_with_series(&self, indices: &RbSeries) -> RbResult<Self> {
300
+ let binding = indices.series.borrow();
301
+ let idx = binding.idx().map_err(RbPolarsErr::from)?;
302
+ let df = self.df.borrow().take(idx).map_err(RbPolarsErr::from)?;
303
+ Ok(RbDataFrame::new(df))
304
+ }
305
+
261
306
  pub fn sort(&self, by_column: String, reverse: bool, nulls_last: bool) -> RbResult<Self> {
262
307
  let df = self
263
308
  .df
@@ -273,6 +318,38 @@ impl RbDataFrame {
273
318
  Ok(RbDataFrame::new(df))
274
319
  }
275
320
 
321
+ pub fn replace(&self, column: String, new_col: &RbSeries) -> RbResult<()> {
322
+ self.df
323
+ .borrow_mut()
324
+ .replace(&column, new_col.series.borrow().clone())
325
+ .map_err(RbPolarsErr::from)?;
326
+ Ok(())
327
+ }
328
+
329
+ pub fn replace_at_idx(&self, index: usize, new_col: &RbSeries) -> RbResult<()> {
330
+ self.df
331
+ .borrow_mut()
332
+ .replace_at_idx(index, new_col.series.borrow().clone())
333
+ .map_err(RbPolarsErr::from)?;
334
+ Ok(())
335
+ }
336
+
337
+ pub fn insert_at_idx(&self, index: usize, new_col: &RbSeries) -> RbResult<()> {
338
+ self.df
339
+ .borrow_mut()
340
+ .insert_at_idx(index, new_col.series.borrow().clone())
341
+ .map_err(RbPolarsErr::from)?;
342
+ Ok(())
343
+ }
344
+
345
+ pub fn slice(&self, offset: usize, length: Option<usize>) -> Self {
346
+ let df = self.df.borrow().slice(
347
+ offset as i64,
348
+ length.unwrap_or_else(|| self.df.borrow().height()),
349
+ );
350
+ df.into()
351
+ }
352
+
276
353
  pub fn head(&self, length: Option<usize>) -> Self {
277
354
  self.df.borrow().head(length).into()
278
355
  }
@@ -281,6 +358,20 @@ impl RbDataFrame {
281
358
  self.df.borrow().tail(length).into()
282
359
  }
283
360
 
361
+ pub fn is_unique(&self) -> RbResult<RbSeries> {
362
+ let mask = self.df.borrow().is_unique().map_err(RbPolarsErr::from)?;
363
+ Ok(mask.into_series().into())
364
+ }
365
+
366
+ pub fn is_duplicated(&self) -> RbResult<RbSeries> {
367
+ let mask = self
368
+ .df
369
+ .borrow()
370
+ .is_duplicated()
371
+ .map_err(RbPolarsErr::from)?;
372
+ Ok(mask.into_series().into())
373
+ }
374
+
284
375
  pub fn frame_equal(&self, other: &RbDataFrame, null_equal: bool) -> bool {
285
376
  if null_equal {
286
377
  self.df.borrow().frame_equal_missing(&other.df.borrow())
@@ -289,16 +380,202 @@ impl RbDataFrame {
289
380
  }
290
381
  }
291
382
 
383
+ pub fn with_row_count(&self, name: String, offset: Option<IdxSize>) -> RbResult<Self> {
384
+ let df = self
385
+ .df
386
+ .borrow()
387
+ .with_row_count(&name, offset)
388
+ .map_err(RbPolarsErr::from)?;
389
+ Ok(df.into())
390
+ }
391
+
392
+ pub fn clone(&self) -> Self {
393
+ RbDataFrame::new(self.df.borrow().clone())
394
+ }
395
+
396
+ pub fn melt(
397
+ &self,
398
+ id_vars: Vec<String>,
399
+ value_vars: Vec<String>,
400
+ value_name: Option<String>,
401
+ variable_name: Option<String>,
402
+ ) -> RbResult<Self> {
403
+ let args = MeltArgs {
404
+ id_vars,
405
+ value_vars,
406
+ value_name,
407
+ variable_name,
408
+ };
409
+
410
+ let df = self.df.borrow().melt2(args).map_err(RbPolarsErr::from)?;
411
+ Ok(RbDataFrame::new(df))
412
+ }
413
+
414
+ pub fn partition_by(&self, groups: Vec<String>, stable: bool) -> RbResult<Vec<Self>> {
415
+ let out = if stable {
416
+ self.df.borrow().partition_by_stable(groups)
417
+ } else {
418
+ self.df.borrow().partition_by(groups)
419
+ }
420
+ .map_err(RbPolarsErr::from)?;
421
+ Ok(out.into_iter().map(|v| RbDataFrame::new(v)).collect())
422
+ }
423
+
424
+ pub fn shift(&self, periods: i64) -> Self {
425
+ self.df.borrow().shift(periods).into()
426
+ }
427
+
428
+ pub fn unique(
429
+ &self,
430
+ maintain_order: bool,
431
+ subset: Option<Vec<String>>,
432
+ keep: Wrap<UniqueKeepStrategy>,
433
+ ) -> RbResult<Self> {
434
+ let subset = subset.as_ref().map(|v| v.as_ref());
435
+ let df = match maintain_order {
436
+ true => self.df.borrow().unique_stable(subset, keep.0),
437
+ false => self.df.borrow().unique(subset, keep.0),
438
+ }
439
+ .map_err(RbPolarsErr::from)?;
440
+ Ok(df.into())
441
+ }
442
+
292
443
  pub fn lazy(&self) -> RbLazyFrame {
293
444
  self.df.borrow().clone().lazy().into()
294
445
  }
295
446
 
447
+ pub fn max(&self) -> Self {
448
+ self.df.borrow().max().into()
449
+ }
450
+
451
+ pub fn min(&self) -> Self {
452
+ self.df.borrow().min().into()
453
+ }
454
+
455
+ pub fn sum(&self) -> Self {
456
+ self.df.borrow().sum().into()
457
+ }
458
+
296
459
  pub fn mean(&self) -> Self {
297
460
  self.df.borrow().mean().into()
298
461
  }
299
462
 
463
+ pub fn std(&self, ddof: u8) -> Self {
464
+ self.df.borrow().std(ddof).into()
465
+ }
466
+
467
+ pub fn var(&self, ddof: u8) -> Self {
468
+ self.df.borrow().var(ddof).into()
469
+ }
470
+
471
+ pub fn median(&self) -> Self {
472
+ self.df.borrow().median().into()
473
+ }
474
+
475
+ pub fn hmean(&self, null_strategy: Wrap<NullStrategy>) -> RbResult<Option<RbSeries>> {
476
+ let s = self
477
+ .df
478
+ .borrow()
479
+ .hmean(null_strategy.0)
480
+ .map_err(RbPolarsErr::from)?;
481
+ Ok(s.map(|s| s.into()))
482
+ }
483
+
484
+ pub fn hmax(&self) -> RbResult<Option<RbSeries>> {
485
+ let s = self.df.borrow().hmax().map_err(RbPolarsErr::from)?;
486
+ Ok(s.map(|s| s.into()))
487
+ }
488
+
489
+ pub fn hmin(&self) -> RbResult<Option<RbSeries>> {
490
+ let s = self.df.borrow().hmin().map_err(RbPolarsErr::from)?;
491
+ Ok(s.map(|s| s.into()))
492
+ }
493
+
494
+ pub fn hsum(&self, null_strategy: Wrap<NullStrategy>) -> RbResult<Option<RbSeries>> {
495
+ let s = self
496
+ .df
497
+ .borrow()
498
+ .hsum(null_strategy.0)
499
+ .map_err(RbPolarsErr::from)?;
500
+ Ok(s.map(|s| s.into()))
501
+ }
502
+
503
+ pub fn quantile(
504
+ &self,
505
+ quantile: f64,
506
+ interpolation: Wrap<QuantileInterpolOptions>,
507
+ ) -> RbResult<Self> {
508
+ let df = self
509
+ .df
510
+ .borrow()
511
+ .quantile(quantile, interpolation.0)
512
+ .map_err(RbPolarsErr::from)?;
513
+ Ok(df.into())
514
+ }
515
+
516
+ pub fn to_dummies(&self, columns: Option<Vec<String>>) -> RbResult<Self> {
517
+ let df = match columns {
518
+ Some(cols) => self
519
+ .df
520
+ .borrow()
521
+ .columns_to_dummies(cols.iter().map(|x| x as &str).collect()),
522
+ None => self.df.borrow().to_dummies(),
523
+ }
524
+ .map_err(RbPolarsErr::from)?;
525
+ Ok(df.into())
526
+ }
527
+
300
528
  pub fn null_count(&self) -> Self {
301
529
  let df = self.df.borrow().null_count();
302
530
  df.into()
303
531
  }
532
+
533
+ pub fn shrink_to_fit(&self) {
534
+ self.df.borrow_mut().shrink_to_fit();
535
+ }
536
+
537
+ pub fn transpose(&self, include_header: bool, names: String) -> RbResult<Self> {
538
+ let mut df = self.df.borrow().transpose().map_err(RbPolarsErr::from)?;
539
+ if include_header {
540
+ let s = Utf8Chunked::from_iter_values(
541
+ &names,
542
+ self.df.borrow().get_columns().iter().map(|s| s.name()),
543
+ )
544
+ .into_series();
545
+ df.insert_at_idx(0, s).unwrap();
546
+ }
547
+ Ok(df.into())
548
+ }
549
+
550
+ pub fn upsample(
551
+ &self,
552
+ by: Vec<String>,
553
+ index_column: String,
554
+ every: String,
555
+ offset: String,
556
+ stable: bool,
557
+ ) -> RbResult<Self> {
558
+ let out = if stable {
559
+ self.df.borrow().upsample_stable(
560
+ by,
561
+ &index_column,
562
+ Duration::parse(&every),
563
+ Duration::parse(&offset),
564
+ )
565
+ } else {
566
+ self.df.borrow().upsample(
567
+ by,
568
+ &index_column,
569
+ Duration::parse(&every),
570
+ Duration::parse(&offset),
571
+ )
572
+ };
573
+ let out = out.map_err(RbPolarsErr::from)?;
574
+ Ok(out.into())
575
+ }
576
+
577
+ pub fn unnest(&self, names: Vec<String>) -> RbResult<Self> {
578
+ let df = self.df.borrow().unnest(names).map_err(RbPolarsErr::from)?;
579
+ Ok(df.into())
580
+ }
304
581
  }