polars-df 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +3 -0
  3. data/CHANGELOG.md +9 -0
  4. data/Cargo.lock +74 -3
  5. data/Cargo.toml +3 -0
  6. data/README.md +1 -1
  7. data/ext/polars/Cargo.toml +18 -1
  8. data/ext/polars/src/conversion.rs +115 -2
  9. data/ext/polars/src/dataframe.rs +228 -11
  10. data/ext/polars/src/error.rs +4 -0
  11. data/ext/polars/src/lazy/dataframe.rs +5 -5
  12. data/ext/polars/src/lazy/dsl.rs +157 -2
  13. data/ext/polars/src/lib.rs +185 -10
  14. data/ext/polars/src/list_construction.rs +100 -0
  15. data/ext/polars/src/series.rs +217 -29
  16. data/ext/polars/src/set.rs +91 -0
  17. data/ext/polars/src/utils.rs +19 -0
  18. data/lib/polars/batched_csv_reader.rb +1 -0
  19. data/lib/polars/cat_expr.rb +39 -0
  20. data/lib/polars/cat_name_space.rb +54 -0
  21. data/lib/polars/data_frame.rb +2384 -140
  22. data/lib/polars/date_time_expr.rb +1282 -7
  23. data/lib/polars/date_time_name_space.rb +1484 -0
  24. data/lib/polars/exceptions.rb +20 -0
  25. data/lib/polars/expr.rb +4374 -53
  26. data/lib/polars/expr_dispatch.rb +22 -0
  27. data/lib/polars/functions.rb +219 -0
  28. data/lib/polars/group_by.rb +518 -0
  29. data/lib/polars/io.rb +421 -2
  30. data/lib/polars/lazy_frame.rb +1267 -69
  31. data/lib/polars/lazy_functions.rb +412 -24
  32. data/lib/polars/lazy_group_by.rb +80 -0
  33. data/lib/polars/list_expr.rb +507 -5
  34. data/lib/polars/list_name_space.rb +346 -0
  35. data/lib/polars/meta_expr.rb +21 -0
  36. data/lib/polars/series.rb +2256 -242
  37. data/lib/polars/slice.rb +104 -0
  38. data/lib/polars/string_expr.rb +847 -10
  39. data/lib/polars/string_name_space.rb +690 -0
  40. data/lib/polars/struct_expr.rb +73 -0
  41. data/lib/polars/struct_name_space.rb +64 -0
  42. data/lib/polars/utils.rb +71 -3
  43. data/lib/polars/version.rb +2 -1
  44. data/lib/polars/when.rb +1 -0
  45. data/lib/polars/when_then.rb +1 -0
  46. data/lib/polars.rb +12 -10
  47. metadata +15 -2
data/lib/polars/series.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  module Polars
2
2
  # A Series represents a single column in a polars DataFrame.
3
3
  class Series
4
- # @private
5
- attr_accessor :_s
4
+ include ExprDispatch
6
5
 
7
6
  # Create a new Series.
8
7
  #
@@ -48,6 +47,8 @@ module Polars
48
47
 
49
48
  if values.nil?
50
49
  self._s = sequence_to_rbseries(name, [], dtype: dtype, dtype_if_empty: dtype_if_empty)
50
+ elsif values.is_a?(Series)
51
+ self._s = series_to_rbseries(name, values)
51
52
  elsif values.is_a?(Range)
52
53
  self._s =
53
54
  Polars.arange(
@@ -130,6 +131,9 @@ module Polars
130
131
  #
131
132
  # @return [Series]
132
133
  def &(other)
134
+ if !other.is_a?(Series)
135
+ other = Series.new([other])
136
+ end
133
137
  Utils.wrap_s(_s.bitand(other._s))
134
138
  end
135
139
 
@@ -137,6 +141,9 @@ module Polars
137
141
  #
138
142
  # @return [Series]
139
143
  def |(other)
144
+ if !other.is_a?(Series)
145
+ other = Series.new([other])
146
+ end
140
147
  Utils.wrap_s(_s.bitor(other._s))
141
148
  end
142
149
 
@@ -144,53 +151,90 @@ module Polars
144
151
  #
145
152
  # @return [Series]
146
153
  def ^(other)
154
+ if !other.is_a?(Series)
155
+ other = Series.new([other])
156
+ end
147
157
  Utils.wrap_s(_s.bitxor(other._s))
148
158
  end
149
159
 
150
- # def ==(other)
151
- # end
160
+ # Equal.
161
+ #
162
+ # @return [Series]
163
+ def ==(other)
164
+ _comp(other, :eq)
165
+ end
152
166
 
153
- # def !=(other)
154
- # end
167
+ # Not equal.
168
+ #
169
+ # @return [Series]
170
+ def !=(other)
171
+ _comp(other, :neq)
172
+ end
155
173
 
156
- # def >(other)
157
- # end
174
+ # Greater than.
175
+ #
176
+ # @return [Series]
177
+ def >(other)
178
+ _comp(other, :gt)
179
+ end
158
180
 
159
- # def <(other)
160
- # end
181
+ # Less than.
182
+ #
183
+ # @return [Series]
184
+ def <(other)
185
+ _comp(other, :lt)
186
+ end
161
187
 
162
- # def >=(other)
163
- # end
188
+ # Greater than or equal.
189
+ #
190
+ # @return [Series]
191
+ def >=(other)
192
+ _comp(other, :gt_eq)
193
+ end
164
194
 
165
- # def <=(other)
166
- # end
195
+ # Less than or equal.
196
+ #
197
+ # @return [Series]
198
+ def <=(other)
199
+ _comp(other, :lt_eq)
200
+ end
167
201
 
168
202
  # Performs addition.
169
203
  #
170
204
  # @return [Series]
171
205
  def +(other)
172
- Utils. wrap_s(_s.add(other._s))
206
+ _arithmetic(other, :add)
173
207
  end
174
208
 
175
209
  # Performs subtraction.
176
210
  #
177
211
  # @return [Series]
178
212
  def -(other)
179
- Utils.wrap_s(_s.sub(other._s))
213
+ _arithmetic(other, :sub)
180
214
  end
181
215
 
182
216
  # Performs multiplication.
183
217
  #
184
218
  # @return [Series]
185
219
  def *(other)
186
- Utils.wrap_s(_s.mul(other._s))
220
+ _arithmetic(other, :mul)
187
221
  end
188
222
 
189
223
  # Performs division.
190
224
  #
191
225
  # @return [Series]
192
226
  def /(other)
193
- Utils.wrap_s(_s.div(other._s))
227
+ _arithmetic(other, :div)
228
+ end
229
+
230
+ # Returns the modulo.
231
+ #
232
+ # @return [Series]
233
+ def %(other)
234
+ if is_datelike
235
+ raise ArgumentError, "first cast to integer before applying modulo on datelike dtypes"
236
+ end
237
+ _arithmetic(other, :rem)
194
238
  end
195
239
 
196
240
  # Raises to the power of exponent.
@@ -203,18 +247,63 @@ module Polars
203
247
  to_frame.select(Polars.col(name).pow(power)).to_series
204
248
  end
205
249
 
206
- # def -@(other)
207
- # end
250
+ # Performs negation.
251
+ #
252
+ # @return [Series]
253
+ def -@
254
+ 0 - self
255
+ end
208
256
 
209
257
  # Returns elements of the Series.
210
258
  #
211
259
  # @return [Object]
212
260
  def [](item)
213
- _s.get_idx(item)
261
+ if item.is_a?(Integer)
262
+ return _s.get_idx(item)
263
+ end
264
+
265
+ if item.is_a?(Range)
266
+ return Slice.new(self).apply(item)
267
+ end
268
+
269
+ raise ArgumentError, "Cannot get item of type: #{item.class.name}"
214
270
  end
215
271
 
216
- # def []=(key, value)
217
- # end
272
+ # Sets an element of the Series.
273
+ #
274
+ # @return [Object]
275
+ def []=(key, value)
276
+ if value.is_a?(Array)
277
+ if is_numeric || is_datelike
278
+ set_at_idx(key, value)
279
+ return
280
+ end
281
+ raise ArgumentError, "cannot set Series of dtype: #{dtype} with list/tuple as value; use a scalar value"
282
+ end
283
+
284
+ if key.is_a?(Series)
285
+ if key.dtype == :bool
286
+ self._s = set(key, value)._s
287
+ elsif key.dtype == :u64
288
+ self._s = set_at_idx(key.cast(:u32), value)._s
289
+ elsif key.dtype == :u32
290
+ self._s = set_at_idx(key, value)._s
291
+ else
292
+ raise Todo
293
+ end
294
+ end
295
+
296
+ if key.is_a?(Array)
297
+ s = Utils.wrap_s(sequence_to_rbseries("", key, dtype: :u32))
298
+ self[s] = value
299
+ elsif key.is_a?(Integer)
300
+ # TODO fix
301
+ # self[[key]] = value
302
+ set_at_idx(key, value)
303
+ else
304
+ raise ArgumentError, "cannot use #{key} for indexing"
305
+ end
306
+ end
218
307
 
219
308
  # Return an estimation of the total (heap) allocated size of the Series.
220
309
  #
@@ -268,20 +357,43 @@ module Polars
268
357
  to_frame.select(Polars.col(name).all).to_series[0]
269
358
  end
270
359
 
271
- # def log
272
- # end
360
+ # Compute the logarithm to a given base.
361
+ #
362
+ # @param base [Float]
363
+ # Given base, defaults to `Math::E`.
364
+ #
365
+ # @return [Series]
366
+ def log(base = Math::E)
367
+ super
368
+ end
273
369
 
274
- # def log10
275
- # end
370
+ # Compute the base 10 logarithm of the input array, element-wise.
371
+ #
372
+ # @return [Series]
373
+ def log10
374
+ super
375
+ end
276
376
 
277
- # def exp
278
- # end
377
+ # Compute the exponential, element-wise.
378
+ #
379
+ # @return [Series]
380
+ def exp
381
+ super
382
+ end
279
383
 
280
- # def drop_nulls
281
- # end
384
+ # Create a new Series that copies data from this Series without null values.
385
+ #
386
+ # @return [Series]
387
+ def drop_nulls
388
+ super
389
+ end
282
390
 
283
- # def drop_nans
284
- # end
391
+ # Drop NaN values.
392
+ #
393
+ # @return [Series]
394
+ def drop_nans
395
+ super
396
+ end
285
397
 
286
398
  # Cast this Series to a DataFrame.
287
399
  #
@@ -290,8 +402,94 @@ module Polars
290
402
  Utils.wrap_df(RbDataFrame.new([_s]))
291
403
  end
292
404
 
293
- # def describe
294
- # end
405
+ # Quick summary statistics of a series.
406
+ #
407
+ # Series with mixed datatypes will return summary statistics for the datatype of
408
+ # the first value.
409
+ #
410
+ # @return [DataFrame]
411
+ #
412
+ # @example
413
+ # series_num = Polars::Series.new([1, 2, 3, 4, 5])
414
+ # series_num.describe
415
+ # # =>
416
+ # # shape: (6, 2)
417
+ # # ┌────────────┬──────────┐
418
+ # # │ statistic ┆ value │
419
+ # # │ --- ┆ --- │
420
+ # # │ str ┆ f64 │
421
+ # # ╞════════════╪══════════╡
422
+ # # │ min ┆ 1.0 │
423
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
424
+ # # │ max ┆ 5.0 │
425
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
426
+ # # │ null_count ┆ 0.0 │
427
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
428
+ # # │ mean ┆ 3.0 │
429
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
430
+ # # │ std ┆ 1.581139 │
431
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
432
+ # # │ count ┆ 5.0 │
433
+ # # └────────────┴──────────┘
434
+ #
435
+ # @example
436
+ # series_str = Polars::Series.new(["a", "a", nil, "b", "c"])
437
+ # series_str.describe
438
+ # # =>
439
+ # # shape: (3, 2)
440
+ # # ┌────────────┬───────┐
441
+ # # │ statistic ┆ value │
442
+ # # │ --- ┆ --- │
443
+ # # │ str ┆ i64 │
444
+ # # ╞════════════╪═══════╡
445
+ # # │ unique ┆ 4 │
446
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
447
+ # # │ null_count ┆ 1 │
448
+ # # ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
449
+ # # │ count ┆ 5 │
450
+ # # └────────────┴───────┘
451
+ def describe
452
+ if len == 0
453
+ raise ArgumentError, "Series must contain at least one value"
454
+ elsif is_numeric
455
+ s = cast(:f64)
456
+ stats = {
457
+ "min" => s.min,
458
+ "max" => s.max,
459
+ "null_count" => s.null_count,
460
+ "mean" => s.mean,
461
+ "std" => s.std,
462
+ "count" => s.len
463
+ }
464
+ elsif is_boolean
465
+ stats = {
466
+ "sum" => sum,
467
+ "null_count" => null_count,
468
+ "count" => len
469
+ }
470
+ elsif is_utf8
471
+ stats = {
472
+ "unique" => unique.length,
473
+ "null_count" => null_count,
474
+ "count" => len
475
+ }
476
+ elsif is_datelike
477
+ # we coerce all to string, because a polars column
478
+ # only has a single dtype and dates: datetime and count: int don't match
479
+ stats = {
480
+ "min" => dt.min.to_s,
481
+ "max" => dt.max.to_s,
482
+ "null_count" => null_count.to_s,
483
+ "count" => len.to_s
484
+ }
485
+ else
486
+ raise TypeError, "This type is not supported"
487
+ end
488
+
489
+ Polars::DataFrame.new(
490
+ {"statistic" => stats.keys, "value" => stats.values}
491
+ )
492
+ end
295
493
 
296
494
  # Reduce this Series to the sum value.
297
495
  #
@@ -352,11 +550,19 @@ module Polars
352
550
  _s.max
353
551
  end
354
552
 
355
- # def nan_max
356
- # end
553
+ # Get maximum value, but propagate/poison encountered NaN values.
554
+ #
555
+ # @return [Object]
556
+ def nan_max
557
+ to_frame.select(Polars.col(name).nan_max)[0, 0]
558
+ end
357
559
 
358
- # def nan_min
359
- # end
560
+ # Get minimum value, but propagate/poison encountered NaN values.
561
+ #
562
+ # @return [Object]
563
+ def nan_min
564
+ to_frame.select(Polars.col(name).nan_min)[0, 0]
565
+ end
360
566
 
361
567
  # Get the standard deviation of this Series.
362
568
  #
@@ -478,14 +684,86 @@ module Polars
478
684
  Utils.wrap_df(_s.value_counts(sort))
479
685
  end
480
686
 
481
- # def unique_counts
482
- # end
687
+ # Return a count of the unique values in the order of appearance.
688
+ #
689
+ # @return [Series]
690
+ #
691
+ # @example
692
+ # s = Polars::Series.new("id", ["a", "b", "b", "c", "c", "c"])
693
+ # s.unique_counts
694
+ # # =>
695
+ # # shape: (3,)
696
+ # # Series: 'id' [u32]
697
+ # # [
698
+ # # 1
699
+ # # 2
700
+ # # 3
701
+ # # ]
702
+ def unique_counts
703
+ super
704
+ end
483
705
 
484
- # def entropy
485
- # end
706
+ # Computes the entropy.
707
+ #
708
+ # Uses the formula `-sum(pk * log(pk)` where `pk` are discrete probabilities.
709
+ #
710
+ # @param base [Float]
711
+ # Given base, defaults to `e`
712
+ # @param normalize [Boolean]
713
+ # Normalize pk if it doesn't sum to 1.
714
+ #
715
+ # @return [Float, nil]
716
+ #
717
+ # @example
718
+ # a = Polars::Series.new([0.99, 0.005, 0.005])
719
+ # a.entropy(normalize: true)
720
+ # # => 0.06293300616044681
721
+ #
722
+ # @example
723
+ # b = Polars::Series.new([0.65, 0.10, 0.25])
724
+ # b.entropy(normalize: true)
725
+ # # => 0.8568409950394724
726
+ def entropy(base: Math::E, normalize: false)
727
+ Polars.select(Polars.lit(self).entropy(base: base, normalize: normalize)).to_series[0]
728
+ end
486
729
 
487
- # def cumulative_eval
488
- # end
730
+ # Run an expression over a sliding window that increases `1` slot every iteration.
731
+ #
732
+ # @param expr [Expr]
733
+ # Expression to evaluate
734
+ # @param min_periods [Integer]
735
+ # Number of valid values there should be in the window before the expression
736
+ # is evaluated. valid values = `length - null_count`
737
+ # @param parallel [Boolean]
738
+ # Run in parallel. Don't do this in a groupby or another operation that
739
+ # already has much parallelization.
740
+ #
741
+ # @return [Series]
742
+ #
743
+ # @note
744
+ # This functionality is experimental and may change without it being considered a
745
+ # breaking change.
746
+ #
747
+ # @note
748
+ # This can be really slow as it can have `O(n^2)` complexity. Don't use this
749
+ # for operations that visit all elements.
750
+ #
751
+ # @example
752
+ # s = Polars::Series.new("values", [1, 2, 3, 4, 5])
753
+ # s.cumulative_eval(Polars.element.first - Polars.element.last ** 2)
754
+ # # =>
755
+ # # shape: (5,)
756
+ # # Series: 'values' [f64]
757
+ # # [
758
+ # # 0.0
759
+ # # -3.0
760
+ # # -8.0
761
+ # # -15.0
762
+ # # -24.0
763
+ # # ]
764
+ def cumulative_eval(expr, min_periods: 1, parallel: false)
765
+ super
766
+ end
489
767
 
490
768
  # Return a copy of the Series with a new alias/name.
491
769
  #
@@ -585,7 +863,7 @@ module Polars
585
863
  # # 6
586
864
  # # ]
587
865
  def cumsum(reverse: false)
588
- Utils.wrap_s(_s.cumsum(reverse))
866
+ super
589
867
  end
590
868
 
591
869
  # Get an array with the cumulative min computed at every element.
@@ -607,7 +885,7 @@ module Polars
607
885
  # # 1
608
886
  # # ]
609
887
  def cummin(reverse: false)
610
- Utils.wrap_s(_s.cummin(reverse))
888
+ super
611
889
  end
612
890
 
613
891
  # Get an array with the cumulative max computed at every element.
@@ -629,7 +907,7 @@ module Polars
629
907
  # # 5
630
908
  # # ]
631
909
  def cummax(reverse: false)
632
- Utils.wrap_s(_s.cummax(reverse))
910
+ super
633
911
  end
634
912
 
635
913
  # Get an array with the cumulative product computed at every element.
@@ -655,7 +933,7 @@ module Polars
655
933
  # # 6
656
934
  # # ]
657
935
  def cumprod(reverse: false)
658
- Utils.wrap_s(_s.cumprod(reverse))
936
+ super
659
937
  end
660
938
 
661
939
  # Get the first `n` rows.
@@ -702,8 +980,7 @@ module Polars
702
980
  # # 3
703
981
  # # ]
704
982
  def slice(offset, length = nil)
705
- length = len if length.nil?
706
- Utils.wrap_s(_s.slice(offset, length))
983
+ super
707
984
  end
708
985
 
709
986
  # Append a Series to this one.
@@ -835,8 +1112,23 @@ module Polars
835
1112
  to_frame.select(Utils.col(name).tail(n)).to_series
836
1113
  end
837
1114
 
838
- # def take_every
839
- # end
1115
+ # Take every nth value in the Series and return as new Series.
1116
+ #
1117
+ # @return [Series]
1118
+ #
1119
+ # @example
1120
+ # s = Polars::Series.new("a", [1, 2, 3, 4])
1121
+ # s.take_every(2)
1122
+ # # =>
1123
+ # # shape: (2,)
1124
+ # # Series: 'a' [i64]
1125
+ # # [
1126
+ # # 1
1127
+ # # 3
1128
+ # # ]
1129
+ def take_every(n)
1130
+ super
1131
+ end
840
1132
 
841
1133
  # Sort this Series.
842
1134
  #
@@ -878,17 +1170,78 @@ module Polars
878
1170
  end
879
1171
  end
880
1172
 
881
- # def top_k
882
- # end
1173
+ # Return the `k` largest elements.
1174
+ #
1175
+ # If `reverse: true`, the smallest elements will be given.
1176
+ #
1177
+ # @param k [Integer]
1178
+ # Number of elements to return.
1179
+ # @param reverse [Boolean]
1180
+ # Return the smallest elements.
1181
+ #
1182
+ # @return [Boolean]
1183
+ def top_k(k: 5, reverse: false)
1184
+ super
1185
+ end
883
1186
 
884
- # def arg_sort
885
- # end
1187
+ # Get the index values that would sort this Series.
1188
+ #
1189
+ # @param reverse [Boolean]
1190
+ # Sort in reverse (descending) order.
1191
+ # @param nulls_last [Boolean]
1192
+ # Place null values last instead of first.
1193
+ #
1194
+ # @return [Series]
1195
+ #
1196
+ # @example
1197
+ # s = Polars::Series.new("a", [5, 3, 4, 1, 2])
1198
+ # s.arg_sort
1199
+ # # =>
1200
+ # # shape: (5,)
1201
+ # # Series: 'a' [u32]
1202
+ # # [
1203
+ # # 3
1204
+ # # 4
1205
+ # # 1
1206
+ # # 2
1207
+ # # 0
1208
+ # # ]
1209
+ def arg_sort(reverse: false, nulls_last: false)
1210
+ super
1211
+ end
886
1212
 
887
- # def argsort
888
- # end
1213
+ # Get the index values that would sort this Series.
1214
+ #
1215
+ # Alias for {#arg_sort}.
1216
+ #
1217
+ # @param reverse [Boolean]
1218
+ # Sort in reverse (descending) order.
1219
+ # @param nulls_last [Boolean]
1220
+ # Place null values last instead of first.
1221
+ #
1222
+ # @return [Series]
1223
+ def argsort(reverse: false, nulls_last: false)
1224
+ super
1225
+ end
889
1226
 
890
- # def arg_unique
891
- # end
1227
+ # Get unique index as Series.
1228
+ #
1229
+ # @return [Series]
1230
+ #
1231
+ # @example
1232
+ # s = Polars::Series.new("a", [1, 2, 2, 3])
1233
+ # s.arg_unique
1234
+ # # =>
1235
+ # # shape: (3,)
1236
+ # # Series: 'a' [u32]
1237
+ # # [
1238
+ # # 0
1239
+ # # 1
1240
+ # # 3
1241
+ # # ]
1242
+ def arg_unique
1243
+ super
1244
+ end
892
1245
 
893
1246
  # Get the index of the minimal value.
894
1247
  #
@@ -914,14 +1267,58 @@ module Polars
914
1267
  _s.arg_max
915
1268
  end
916
1269
 
917
- # def search_sorted
918
- # end
1270
+ # Find indices where elements should be inserted to maintain order.
1271
+ #
1272
+ # @param element [Object]
1273
+ # Expression or scalar value.
1274
+ #
1275
+ # @return [Integer]
1276
+ def search_sorted(element)
1277
+ Polars.select(Polars.lit(self).search_sorted(element))[0, 0]
1278
+ end
919
1279
 
920
- # def unique
921
- # end
1280
+ # Get unique elements in series.
1281
+ #
1282
+ # @param maintain_order [Boolean]
1283
+ # Maintain order of data. This requires more work.
1284
+ #
1285
+ # @return [Series]
1286
+ #
1287
+ # @example
1288
+ # s = Polars::Series.new("a", [1, 2, 2, 3])
1289
+ # s.unique.sort
1290
+ # # =>
1291
+ # # shape: (3,)
1292
+ # # Series: 'a' [i64]
1293
+ # # [
1294
+ # # 1
1295
+ # # 2
1296
+ # # 3
1297
+ # # ]
1298
+ def unique(maintain_order: false)
1299
+ super
1300
+ end
922
1301
 
923
- # def take
924
- # end
1302
+ # Take values by index.
1303
+ #
1304
+ # @param indices [Array]
1305
+ # Index location used for selection.
1306
+ #
1307
+ # @return [Series]
1308
+ #
1309
+ # @example
1310
+ # s = Polars::Series.new("a", [1, 2, 3, 4])
1311
+ # s.take([1, 3])
1312
+ # # =>
1313
+ # # shape: (2,)
1314
+ # # Series: 'a' [i64]
1315
+ # # [
1316
+ # # 2
1317
+ # # 4
1318
+ # # ]
1319
+ def take(indices)
1320
+ to_frame.select(Polars.col(name).take(indices)).to_series
1321
+ end
925
1322
 
926
1323
  # Count the null values in this Series.
927
1324
  #
@@ -930,7 +1327,7 @@ module Polars
930
1327
  _s.null_count
931
1328
  end
932
1329
 
933
- # Return True if the Series has a validity bitmask.
1330
+ # Return `true` if the Series has a validity bitmask.
934
1331
  #
935
1332
  # If there is none, it means that there are no null values.
936
1333
  # Use this to swiftly assert a Series does not have null values.
@@ -953,41 +1350,263 @@ module Polars
953
1350
  end
954
1351
  alias_method :empty?, :is_empty
955
1352
 
956
- # def is_null
957
- # end
958
-
959
- # def is_not_null
960
- # end
961
-
962
- # def is_finite
963
- # end
964
-
965
- # def is_infinite
966
- # end
1353
+ # Returns a boolean Series indicating which values are null.
1354
+ #
1355
+ # @return [Series]
1356
+ #
1357
+ # @example
1358
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, nil])
1359
+ # s.is_null
1360
+ # # =>
1361
+ # # shape: (4,)
1362
+ # # Series: 'a' [bool]
1363
+ # # [
1364
+ # # false
1365
+ # # false
1366
+ # # false
1367
+ # # true
1368
+ # # ]
1369
+ def is_null
1370
+ super
1371
+ end
967
1372
 
968
- # def is_nan
969
- # end
1373
+ # Returns a boolean Series indicating which values are not null.
1374
+ #
1375
+ # @return [Series]
1376
+ #
1377
+ # @example
1378
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, nil])
1379
+ # s.is_not_null
1380
+ # # =>
1381
+ # # shape: (4,)
1382
+ # # Series: 'a' [bool]
1383
+ # # [
1384
+ # # true
1385
+ # # true
1386
+ # # true
1387
+ # # false
1388
+ # # ]
1389
+ def is_not_null
1390
+ super
1391
+ end
970
1392
 
971
- # def is_not_nan
972
- # end
1393
+ # Returns a boolean Series indicating which values are finite.
1394
+ #
1395
+ # @return [Series]
1396
+ #
1397
+ # @example
1398
+ # s = Polars::Series.new("a", [1.0, 2.0, Float::INFINITY])
1399
+ # s.is_finite
1400
+ # # =>
1401
+ # # shape: (3,)
1402
+ # # Series: 'a' [bool]
1403
+ # # [
1404
+ # # true
1405
+ # # true
1406
+ # # false
1407
+ # # ]
1408
+ def is_finite
1409
+ super
1410
+ end
973
1411
 
974
- # def is_in
975
- # end
1412
+ # Returns a boolean Series indicating which values are infinite.
1413
+ #
1414
+ # @return [Series]
1415
+ #
1416
+ # @example
1417
+ # s = Polars::Series.new("a", [1.0, 2.0, Float::INFINITY])
1418
+ # s.is_infinite
1419
+ # # =>
1420
+ # # shape: (3,)
1421
+ # # Series: 'a' [bool]
1422
+ # # [
1423
+ # # false
1424
+ # # false
1425
+ # # true
1426
+ # # ]
1427
+ def is_infinite
1428
+ super
1429
+ end
976
1430
 
977
- # def arg_true
978
- # end
1431
+ # Returns a boolean Series indicating which values are NaN.
1432
+ #
1433
+ # @return [Series]
1434
+ #
1435
+ # @example
1436
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, Float::NAN])
1437
+ # s.is_nan
1438
+ # # =>
1439
+ # # shape: (4,)
1440
+ # # Series: 'a' [bool]
1441
+ # # [
1442
+ # # false
1443
+ # # false
1444
+ # # false
1445
+ # # true
1446
+ # # ]
1447
+ def is_nan
1448
+ super
1449
+ end
979
1450
 
980
- # def is_unique
981
- # end
1451
+ # Returns a boolean Series indicating which values are not NaN.
1452
+ #
1453
+ # @return [Series]
1454
+ #
1455
+ # @example
1456
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, Float::NAN])
1457
+ # s.is_not_nan
1458
+ # # =>
1459
+ # # shape: (4,)
1460
+ # # Series: 'a' [bool]
1461
+ # # [
1462
+ # # true
1463
+ # # true
1464
+ # # true
1465
+ # # false
1466
+ # # ]
1467
+ def is_not_nan
1468
+ super
1469
+ end
982
1470
 
983
- # def is_first
984
- # end
1471
+ # Check if elements of this Series are in the other Series.
1472
+ #
1473
+ # @return [Series]
1474
+ #
1475
+ # @example
1476
+ # s = Polars::Series.new("a", [1, 2, 3])
1477
+ # s2 = Polars::Series.new("b", [2, 4])
1478
+ # s2.is_in(s)
1479
+ # # =>
1480
+ # # shape: (2,)
1481
+ # # Series: 'b' [bool]
1482
+ # # [
1483
+ # # true
1484
+ # # false
1485
+ # # ]
1486
+ #
1487
+ # @example
1488
+ # sets = Polars::Series.new("sets", [[1, 2, 3], [1, 2], [9, 10]])
1489
+ # # =>
1490
+ # # shape: (3,)
1491
+ # # Series: 'sets' [list]
1492
+ # # [
1493
+ # # [1, 2, 3]
1494
+ # # [1, 2]
1495
+ # # [9, 10]
1496
+ # # ]
1497
+ #
1498
+ # @example
1499
+ # optional_members = Polars::Series.new("optional_members", [1, 2, 3])
1500
+ # # =>
1501
+ # # shape: (3,)
1502
+ # # Series: 'optional_members' [i64]
1503
+ # # [
1504
+ # # 1
1505
+ # # 2
1506
+ # # 3
1507
+ # # ]
1508
+ #
1509
+ # @example
1510
+ # optional_members.is_in(sets)
1511
+ # # =>
1512
+ # # shape: (3,)
1513
+ # # Series: 'optional_members' [bool]
1514
+ # # [
1515
+ # # true
1516
+ # # true
1517
+ # # false
1518
+ # # ]
1519
+ def is_in(other)
1520
+ super
1521
+ end
985
1522
 
986
- # def is_duplicated
987
- # end
1523
+ # Get index values where Boolean Series evaluate `true`.
1524
+ #
1525
+ # @return [Series]
1526
+ #
1527
+ # @example
1528
+ # s = Polars::Series.new("a", [1, 2, 3])
1529
+ # (s == 2).arg_true
1530
+ # # =>
1531
+ # # shape: (1,)
1532
+ # # Series: 'a' [u32]
1533
+ # # [
1534
+ # # 1
1535
+ # # ]
1536
+ def arg_true
1537
+ Polars.arg_where(self, eager: true)
1538
+ end
988
1539
 
989
- # def explode
990
- # end
1540
+ # Get mask of all unique values.
1541
+ #
1542
+ # @return [Series]
1543
+ #
1544
+ # @example
1545
+ # s = Polars::Series.new("a", [1, 2, 2, 3])
1546
+ # s.is_unique
1547
+ # # =>
1548
+ # # shape: (4,)
1549
+ # # Series: 'a' [bool]
1550
+ # # [
1551
+ # # true
1552
+ # # false
1553
+ # # false
1554
+ # # true
1555
+ # # ]
1556
+ def is_unique
1557
+ super
1558
+ end
1559
+
1560
+ # Get a mask of the first unique value.
1561
+ #
1562
+ # @return [Series]
1563
+ def is_first
1564
+ super
1565
+ end
1566
+
1567
+ # Get mask of all duplicated values.
1568
+ #
1569
+ # @return [Series]
1570
+ #
1571
+ # @example
1572
+ # s = Polars::Series.new("a", [1, 2, 2, 3])
1573
+ # s.is_duplicated
1574
+ # # =>
1575
+ # # shape: (4,)
1576
+ # # Series: 'a' [bool]
1577
+ # # [
1578
+ # # false
1579
+ # # true
1580
+ # # true
1581
+ # # false
1582
+ # # ]
1583
+ def is_duplicated
1584
+ super
1585
+ end
1586
+
1587
+ # Explode a list or utf8 Series.
1588
+ #
1589
+ # This means that every item is expanded to a new row.
1590
+ #
1591
+ # @return [Series]
1592
+ #
1593
+ # @example
1594
+ # s = Polars::Series.new("a", [[1, 2], [3, 4], [9, 10]])
1595
+ # s.explode
1596
+ # # =>
1597
+ # # shape: (6,)
1598
+ # # Series: 'a' [i64]
1599
+ # # [
1600
+ # # 1
1601
+ # # 2
1602
+ # # 3
1603
+ # # 4
1604
+ # # 9
1605
+ # # 10
1606
+ # # ]
1607
+ def explode
1608
+ super
1609
+ end
991
1610
 
992
1611
  # Check if series is equal with another Series.
993
1612
  #
@@ -1025,8 +1644,29 @@ module Polars
1025
1644
  end
1026
1645
  alias_method :length, :len
1027
1646
 
1028
- # def cast
1029
- # end
1647
+ # Cast between data types.
1648
+ #
1649
+ # @param dtype [Symbol]
1650
+ # DataType to cast to
1651
+ # @param strict [Boolean]
1652
+ # Throw an error if a cast could not be done for instance due to an overflow
1653
+ #
1654
+ # @return [Series]
1655
+ #
1656
+ # @example
1657
+ # s = Polars::Series.new("a", [true, false, true])
1658
+ # s.cast(:u32)
1659
+ # # =>
1660
+ # # shape: (3,)
1661
+ # # Series: 'a' [u32]
1662
+ # # [
1663
+ # # 1
1664
+ # # 0
1665
+ # # 1
1666
+ # # ]
1667
+ def cast(dtype, strict: true)
1668
+ super
1669
+ end
1030
1670
 
1031
1671
  # def to_physical
1032
1672
  # end
@@ -1054,8 +1694,24 @@ module Polars
1054
1694
  in_place ? self : Utils.wrap_s(opt_s)
1055
1695
  end
1056
1696
 
1057
- # def reverse
1058
- # end
1697
+ # Return Series in reverse order.
1698
+ #
1699
+ # @return [Series]
1700
+ #
1701
+ # @example
1702
+ # s = Polars::Series.new("a", [1, 2, 3], dtype: :i8)
1703
+ # s.reverse
1704
+ # # =>
1705
+ # # shape: (3,)
1706
+ # # Series: 'a' [i8]
1707
+ # # [
1708
+ # # 3
1709
+ # # 2
1710
+ # # 1
1711
+ # # ]
1712
+ def reverse
1713
+ super
1714
+ end
1059
1715
 
1060
1716
  # Check if this Series datatype is numeric.
1061
1717
  #
@@ -1132,52 +1788,176 @@ module Polars
1132
1788
  # def set
1133
1789
  # end
1134
1790
 
1135
- # def set_at_idx
1136
- # end
1137
-
1138
- # def cleared
1139
- # end
1140
-
1141
- # clone handled by initialize_copy
1142
-
1143
- # def fill_nan
1144
- # end
1145
-
1146
- # def fill_null
1147
- # end
1148
-
1149
- # Rounds down to the nearest integer value.
1791
+ # Set values at the index locations.
1150
1792
  #
1151
- # Only works on floating point Series.
1793
+ # @param idx [Object]
1794
+ # Integers representing the index locations.
1795
+ # @param value [Object]
1796
+ # Replacement values.
1152
1797
  #
1153
1798
  # @return [Series]
1154
1799
  #
1155
1800
  # @example
1156
- # s = Polars::Series.new("a", [1.12345, 2.56789, 3.901234])
1157
- # s.floor
1801
+ # s = Polars::Series.new("a", [1, 2, 3])
1802
+ # s.set_at_idx(1, 10)
1158
1803
  # # =>
1159
1804
  # # shape: (3,)
1160
- # # Series: 'a' [f64]
1805
+ # # Series: 'a' [i64]
1161
1806
  # # [
1162
- # # 1.0
1163
- # # 2.0
1164
- # # 3.0
1807
+ # # 1
1808
+ # # 10
1809
+ # # 3
1165
1810
  # # ]
1166
- def floor
1167
- Utils.wrap_s(_s.floor)
1811
+ def set_at_idx(idx, value)
1812
+ if idx.is_a?(Integer)
1813
+ idx = [idx]
1814
+ end
1815
+ if idx.length == 0
1816
+ return self
1817
+ end
1818
+
1819
+ idx = Series.new("", idx)
1820
+ if value.is_a?(Integer) || value.is_a?(Float) || Utils.bool?(value) || value.is_a?(String) || value.nil?
1821
+ value = Series.new("", [value])
1822
+
1823
+ # if we need to set more than a single value, we extend it
1824
+ if idx.length > 0
1825
+ value = value.extend_constant(value[0], idx.length - 1)
1826
+ end
1827
+ elsif !value.is_a?(Series)
1828
+ value = Series.new("", value)
1829
+ end
1830
+ _s.set_at_idx(idx._s, value._s)
1831
+ self
1168
1832
  end
1169
1833
 
1170
- # Rounds up to the nearest integer value.
1834
+ # Create an empty copy of the current Series.
1171
1835
  #
1172
- # Only works on floating point Series.
1836
+ # The copy has identical name/dtype but no data.
1173
1837
  #
1174
1838
  # @return [Series]
1175
1839
  #
1176
1840
  # @example
1177
- # s = Polars::Series.new("a", [1.12345, 2.56789, 3.901234])
1178
- # s.ceil
1841
+ # s = Polars::Series.new("a", [nil, true, false])
1842
+ # s.cleared
1179
1843
  # # =>
1180
- # # shape: (3,)
1844
+ # # shape: (0,)
1845
+ # # Series: 'a' [bool]
1846
+ # # [
1847
+ # # ]
1848
+ def cleared
1849
+ len > 0 ? limit(0) : clone
1850
+ end
1851
+
1852
+ # clone handled by initialize_copy
1853
+
1854
+ # Fill floating point NaN value with a fill value.
1855
+ #
1856
+ # @param fill_value [Object]
1857
+ # Value used to fill nan values.
1858
+ #
1859
+ # @return [Series]
1860
+ #
1861
+ # @example
1862
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, Float::NAN])
1863
+ # s.fill_nan(0)
1864
+ # # =>
1865
+ # # shape: (4,)
1866
+ # # Series: 'a' [f64]
1867
+ # # [
1868
+ # # 1.0
1869
+ # # 2.0
1870
+ # # 3.0
1871
+ # # 0.0
1872
+ # # ]
1873
+ def fill_nan(fill_value)
1874
+ super
1875
+ end
1876
+
1877
+ # Fill null values using the specified value or strategy.
1878
+ #
1879
+ # @param value [Object]
1880
+ # Value used to fill null values.
1881
+ # @param strategy [nil, "forward", "backward", "min", "max", "mean", "zero", "one"]
1882
+ # Strategy used to fill null values.
1883
+ # @param limit
1884
+ # Number of consecutive null values to fill when using the "forward" or
1885
+ # "backward" strategy.
1886
+ #
1887
+ # @return [Series]
1888
+ #
1889
+ # @example
1890
+ # s = Polars::Series.new("a", [1, 2, 3, nil])
1891
+ # s.fill_null(strategy: "forward")
1892
+ # # =>
1893
+ # # shape: (4,)
1894
+ # # Series: 'a' [i64]
1895
+ # # [
1896
+ # # 1
1897
+ # # 2
1898
+ # # 3
1899
+ # # 3
1900
+ # # ]
1901
+ #
1902
+ # @example
1903
+ # s.fill_null(strategy: "min")
1904
+ # # =>
1905
+ # # shape: (4,)
1906
+ # # Series: 'a' [i64]
1907
+ # # [
1908
+ # # 1
1909
+ # # 2
1910
+ # # 3
1911
+ # # 1
1912
+ # # ]
1913
+ #
1914
+ # @example
1915
+ # s = Polars::Series.new("b", ["x", nil, "z"])
1916
+ # s.fill_null(Polars.lit(""))
1917
+ # # =>
1918
+ # # shape: (3,)
1919
+ # # Series: 'b' [str]
1920
+ # # [
1921
+ # # "x"
1922
+ # # ""
1923
+ # # "z"
1924
+ # # ]
1925
+ def fill_null(value = nil, strategy: nil, limit: nil)
1926
+ super
1927
+ end
1928
+
1929
+ # Rounds down to the nearest integer value.
1930
+ #
1931
+ # Only works on floating point Series.
1932
+ #
1933
+ # @return [Series]
1934
+ #
1935
+ # @example
1936
+ # s = Polars::Series.new("a", [1.12345, 2.56789, 3.901234])
1937
+ # s.floor
1938
+ # # =>
1939
+ # # shape: (3,)
1940
+ # # Series: 'a' [f64]
1941
+ # # [
1942
+ # # 1.0
1943
+ # # 2.0
1944
+ # # 3.0
1945
+ # # ]
1946
+ def floor
1947
+ Utils.wrap_s(_s.floor)
1948
+ end
1949
+
1950
+ # Rounds up to the nearest integer value.
1951
+ #
1952
+ # Only works on floating point Series.
1953
+ #
1954
+ # @return [Series]
1955
+ #
1956
+ # @example
1957
+ # s = Polars::Series.new("a", [1.12345, 2.56789, 3.901234])
1958
+ # s.ceil
1959
+ # # =>
1960
+ # # shape: (3,)
1181
1961
  # # Series: 'a' [f64]
1182
1962
  # # [
1183
1963
  # # 2.0
@@ -1185,7 +1965,7 @@ module Polars
1185
1965
  # # 4.0
1186
1966
  # # ]
1187
1967
  def ceil
1188
- Utils.wrap_s(_s.ceil)
1968
+ super
1189
1969
  end
1190
1970
 
1191
1971
  # Round underlying floating point data by `decimals` digits.
@@ -1207,98 +1987,900 @@ module Polars
1207
1987
  # # 3.9
1208
1988
  # # ]
1209
1989
  def round(decimals = 0)
1210
- Utils.wrap_s(_s.round(decimals))
1990
+ super
1211
1991
  end
1212
1992
 
1213
- # def dot
1214
- # end
1993
+ # Compute the dot/inner product between two Series.
1994
+ #
1995
+ # @param other [Object]
1996
+ # Series (or array) to compute dot product with.
1997
+ #
1998
+ # @return [Numeric]
1999
+ #
2000
+ # @example
2001
+ # s = Polars::Series.new("a", [1, 2, 3])
2002
+ # s2 = Polars::Series.new("b", [4.0, 5.0, 6.0])
2003
+ # s.dot(s2)
2004
+ # # => 32.0
2005
+ def dot(other)
2006
+ if !other.is_a?(Series)
2007
+ other = Series.new(other)
2008
+ end
2009
+ if len != other.len
2010
+ n, m = len, other.len
2011
+ raise ArgumentError, "Series length mismatch: expected #{n}, found #{m}"
2012
+ end
2013
+ _s.dot(other._s)
2014
+ end
1215
2015
 
1216
- # def mode
1217
- # end
2016
+ # Compute the most occurring value(s).
2017
+ #
2018
+ # Can return multiple Values.
2019
+ #
2020
+ # @return [Series]
2021
+ #
2022
+ # @example
2023
+ # s = Polars::Series.new("a", [1, 2, 2, 3])
2024
+ # s.mode
2025
+ # # =>
2026
+ # # shape: (1,)
2027
+ # # Series: 'a' [i64]
2028
+ # # [
2029
+ # # 2
2030
+ # # ]
2031
+ def mode
2032
+ super
2033
+ end
1218
2034
 
1219
- # def sign
1220
- # end
2035
+ # Compute the element-wise indication of the sign.
2036
+ #
2037
+ # @return [Series]
2038
+ #
2039
+ # @example
2040
+ # s = Polars::Series.new("a", [-9.0, -0.0, 0.0, 4.0, nil])
2041
+ # s.sign
2042
+ # # =>
2043
+ # # shape: (5,)
2044
+ # # Series: 'a' [i64]
2045
+ # # [
2046
+ # # -1
2047
+ # # 0
2048
+ # # 0
2049
+ # # 1
2050
+ # # null
2051
+ # # ]
2052
+ def sign
2053
+ super
2054
+ end
1221
2055
 
1222
- # def sin
1223
- # end
2056
+ # Compute the element-wise value for the sine.
2057
+ #
2058
+ # @return [Series]
2059
+ #
2060
+ # @example
2061
+ # s = Polars::Series.new("a", [0.0, Math::PI / 2.0, Math::PI])
2062
+ # s.sin
2063
+ # # =>
2064
+ # # shape: (3,)
2065
+ # # Series: 'a' [f64]
2066
+ # # [
2067
+ # # 0.0
2068
+ # # 1.0
2069
+ # # 1.2246e-16
2070
+ # # ]
2071
+ def sin
2072
+ super
2073
+ end
1224
2074
 
1225
- # def cos
1226
- # end
2075
+ # Compute the element-wise value for the cosine.
2076
+ #
2077
+ # @return [Series]
2078
+ #
2079
+ # @example
2080
+ # s = Polars::Series.new("a", [0.0, Math::PI / 2.0, Math::PI])
2081
+ # s.cos
2082
+ # # =>
2083
+ # # shape: (3,)
2084
+ # # Series: 'a' [f64]
2085
+ # # [
2086
+ # # 1.0
2087
+ # # 6.1232e-17
2088
+ # # -1.0
2089
+ # # ]
2090
+ def cos
2091
+ super
2092
+ end
1227
2093
 
1228
- # def tan
1229
- # end
2094
+ # Compute the element-wise value for the tangent.
2095
+ #
2096
+ # @return [Series]
2097
+ #
2098
+ # @example
2099
+ # s = Polars::Series.new("a", [0.0, Math::PI / 2.0, Math::PI])
2100
+ # s.tan
2101
+ # # =>
2102
+ # # shape: (3,)
2103
+ # # Series: 'a' [f64]
2104
+ # # [
2105
+ # # 0.0
2106
+ # # 1.6331e16
2107
+ # # -1.2246e-16
2108
+ # # ]
2109
+ def tan
2110
+ super
2111
+ end
1230
2112
 
1231
- # def arcsin
1232
- # end
2113
+ # Compute the element-wise value for the inverse sine.
2114
+ #
2115
+ # @return [Series]
2116
+ #
2117
+ # @example
2118
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2119
+ # s.arcsin
2120
+ # # =>
2121
+ # # shape: (3,)
2122
+ # # Series: 'a' [f64]
2123
+ # # [
2124
+ # # 1.570796
2125
+ # # 0.0
2126
+ # # -1.570796
2127
+ # # ]
2128
+ def arcsin
2129
+ super
2130
+ end
1233
2131
 
1234
- # def arccos
1235
- # end
2132
+ # Compute the element-wise value for the inverse cosine.
2133
+ #
2134
+ # @return [Series]
2135
+ #
2136
+ # @example
2137
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2138
+ # s.arccos
2139
+ # # =>
2140
+ # # shape: (3,)
2141
+ # # Series: 'a' [f64]
2142
+ # # [
2143
+ # # 0.0
2144
+ # # 1.570796
2145
+ # # 3.141593
2146
+ # # ]
2147
+ def arccos
2148
+ super
2149
+ end
1236
2150
 
1237
- # def arctan
1238
- # end
2151
+ # Compute the element-wise value for the inverse tangent.
2152
+ #
2153
+ # @return [Series]
2154
+ #
2155
+ # @example
2156
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2157
+ # s.arctan
2158
+ # # =>
2159
+ # # shape: (3,)
2160
+ # # Series: 'a' [f64]
2161
+ # # [
2162
+ # # 0.785398
2163
+ # # 0.0
2164
+ # # -0.785398
2165
+ # # ]
2166
+ def arctan
2167
+ super
2168
+ end
1239
2169
 
1240
- # def arcsinh
1241
- # end
2170
+ # Compute the element-wise value for the inverse hyperbolic sine.
2171
+ #
2172
+ # @return [Series]
2173
+ #
2174
+ # @example
2175
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2176
+ # s.arcsinh
2177
+ # # =>
2178
+ # # shape: (3,)
2179
+ # # Series: 'a' [f64]
2180
+ # # [
2181
+ # # 0.881374
2182
+ # # 0.0
2183
+ # # -0.881374
2184
+ # # ]
2185
+ def arcsinh
2186
+ super
2187
+ end
1242
2188
 
1243
- # def arccosh
1244
- # end
2189
+ # Compute the element-wise value for the inverse hyperbolic cosine.
2190
+ #
2191
+ # @return [Series]
2192
+ #
2193
+ # @example
2194
+ # s = Polars::Series.new("a", [5.0, 1.0, 0.0, -1.0])
2195
+ # s.arccosh
2196
+ # # =>
2197
+ # # shape: (4,)
2198
+ # # Series: 'a' [f64]
2199
+ # # [
2200
+ # # 2.292432
2201
+ # # 0.0
2202
+ # # NaN
2203
+ # # NaN
2204
+ # # ]
2205
+ def arccosh
2206
+ super
2207
+ end
1245
2208
 
1246
- # def arctanh
1247
- # end
2209
+ # Compute the element-wise value for the inverse hyperbolic tangent.
2210
+ #
2211
+ # @return [Series]
2212
+ #
2213
+ # @example
2214
+ # s = Polars::Series.new("a", [2.0, 1.0, 0.5, 0.0, -0.5, -1.0, -1.1])
2215
+ # s.arctanh
2216
+ # # =>
2217
+ # # shape: (7,)
2218
+ # # Series: 'a' [f64]
2219
+ # # [
2220
+ # # NaN
2221
+ # # inf
2222
+ # # 0.549306
2223
+ # # 0.0
2224
+ # # -0.549306
2225
+ # # -inf
2226
+ # # NaN
2227
+ # # ]
2228
+ def arctanh
2229
+ super
2230
+ end
1248
2231
 
1249
- # def sinh
1250
- # end
2232
+ # Compute the element-wise value for the hyperbolic sine.
2233
+ #
2234
+ # @return [Series]
2235
+ #
2236
+ # @example
2237
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2238
+ # s.sinh
2239
+ # # =>
2240
+ # # shape: (3,)
2241
+ # # Series: 'a' [f64]
2242
+ # # [
2243
+ # # 1.175201
2244
+ # # 0.0
2245
+ # # -1.175201
2246
+ # # ]
2247
+ def sinh
2248
+ super
2249
+ end
1251
2250
 
1252
- # def cosh
1253
- # end
2251
+ # Compute the element-wise value for the hyperbolic cosine.
2252
+ #
2253
+ # @return [Series]
2254
+ #
2255
+ # @example
2256
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2257
+ # s.cosh
2258
+ # # =>
2259
+ # # shape: (3,)
2260
+ # # Series: 'a' [f64]
2261
+ # # [
2262
+ # # 1.543081
2263
+ # # 1.0
2264
+ # # 1.543081
2265
+ # # ]
2266
+ def cosh
2267
+ super
2268
+ end
1254
2269
 
1255
- # def tanh
1256
- # end
2270
+ # Compute the element-wise value for the hyperbolic tangent.
2271
+ #
2272
+ # @return [Series]
2273
+ #
2274
+ # @example
2275
+ # s = Polars::Series.new("a", [1.0, 0.0, -1.0])
2276
+ # s.tanh
2277
+ # # =>
2278
+ # # shape: (3,)
2279
+ # # Series: 'a' [f64]
2280
+ # # [
2281
+ # # 0.761594
2282
+ # # 0.0
2283
+ # # -0.761594
2284
+ # # ]
2285
+ def tanh
2286
+ super
2287
+ end
1257
2288
 
1258
2289
  # def apply
1259
2290
  # end
1260
2291
 
1261
- # def shift
1262
- # end
2292
+ # Shift the values by a given period.
2293
+ #
2294
+ # @param periods [Integer]
2295
+ # Number of places to shift (may be negative).
2296
+ #
2297
+ # @return [Series]
2298
+ #
2299
+ # @example
2300
+ # s = Polars::Series.new("a", [1, 2, 3])
2301
+ # s.shift(1)
2302
+ # # =>
2303
+ # # shape: (3,)
2304
+ # # Series: 'a' [i64]
2305
+ # # [
2306
+ # # null
2307
+ # # 1
2308
+ # # 2
2309
+ # # ]
2310
+ #
2311
+ # @example
2312
+ # s.shift(-1)
2313
+ # # =>
2314
+ # # shape: (3,)
2315
+ # # Series: 'a' [i64]
2316
+ # # [
2317
+ # # 2
2318
+ # # 3
2319
+ # # null
2320
+ # # ]
2321
+ def shift(periods = 1)
2322
+ super
2323
+ end
1263
2324
 
1264
- # def shift_and_fill
1265
- # end
2325
+ # Shift the values by a given period and fill the resulting null values.
2326
+ #
2327
+ # @param periods [Integer]
2328
+ # Number of places to shift (may be negative).
2329
+ # @param fill_value [Object]
2330
+ # Fill None values with the result of this expression.
2331
+ #
2332
+ # @return [Series]
2333
+ def shift_and_fill(periods, fill_value)
2334
+ super
2335
+ end
1266
2336
 
1267
- # def zip_with
1268
- # end
2337
+ # Take values from self or other based on the given mask.
2338
+ #
2339
+ # Where mask evaluates true, take values from self. Where mask evaluates false,
2340
+ # take values from other.
2341
+ #
2342
+ # @param mask [Series]
2343
+ # Boolean Series.
2344
+ # @param other [Series]
2345
+ # Series of same type.
2346
+ #
2347
+ # @return [Series]
2348
+ #
2349
+ # @example
2350
+ # s1 = Polars::Series.new([1, 2, 3, 4, 5])
2351
+ # s2 = Polars::Series.new([5, 4, 3, 2, 1])
2352
+ # s1.zip_with(s1 < s2, s2)
2353
+ # # =>
2354
+ # # shape: (5,)
2355
+ # # Series: '' [i64]
2356
+ # # [
2357
+ # # 1
2358
+ # # 2
2359
+ # # 3
2360
+ # # 2
2361
+ # # 1
2362
+ # # ]
2363
+ #
2364
+ # @example
2365
+ # mask = Polars::Series.new([true, false, true, false, true])
2366
+ # s1.zip_with(mask, s2)
2367
+ # # =>
2368
+ # # shape: (5,)
2369
+ # # Series: '' [i64]
2370
+ # # [
2371
+ # # 1
2372
+ # # 4
2373
+ # # 3
2374
+ # # 2
2375
+ # # 5
2376
+ # # ]
2377
+ def zip_with(mask, other)
2378
+ Utils.wrap_s(_s.zip_with(mask._s, other._s))
2379
+ end
1269
2380
 
1270
- # def rolling_min
1271
- # end
2381
+ # Apply a rolling min (moving min) over the values in this array.
2382
+ #
2383
+ # A window of length `window_size` will traverse the array. The values that fill
2384
+ # this window will (optionally) be multiplied with the weights given by the
2385
+ # `weight` vector. The resulting values will be aggregated to their sum.
2386
+ #
2387
+ # @param window_size [Integer]
2388
+ # The length of the window.
2389
+ # @param weights [Array]
2390
+ # An optional slice with the same length as the window that will be multiplied
2391
+ # elementwise with the values in the window.
2392
+ # @param min_periods [Integer]
2393
+ # The number of values in the window that should be non-null before computing
2394
+ # a result. If None, it will be set equal to window size.
2395
+ # @param center [Boolean]
2396
+ # Set the labels at the center of the window
2397
+ #
2398
+ # @return [Series]
2399
+ #
2400
+ # @example
2401
+ # s = Polars::Series.new("a", [100, 200, 300, 400, 500])
2402
+ # s.rolling_min(3)
2403
+ # # =>
2404
+ # # shape: (5,)
2405
+ # # Series: 'a' [i64]
2406
+ # # [
2407
+ # # null
2408
+ # # null
2409
+ # # 100
2410
+ # # 200
2411
+ # # 300
2412
+ # # ]
2413
+ def rolling_min(
2414
+ window_size,
2415
+ weights: nil,
2416
+ min_periods: nil,
2417
+ center: false
2418
+ )
2419
+ to_frame
2420
+ .select(
2421
+ Polars.col(name).rolling_min(
2422
+ window_size,
2423
+ weights: weights,
2424
+ min_periods: min_periods,
2425
+ center: center
2426
+ )
2427
+ )
2428
+ .to_series
2429
+ end
1272
2430
 
1273
- # def rolling_max
1274
- # end
2431
+ # Apply a rolling max (moving max) over the values in this array.
2432
+ #
2433
+ # A window of length `window_size` will traverse the array. The values that fill
2434
+ # this window will (optionally) be multiplied with the weights given by the
2435
+ # `weight` vector. The resulting values will be aggregated to their sum.
2436
+ #
2437
+ # @param window_size [Integer]
2438
+ # The length of the window.
2439
+ # @param weights [Array]
2440
+ # An optional slice with the same length as the window that will be multiplied
2441
+ # elementwise with the values in the window.
2442
+ # @param min_periods [Integer]
2443
+ # The number of values in the window that should be non-null before computing
2444
+ # a result. If None, it will be set equal to window size.
2445
+ # @param center [Boolean]
2446
+ # Set the labels at the center of the window
2447
+ #
2448
+ # @return [Series]
2449
+ #
2450
+ # @example
2451
+ # s = Polars::Series.new("a", [100, 200, 300, 400, 500])
2452
+ # s.rolling_max(2)
2453
+ # # =>
2454
+ # # shape: (5,)
2455
+ # # Series: 'a' [i64]
2456
+ # # [
2457
+ # # null
2458
+ # # 200
2459
+ # # 300
2460
+ # # 400
2461
+ # # 500
2462
+ # # ]
2463
+ def rolling_max(
2464
+ window_size,
2465
+ weights: nil,
2466
+ min_periods: nil,
2467
+ center: false
2468
+ )
2469
+ to_frame
2470
+ .select(
2471
+ Polars.col(name).rolling_max(
2472
+ window_size,
2473
+ weights: weights,
2474
+ min_periods: min_periods,
2475
+ center: center
2476
+ )
2477
+ )
2478
+ .to_series
2479
+ end
1275
2480
 
1276
- # def rolling_mean
1277
- # end
2481
+ # Apply a rolling mean (moving mean) over the values in this array.
2482
+ #
2483
+ # A window of length `window_size` will traverse the array. The values that fill
2484
+ # this window will (optionally) be multiplied with the weights given by the
2485
+ # `weight` vector. The resulting values will be aggregated to their sum.
2486
+ #
2487
+ # @param window_size [Integer]
2488
+ # The length of the window.
2489
+ # @param weights [Array]
2490
+ # An optional slice with the same length as the window that will be multiplied
2491
+ # elementwise with the values in the window.
2492
+ # @param min_periods [Integer]
2493
+ # The number of values in the window that should be non-null before computing
2494
+ # a result. If None, it will be set equal to window size.
2495
+ # @param center [Boolean]
2496
+ # Set the labels at the center of the window
2497
+ #
2498
+ # @return [Series]
2499
+ #
2500
+ # @example
2501
+ # s = Polars::Series.new("a", [100, 200, 300, 400, 500])
2502
+ # s.rolling_mean(2)
2503
+ # # =>
2504
+ # # shape: (5,)
2505
+ # # Series: 'a' [f64]
2506
+ # # [
2507
+ # # null
2508
+ # # 150.0
2509
+ # # 250.0
2510
+ # # 350.0
2511
+ # # 450.0
2512
+ # # ]
2513
+ def rolling_mean(
2514
+ window_size,
2515
+ weights: nil,
2516
+ min_periods: nil,
2517
+ center: false
2518
+ )
2519
+ to_frame
2520
+ .select(
2521
+ Polars.col(name).rolling_mean(
2522
+ window_size,
2523
+ weights: weights,
2524
+ min_periods: min_periods,
2525
+ center: center
2526
+ )
2527
+ )
2528
+ .to_series
2529
+ end
1278
2530
 
1279
- # def rolling_sum
1280
- # end
2531
+ # Apply a rolling sum (moving sum) over the values in this array.
2532
+ #
2533
+ # A window of length `window_size` will traverse the array. The values that fill
2534
+ # this window will (optionally) be multiplied with the weights given by the
2535
+ # `weight` vector. The resulting values will be aggregated to their sum.
2536
+ #
2537
+ # @param window_size [Integer]
2538
+ # The length of the window.
2539
+ # @param weights [Array]
2540
+ # An optional slice with the same length as the window that will be multiplied
2541
+ # elementwise with the values in the window.
2542
+ # @param min_periods [Integer]
2543
+ # The number of values in the window that should be non-null before computing
2544
+ # a result. If None, it will be set equal to window size.
2545
+ # @param center [Boolean]
2546
+ # Set the labels at the center of the window
2547
+ #
2548
+ # @return [Series]
2549
+ #
2550
+ # @example
2551
+ # s = Polars::Series.new("a", [1, 2, 3, 4, 5])
2552
+ # s.rolling_sum(2)
2553
+ # # =>
2554
+ # # shape: (5,)
2555
+ # # Series: 'a' [i64]
2556
+ # # [
2557
+ # # null
2558
+ # # 3
2559
+ # # 5
2560
+ # # 7
2561
+ # # 9
2562
+ # # ]
2563
+ def rolling_sum(
2564
+ window_size,
2565
+ weights: nil,
2566
+ min_periods: nil,
2567
+ center: false
2568
+ )
2569
+ to_frame
2570
+ .select(
2571
+ Polars.col(name).rolling_sum(
2572
+ window_size,
2573
+ weights: weights,
2574
+ min_periods: min_periods,
2575
+ center: center
2576
+ )
2577
+ )
2578
+ .to_series
2579
+ end
1281
2580
 
1282
- # def rolling_std
1283
- # end
2581
+ # Compute a rolling std dev.
2582
+ #
2583
+ # A window of length `window_size` will traverse the array. The values that fill
2584
+ # this window will (optionally) be multiplied with the weights given by the
2585
+ # `weight` vector. The resulting values will be aggregated to their sum.
2586
+ #
2587
+ # @param window_size [Integer]
2588
+ # The length of the window.
2589
+ # @param weights [Array]
2590
+ # An optional slice with the same length as the window that will be multiplied
2591
+ # elementwise with the values in the window.
2592
+ # @param min_periods [Integer]
2593
+ # The number of values in the window that should be non-null before computing
2594
+ # a result. If None, it will be set equal to window size.
2595
+ # @param center [Boolean]
2596
+ # Set the labels at the center of the window
2597
+ #
2598
+ # @return [Series]
2599
+ #
2600
+ # @example
2601
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, 4.0, 6.0, 8.0])
2602
+ # s.rolling_std(3)
2603
+ # # =>
2604
+ # # shape: (6,)
2605
+ # # Series: 'a' [f64]
2606
+ # # [
2607
+ # # null
2608
+ # # null
2609
+ # # 1.0
2610
+ # # 1.0
2611
+ # # 1.527525
2612
+ # # 2.0
2613
+ # # ]
2614
+ def rolling_std(
2615
+ window_size,
2616
+ weights: nil,
2617
+ min_periods: nil,
2618
+ center: false
2619
+ )
2620
+ to_frame
2621
+ .select(
2622
+ Polars.col(name).rolling_std(
2623
+ window_size,
2624
+ weights: weights,
2625
+ min_periods: min_periods,
2626
+ center: center
2627
+ )
2628
+ )
2629
+ .to_series
2630
+ end
1284
2631
 
1285
- # def rolling_var
1286
- # end
2632
+ # Compute a rolling variance.
2633
+ #
2634
+ # A window of length `window_size` will traverse the array. The values that fill
2635
+ # this window will (optionally) be multiplied with the weights given by the
2636
+ # `weight` vector. The resulting values will be aggregated to their sum.
2637
+ #
2638
+ # @param window_size [Integer]
2639
+ # The length of the window.
2640
+ # @param weights [Array]
2641
+ # An optional slice with the same length as the window that will be multiplied
2642
+ # elementwise with the values in the window.
2643
+ # @param min_periods [Integer]
2644
+ # The number of values in the window that should be non-null before computing
2645
+ # a result. If None, it will be set equal to window size.
2646
+ # @param center [Boolean]
2647
+ # Set the labels at the center of the window
2648
+ #
2649
+ # @return [Series]
2650
+ #
2651
+ # @example
2652
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, 4.0, 6.0, 8.0])
2653
+ # s.rolling_var(3)
2654
+ # # =>
2655
+ # # shape: (6,)
2656
+ # # Series: 'a' [f64]
2657
+ # # [
2658
+ # # null
2659
+ # # null
2660
+ # # 1.0
2661
+ # # 1.0
2662
+ # # 2.333333
2663
+ # # 4.0
2664
+ # # ]
2665
+ def rolling_var(
2666
+ window_size,
2667
+ weights: nil,
2668
+ min_periods: nil,
2669
+ center: false
2670
+ )
2671
+ to_frame
2672
+ .select(
2673
+ Polars.col(name).rolling_var(
2674
+ window_size,
2675
+ weights: weights,
2676
+ min_periods: min_periods,
2677
+ center: center
2678
+ )
2679
+ )
2680
+ .to_series
2681
+ end
1287
2682
 
1288
2683
  # def rolling_apply
1289
2684
  # end
1290
2685
 
1291
- # def rolling_median
1292
- # end
2686
+ # Compute a rolling median.
2687
+ #
2688
+ # @param window_size [Integer]
2689
+ # The length of the window.
2690
+ # @param weights [Array]
2691
+ # An optional slice with the same length as the window that will be multiplied
2692
+ # elementwise with the values in the window.
2693
+ # @param min_periods [Integer]
2694
+ # The number of values in the window that should be non-null before computing
2695
+ # a result. If None, it will be set equal to window size.
2696
+ # @param center [Boolean]
2697
+ # Set the labels at the center of the window
2698
+ #
2699
+ # @return [Series]
2700
+ #
2701
+ # @example
2702
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, 4.0, 6.0, 8.0])
2703
+ # s.rolling_median(3)
2704
+ # # =>
2705
+ # # shape: (6,)
2706
+ # # Series: 'a' [f64]
2707
+ # # [
2708
+ # # null
2709
+ # # null
2710
+ # # 2.0
2711
+ # # 3.0
2712
+ # # 4.0
2713
+ # # 6.0
2714
+ # # ]
2715
+ def rolling_median(
2716
+ window_size,
2717
+ weights: nil,
2718
+ min_periods: nil,
2719
+ center: false
2720
+ )
2721
+ if min_periods.nil?
2722
+ min_periods = window_size
2723
+ end
1293
2724
 
1294
- # def rolling_quantile
1295
- # end
2725
+ to_frame
2726
+ .select(
2727
+ Polars.col(name).rolling_median(
2728
+ window_size,
2729
+ weights: weights,
2730
+ min_periods: min_periods,
2731
+ center: center
2732
+ )
2733
+ )
2734
+ .to_series
2735
+ end
2736
+
2737
+ # Compute a rolling quantile.
2738
+ #
2739
+ # @param quantile [Float]
2740
+ # Quantile between 0.0 and 1.0.
2741
+ # @param interpolation ["nearest", "higher", "lower", "midpoint", "linear"]
2742
+ # Interpolation method.
2743
+ # @param window_size [Integer]
2744
+ # The length of the window.
2745
+ # @param weights [Array]
2746
+ # An optional slice with the same length as the window that will be multiplied
2747
+ # elementwise with the values in the window.
2748
+ # @param min_periods [Integer]
2749
+ # The number of values in the window that should be non-null before computing
2750
+ # a result. If None, it will be set equal to window size.
2751
+ # @param center [Boolean]
2752
+ # Set the labels at the center of the window
2753
+ #
2754
+ # @return [Series]
2755
+ #
2756
+ # @example
2757
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, 4.0, 6.0, 8.0])
2758
+ # s.rolling_quantile(0.33, window_size: 3)
2759
+ # # =>
2760
+ # # shape: (6,)
2761
+ # # Series: 'a' [f64]
2762
+ # # [
2763
+ # # null
2764
+ # # null
2765
+ # # 1.0
2766
+ # # 2.0
2767
+ # # 3.0
2768
+ # # 4.0
2769
+ # # ]
2770
+ #
2771
+ # @example
2772
+ # s.rolling_quantile(0.33, interpolation: "linear", window_size: 3)
2773
+ # # =>
2774
+ # # shape: (6,)
2775
+ # # Series: 'a' [f64]
2776
+ # # [
2777
+ # # null
2778
+ # # null
2779
+ # # 1.66
2780
+ # # 2.66
2781
+ # # 3.66
2782
+ # # 5.32
2783
+ # # ]
2784
+ def rolling_quantile(
2785
+ quantile,
2786
+ interpolation: "nearest",
2787
+ window_size: 2,
2788
+ weights: nil,
2789
+ min_periods: nil,
2790
+ center: false
2791
+ )
2792
+ if min_periods.nil?
2793
+ min_periods = window_size
2794
+ end
2795
+
2796
+ to_frame
2797
+ .select(
2798
+ Polars.col(name).rolling_quantile(
2799
+ quantile,
2800
+ interpolation: interpolation,
2801
+ window_size: window_size,
2802
+ weights: weights,
2803
+ min_periods: min_periods,
2804
+ center: center
2805
+ )
2806
+ )
2807
+ .to_series
2808
+ end
2809
+
2810
+ # Compute a rolling skew.
2811
+ #
2812
+ # @param window_size [Integer]
2813
+ # Integer size of the rolling window.
2814
+ # @param bias [Boolean]
2815
+ # If false, the calculations are corrected for statistical bias.
2816
+ #
2817
+ # @return [Series]
2818
+ #
2819
+ # @example
2820
+ # s = Polars::Series.new("a", [1.0, 2.0, 3.0, 4.0, 6.0, 8.0])
2821
+ # s.rolling_skew(3)
2822
+ # # =>
2823
+ # # shape: (6,)
2824
+ # # Series: 'a' [f64]
2825
+ # # [
2826
+ # # null
2827
+ # # null
2828
+ # # 0.0
2829
+ # # 0.0
2830
+ # # 0.381802
2831
+ # # 0.0
2832
+ # # ]
2833
+ def rolling_skew(window_size, bias: true)
2834
+ super
2835
+ end
2836
+
2837
+ # Sample from this Series.
2838
+ #
2839
+ # @param n [Integer]
2840
+ # Number of items to return. Cannot be used with `frac`. Defaults to 1 if
2841
+ # `frac` is None.
2842
+ # @param frac [Float]
2843
+ # Fraction of items to return. Cannot be used with `n`.
2844
+ # @param with_replacement [Boolean]
2845
+ # Allow values to be sampled more than once.
2846
+ # @param shuffle [Boolean]
2847
+ # Shuffle the order of sampled data points.
2848
+ # @param seed [Integer]
2849
+ # Seed for the random number generator. If set to None (default), a random
2850
+ # seed is used.
2851
+ #
2852
+ # @return [Series]
2853
+ #
2854
+ # @example
2855
+ # s = Polars::Series.new("a", [1, 2, 3, 4, 5])
2856
+ # s.sample(n: 2, seed: 0)
2857
+ # # =>
2858
+ # # shape: (2,)
2859
+ # # Series: 'a' [i64]
2860
+ # # [
2861
+ # # 1
2862
+ # # 5
2863
+ # # ]
2864
+ def sample(
2865
+ n: nil,
2866
+ frac: nil,
2867
+ with_replacement: false,
2868
+ shuffle: false,
2869
+ seed: nil
2870
+ )
2871
+ if !n.nil? && !frac.nil?
2872
+ raise ArgumentError, "cannot specify both `n` and `frac`"
2873
+ end
1296
2874
 
1297
- # def rolling_skew
1298
- # end
2875
+ if n.nil? && !frac.nil?
2876
+ return Utils.wrap_s(_s.sample_frac(frac, with_replacement, shuffle, seed))
2877
+ end
1299
2878
 
1300
- # def sample
1301
- # end
2879
+ if n.nil?
2880
+ n = 1
2881
+ end
2882
+ Utils.wrap_s(_s.sample_n(n, with_replacement, shuffle, seed))
2883
+ end
1302
2884
 
1303
2885
  # Get a boolean mask of the local maximum peaks.
1304
2886
  #
@@ -1354,62 +2936,384 @@ module Polars
1354
2936
  _s.n_unique
1355
2937
  end
1356
2938
 
1357
- # def shrink_to_fit
1358
- # end
2939
+ # Shrink Series memory usage.
2940
+ #
2941
+ # Shrinks the underlying array capacity to exactly fit the actual data.
2942
+ # (Note that this function does not change the Series data type).
2943
+ #
2944
+ # @return [Series]
2945
+ def shrink_to_fit(in_place: false)
2946
+ if in_place
2947
+ _s.shrink_to_fit
2948
+ self
2949
+ else
2950
+ series = clone
2951
+ series._s.shrink_to_fit
2952
+ series
2953
+ end
2954
+ end
1359
2955
 
1360
2956
  # def _hash
1361
2957
  # end
1362
2958
 
1363
- # def reinterpret
1364
- # end
2959
+ # Reinterpret the underlying bits as a signed/unsigned integer.
2960
+ #
2961
+ # This operation is only allowed for 64bit integers. For lower bits integers,
2962
+ # you can safely use that cast operation.
2963
+ #
2964
+ # @param signed [Boolean]
2965
+ # If true, reinterpret as `:i64`. Otherwise, reinterpret as `:u64`.
2966
+ #
2967
+ # @return [Series]
2968
+ def reinterpret(signed: true)
2969
+ super
2970
+ end
1365
2971
 
1366
- # def interpolate
1367
- # end
2972
+ # Interpolate intermediate values. The interpolation method is linear.
2973
+ #
2974
+ # @return [Series]
2975
+ #
2976
+ # @example
2977
+ # s = Polars::Series.new("a", [1, 2, nil, nil, 5])
2978
+ # s.interpolate
2979
+ # # =>
2980
+ # # shape: (5,)
2981
+ # # Series: 'a' [i64]
2982
+ # # [
2983
+ # # 1
2984
+ # # 2
2985
+ # # 3
2986
+ # # 4
2987
+ # # 5
2988
+ # # ]
2989
+ def interpolate
2990
+ super
2991
+ end
1368
2992
 
1369
- # def abs
1370
- # end
2993
+ # Compute absolute values.
2994
+ #
2995
+ # @return [Series]
2996
+ def abs
2997
+ super
2998
+ end
1371
2999
 
1372
- # def rank
1373
- # end
3000
+ # Assign ranks to data, dealing with ties appropriately.
3001
+ #
3002
+ # @param method ["average", "min", "max", "dense", "ordinal", "random"]
3003
+ # The method used to assign ranks to tied elements.
3004
+ # The following methods are available (default is 'average'):
3005
+ #
3006
+ # - 'average' : The average of the ranks that would have been assigned to
3007
+ # all the tied values is assigned to each value.
3008
+ # - 'min' : The minimum of the ranks that would have been assigned to all
3009
+ # the tied values is assigned to each value. (This is also referred to
3010
+ # as "competition" ranking.)
3011
+ # - 'max' : The maximum of the ranks that would have been assigned to all
3012
+ # the tied values is assigned to each value.
3013
+ # - 'dense' : Like 'min', but the rank of the next highest element is
3014
+ # assigned the rank immediately after those assigned to the tied
3015
+ # elements.
3016
+ # - 'ordinal' : All values are given a distinct rank, corresponding to
3017
+ # the order that the values occur in the Series.
3018
+ # - 'random' : Like 'ordinal', but the rank for ties is not dependent
3019
+ # on the order that the values occur in the Series.
3020
+ # @param reverse [Boolean]
3021
+ # Reverse the operation.
3022
+ #
3023
+ # @return [Series]
3024
+ #
3025
+ # @example The 'average' method:
3026
+ # s = Polars::Series.new("a", [3, 6, 1, 1, 6])
3027
+ # s.rank
3028
+ # # =>
3029
+ # # shape: (5,)
3030
+ # # Series: 'a' [f32]
3031
+ # # [
3032
+ # # 3.0
3033
+ # # 4.5
3034
+ # # 1.5
3035
+ # # 1.5
3036
+ # # 4.5
3037
+ # # ]
3038
+ #
3039
+ # @example The 'ordinal' method:
3040
+ # s = Polars::Series.new("a", [3, 6, 1, 1, 6])
3041
+ # s.rank(method: "ordinal")
3042
+ # # =>
3043
+ # # shape: (5,)
3044
+ # # Series: 'a' [u32]
3045
+ # # [
3046
+ # # 3
3047
+ # # 4
3048
+ # # 1
3049
+ # # 2
3050
+ # # 5
3051
+ # # ]
3052
+ def rank(method: "average", reverse: false)
3053
+ super
3054
+ end
1374
3055
 
1375
- # def diff
1376
- # end
3056
+ # Calculate the n-th discrete difference.
3057
+ #
3058
+ # @param n [Integer]
3059
+ # Number of slots to shift.
3060
+ # @param null_behavior ["ignore", "drop"]
3061
+ # How to handle null values.
3062
+ #
3063
+ # @return [Series]
3064
+ def diff(n: 1, null_behavior: "ignore")
3065
+ super
3066
+ end
1377
3067
 
1378
- # def pct_change
1379
- # end
3068
+ # Computes percentage change between values.
3069
+ #
3070
+ # Percentage change (as fraction) between current element and most-recent
3071
+ # non-null element at least `n` period(s) before the current element.
3072
+ #
3073
+ # Computes the change from the previous row by default.
3074
+ #
3075
+ # @param n [Integer]
3076
+ # periods to shift for forming percent change.
3077
+ #
3078
+ # @return [Series]
3079
+ #
3080
+ # @example
3081
+ # Polars::Series.new(0..9).pct_change
3082
+ # # =>
3083
+ # # shape: (10,)
3084
+ # # Series: '' [f64]
3085
+ # # [
3086
+ # # null
3087
+ # # inf
3088
+ # # 1.0
3089
+ # # 0.5
3090
+ # # 0.333333
3091
+ # # 0.25
3092
+ # # 0.2
3093
+ # # 0.166667
3094
+ # # 0.142857
3095
+ # # 0.125
3096
+ # # ]
3097
+ #
3098
+ # @example
3099
+ # Polars::Series.new([1, 2, 4, 8, 16, 32, 64, 128, 256, 512]).pct_change(n: 2)
3100
+ # # =>
3101
+ # # shape: (10,)
3102
+ # # Series: '' [f64]
3103
+ # # [
3104
+ # # null
3105
+ # # null
3106
+ # # 3.0
3107
+ # # 3.0
3108
+ # # 3.0
3109
+ # # 3.0
3110
+ # # 3.0
3111
+ # # 3.0
3112
+ # # 3.0
3113
+ # # 3.0
3114
+ # # ]
3115
+ def pct_change(n: 1)
3116
+ super
3117
+ end
1380
3118
 
1381
- # def skew
1382
- # end
3119
+ # Compute the sample skewness of a data set.
3120
+ #
3121
+ # For normally distributed data, the skewness should be about zero. For
3122
+ # unimodal continuous distributions, a skewness value greater than zero means
3123
+ # that there is more weight in the right tail of the distribution. The
3124
+ # function `skewtest` can be used to determine if the skewness value
3125
+ # is close enough to zero, statistically speaking.
3126
+ #
3127
+ # @param bias [Boolean]
3128
+ # If `false`, the calculations are corrected for statistical bias.
3129
+ #
3130
+ # @return [Float, nil]
3131
+ def skew(bias: true)
3132
+ _s.skew(bias)
3133
+ end
1383
3134
 
1384
- # def kurtosis
1385
- # end
3135
+ # Compute the kurtosis (Fisher or Pearson) of a dataset.
3136
+ #
3137
+ # Kurtosis is the fourth central moment divided by the square of the
3138
+ # variance. If Fisher's definition is used, then 3.0 is subtracted from
3139
+ # the result to give 0.0 for a normal distribution.
3140
+ # If bias is false, then the kurtosis is calculated using k statistics to
3141
+ # eliminate bias coming from biased moment estimators
3142
+ #
3143
+ # @param fisher [Boolean]
3144
+ # If `true`, Fisher's definition is used (normal ==> 0.0). If `false`,
3145
+ # Pearson's definition is used (normal ==> 3.0).
3146
+ # @param bias [Boolean]
3147
+ # If `false`, the calculations are corrected for statistical bias.
3148
+ #
3149
+ # @return [Float, nil]
3150
+ def kurtosis(fisher: true, bias: true)
3151
+ _s.kurtosis(fisher, bias)
3152
+ end
1386
3153
 
1387
- # def clip
1388
- # end
3154
+ # Clip (limit) the values in an array to a `min` and `max` boundary.
3155
+ #
3156
+ # Only works for numerical types.
3157
+ #
3158
+ # If you want to clip other dtypes, consider writing a "when, then, otherwise"
3159
+ # expression. See {#when} for more information.
3160
+ #
3161
+ # @param min_val [Numeric]
3162
+ # Minimum value.
3163
+ # @param max_val [Numeric]
3164
+ # Maximum value.
3165
+ #
3166
+ # @return [Series]
3167
+ #
3168
+ # @example
3169
+ # s = Polars::Series.new("foo", [-50, 5, nil, 50])
3170
+ # s.clip(1, 10)
3171
+ # # =>
3172
+ # # shape: (4,)
3173
+ # # Series: 'foo' [i64]
3174
+ # # [
3175
+ # # 1
3176
+ # # 5
3177
+ # # null
3178
+ # # 10
3179
+ # # ]
3180
+ def clip(min_val, max_val)
3181
+ super
3182
+ end
1389
3183
 
1390
- # def clip_min
1391
- # end
3184
+ # Clip (limit) the values in an array to a `min` boundary.
3185
+ #
3186
+ # Only works for numerical types.
3187
+ #
3188
+ # If you want to clip other dtypes, consider writing a "when, then, otherwise"
3189
+ # expression. See {#when} for more information.
3190
+ #
3191
+ # @param min_val [Numeric]
3192
+ # Minimum value.
3193
+ #
3194
+ # @return [Series]
3195
+ def clip_min(min_val)
3196
+ super
3197
+ end
1392
3198
 
1393
- # def clip_max
1394
- # end
3199
+ # Clip (limit) the values in an array to a `max` boundary.
3200
+ #
3201
+ # Only works for numerical types.
3202
+ #
3203
+ # If you want to clip other dtypes, consider writing a "when, then, otherwise"
3204
+ # expression. See {#when} for more information.
3205
+ #
3206
+ # @param max_val [Numeric]
3207
+ # Maximum value.
3208
+ #
3209
+ # @return [Series]
3210
+ def clip_max(max_val)
3211
+ super
3212
+ end
1395
3213
 
1396
- # def reshape
1397
- # end
3214
+ # Reshape this Series to a flat Series or a Series of Lists.
3215
+ #
3216
+ # @param dims [Array]
3217
+ # Tuple of the dimension sizes. If a -1 is used in any of the dimensions, that
3218
+ # dimension is inferred.
3219
+ #
3220
+ # @return [Series]
3221
+ def reshape(dims)
3222
+ super
3223
+ end
1398
3224
 
1399
- # def shuffle
1400
- # end
3225
+ # Shuffle the contents of this Series.
3226
+ #
3227
+ # @param seed [Integer, nil]
3228
+ # Seed for the random number generator.
3229
+ #
3230
+ # @return [Series]
3231
+ #
3232
+ # @example
3233
+ # s = Polars::Series.new("a", [1, 2, 3])
3234
+ # s.shuffle(seed: 1)
3235
+ # # =>
3236
+ # # shape: (3,)
3237
+ # # Series: 'a' [i64]
3238
+ # # [
3239
+ # # 2
3240
+ # # 1
3241
+ # # 3
3242
+ # # ]
3243
+ def shuffle(seed: nil)
3244
+ super
3245
+ end
1401
3246
 
1402
- # def ewm_mean
1403
- # end
3247
+ # Exponentially-weighted moving average.
3248
+ #
3249
+ # @return [Series]
3250
+ def ewm_mean(
3251
+ com: nil,
3252
+ span: nil,
3253
+ half_life: nil,
3254
+ alpha: nil,
3255
+ adjust: true,
3256
+ min_periods: 1
3257
+ )
3258
+ super
3259
+ end
1404
3260
 
1405
- # def ewm_std
1406
- # end
3261
+ # Exponentially-weighted moving standard deviation.
3262
+ #
3263
+ # @return [Series]
3264
+ def ewm_std(
3265
+ com: nil,
3266
+ span: nil,
3267
+ half_life: nil,
3268
+ alpha: nil,
3269
+ adjust: true,
3270
+ bias: false,
3271
+ min_periods: 1
3272
+ )
3273
+ super
3274
+ end
1407
3275
 
1408
- # def ewm_var
1409
- # end
3276
+ # Exponentially-weighted moving variance.
3277
+ #
3278
+ # @return [Series]
3279
+ def ewm_var(
3280
+ com: nil,
3281
+ span: nil,
3282
+ half_life: nil,
3283
+ alpha: nil,
3284
+ adjust: true,
3285
+ bias: false,
3286
+ min_periods: 1
3287
+ )
3288
+ super
3289
+ end
1410
3290
 
1411
- # def extend_constant
1412
- # end
3291
+ # Extend the Series with given number of values.
3292
+ #
3293
+ # @param value [Object]
3294
+ # The value to extend the Series with. This value may be `nil` to fill with
3295
+ # nulls.
3296
+ # @param n [Integer]
3297
+ # The number of values to extend.
3298
+ #
3299
+ # @return [Series]
3300
+ #
3301
+ # @example
3302
+ # s = Polars::Series.new("a", [1, 2, 3])
3303
+ # s.extend_constant(99, 2)
3304
+ # # =>
3305
+ # # shape: (5,)
3306
+ # # Series: 'a' [i64]
3307
+ # # [
3308
+ # # 1
3309
+ # # 2
3310
+ # # 3
3311
+ # # 99
3312
+ # # 99
3313
+ # # ]
3314
+ def extend_constant(value, n)
3315
+ super
3316
+ end
1413
3317
 
1414
3318
  # Flags the Series as sorted.
1415
3319
  #
@@ -1432,26 +3336,57 @@ module Polars
1432
3336
  Utils.wrap_s(_s.set_sorted(reverse))
1433
3337
  end
1434
3338
 
1435
- # def new_from_index
1436
- # end
3339
+ # Create a new Series filled with values from the given index.
3340
+ #
3341
+ # @return [Series]
3342
+ def new_from_index(index, length)
3343
+ Utils.wrap_s(_s.new_from_index(index, length))
3344
+ end
1437
3345
 
1438
- # def shrink_dtype
1439
- # end
3346
+ # Shrink numeric columns to the minimal required datatype.
3347
+ #
3348
+ # Shrink to the dtype needed to fit the extrema of this Series.
3349
+ # This can be used to reduce memory pressure.
3350
+ #
3351
+ # @return [Series]
3352
+ def shrink_dtype
3353
+ super
3354
+ end
1440
3355
 
1441
- # def arr
1442
- # end
3356
+ # Create an object namespace of all list related methods.
3357
+ #
3358
+ # @return [ListNameSpace]
3359
+ def arr
3360
+ ListNameSpace.new(self)
3361
+ end
1443
3362
 
1444
- # def cat
1445
- # end
3363
+ # Create an object namespace of all categorical related methods.
3364
+ #
3365
+ # @return [CatNameSpace]
3366
+ def cat
3367
+ CatNameSpace.new(self)
3368
+ end
1446
3369
 
1447
- # def dt
1448
- # end
3370
+ # Create an object namespace of all datetime related methods.
3371
+ #
3372
+ # @return [DateTimeNameSpace]
3373
+ def dt
3374
+ DateTimeNameSpace.new(self)
3375
+ end
1449
3376
 
1450
- # def str
1451
- # end
3377
+ # Create an object namespace of all string related methods.
3378
+ #
3379
+ # @return [StringNameSpace]
3380
+ def str
3381
+ StringNameSpace.new(self)
3382
+ end
1452
3383
 
1453
- # def struct
1454
- # end
3384
+ # Create an object namespace of all struct related methods.
3385
+ #
3386
+ # @return [StructNameSpace]
3387
+ def struct
3388
+ StructNameSpace.new(self)
3389
+ end
1455
3390
 
1456
3391
  private
1457
3392
 
@@ -1460,8 +3395,47 @@ module Polars
1460
3395
  self._s = _s._clone
1461
3396
  end
1462
3397
 
3398
+ def coerce(other)
3399
+ if other.is_a?(Numeric)
3400
+ # TODO improve
3401
+ series = to_frame.select(Polars.lit(other)).to_series
3402
+ [series, self]
3403
+ else
3404
+ raise TypeError, "#{self.class} can't be coerced into #{other.class}"
3405
+ end
3406
+ end
3407
+
3408
+ def _comp(other, op)
3409
+ if other.is_a?(Series)
3410
+ return Utils.wrap_s(_s.send(op, other._s))
3411
+ end
3412
+
3413
+ if dtype == :str
3414
+ raise Todo
3415
+ end
3416
+ Utils.wrap_s(_s.send("#{op}_#{dtype}", other))
3417
+ end
3418
+
3419
+ def _arithmetic(other, op)
3420
+ if other.is_a?(Expr)
3421
+ other = to_frame.select(other).to_series
3422
+ end
3423
+ if other.is_a?(Series)
3424
+ return Utils.wrap_s(_s.send(op, other._s))
3425
+ end
3426
+
3427
+ raise Todo
3428
+ end
3429
+
3430
+ def series_to_rbseries(name, values)
3431
+ # should not be in-place?
3432
+ values.rename(name, in_place: true)
3433
+ values._s
3434
+ end
3435
+
1463
3436
  def sequence_to_rbseries(name, values, dtype: nil, strict: true, dtype_if_empty: nil)
1464
3437
  ruby_dtype = nil
3438
+ nested_dtype = nil
1465
3439
 
1466
3440
  if (values.nil? || values.empty?) && dtype.nil?
1467
3441
  if dtype_if_empty
@@ -1470,7 +3444,7 @@ module Polars
1470
3444
  dtype = dtype_if_empty
1471
3445
  else
1472
3446
  # default to Float32 type
1473
- dtype = "f32"
3447
+ dtype = :f32
1474
3448
  end
1475
3449
  end
1476
3450
 
@@ -1479,8 +3453,7 @@ module Polars
1479
3453
  rb_temporal_types << DateTime if defined?(DateTime)
1480
3454
  rb_temporal_types << Time if defined?(Time)
1481
3455
 
1482
- # _get_first_non_none
1483
- value = values.find { |v| !v.nil? }
3456
+ value = _get_first_non_none(values)
1484
3457
 
1485
3458
  if !dtype.nil? && Utils.is_polars_dtype(dtype) && ruby_dtype.nil?
1486
3459
  constructor = polars_type_to_constructor(dtype)
@@ -1504,7 +3477,45 @@ module Polars
1504
3477
  # dtype = rb_type_to_dtype(dtype)
1505
3478
  # end
1506
3479
 
1507
- raise Todo
3480
+ if ruby_dtype == Date
3481
+ RbSeries.new_opt_date(name, values, strict)
3482
+ elsif ruby_dtype == Time
3483
+ RbSeries.new_opt_datetime(name, values, strict)
3484
+ elsif ruby_dtype == DateTime
3485
+ RbSeries.new_opt_datetime(name, values.map(&:to_time), strict)
3486
+ else
3487
+ raise Todo
3488
+ end
3489
+ elsif ruby_dtype == Array
3490
+ if nested_dtype.nil?
3491
+ nested_value = _get_first_non_none(value)
3492
+ nested_dtype = nested_value.nil? ? Float : nested_value.class
3493
+ end
3494
+
3495
+ if nested_dtype == Array
3496
+ raise Todo
3497
+ end
3498
+
3499
+ if value.is_a?(Array)
3500
+ count = 0
3501
+ equal_to_inner = true
3502
+ values.each do |lst|
3503
+ lst.each do |vl|
3504
+ equal_to_inner = vl.class == nested_dtype
3505
+ if !equal_to_inner || count > 50
3506
+ break
3507
+ end
3508
+ count += 1
3509
+ end
3510
+ end
3511
+ if equal_to_inner
3512
+ dtype = Utils.rb_type_to_dtype(nested_dtype)
3513
+ # TODO rescue and fallback to new_object
3514
+ return RbSeries.new_list(name, values, dtype)
3515
+ end
3516
+ end
3517
+
3518
+ RbSeries.new_object(name, values, strict)
1508
3519
  else
1509
3520
  constructor = rb_type_to_constructor(value.class)
1510
3521
  constructor.call(name, values, strict)
@@ -1544,8 +3555,11 @@ module Polars
1544
3555
  def rb_type_to_constructor(dtype)
1545
3556
  RB_TYPE_TO_CONSTRUCTOR.fetch(dtype)
1546
3557
  rescue KeyError
1547
- # RbSeries.method(:new_object)
1548
- raise ArgumentError, "Cannot determine type"
3558
+ RbSeries.method(:new_object)
3559
+ end
3560
+
3561
+ def _get_first_non_none(values)
3562
+ values.find { |v| !v.nil? }
1549
3563
  end
1550
3564
  end
1551
3565
  end