polars-df 0.15.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +274 -0
  3. data/Cargo.lock +1465 -867
  4. data/Cargo.toml +3 -0
  5. data/LICENSE.txt +2 -2
  6. data/README.md +87 -37
  7. data/ext/polars/Cargo.toml +47 -16
  8. data/ext/polars/src/c_api/allocator.rs +7 -0
  9. data/ext/polars/src/c_api/mod.rs +1 -0
  10. data/ext/polars/src/catalog/mod.rs +1 -0
  11. data/ext/polars/src/catalog/unity.rs +470 -0
  12. data/ext/polars/src/conversion/any_value.rs +99 -84
  13. data/ext/polars/src/conversion/categorical.rs +30 -0
  14. data/ext/polars/src/conversion/chunked_array.rs +71 -62
  15. data/ext/polars/src/conversion/datetime.rs +63 -0
  16. data/ext/polars/src/conversion/mod.rs +796 -312
  17. data/ext/polars/src/dataframe/construction.rs +6 -18
  18. data/ext/polars/src/dataframe/export.rs +30 -39
  19. data/ext/polars/src/dataframe/general.rs +294 -362
  20. data/ext/polars/src/dataframe/io.rs +33 -150
  21. data/ext/polars/src/dataframe/map.rs +175 -0
  22. data/ext/polars/src/dataframe/mod.rs +37 -5
  23. data/ext/polars/src/dataframe/serde.rs +23 -8
  24. data/ext/polars/src/error.rs +44 -7
  25. data/ext/polars/src/exceptions.rs +21 -8
  26. data/ext/polars/src/expr/array.rs +86 -22
  27. data/ext/polars/src/expr/binary.rs +50 -1
  28. data/ext/polars/src/expr/bitwise.rs +39 -0
  29. data/ext/polars/src/expr/categorical.rs +20 -0
  30. data/ext/polars/src/expr/datatype.rs +51 -0
  31. data/ext/polars/src/expr/datetime.rs +99 -41
  32. data/ext/polars/src/expr/extension.rs +12 -0
  33. data/ext/polars/src/expr/general.rs +252 -128
  34. data/ext/polars/src/expr/list.rs +56 -60
  35. data/ext/polars/src/expr/meta.rs +30 -35
  36. data/ext/polars/src/expr/mod.rs +28 -6
  37. data/ext/polars/src/expr/name.rs +29 -14
  38. data/ext/polars/src/expr/rolling.rs +111 -3
  39. data/ext/polars/src/expr/selector.rs +219 -0
  40. data/ext/polars/src/expr/serde.rs +28 -0
  41. data/ext/polars/src/expr/string.rs +118 -20
  42. data/ext/polars/src/expr/struct.rs +14 -1
  43. data/ext/polars/src/file.rs +194 -86
  44. data/ext/polars/src/functions/aggregation.rs +13 -12
  45. data/ext/polars/src/functions/business.rs +2 -3
  46. data/ext/polars/src/functions/eager.rs +3 -2
  47. data/ext/polars/src/functions/io.rs +90 -18
  48. data/ext/polars/src/functions/lazy.rs +267 -118
  49. data/ext/polars/src/functions/meta.rs +8 -7
  50. data/ext/polars/src/functions/misc.rs +1 -1
  51. data/ext/polars/src/functions/mod.rs +2 -1
  52. data/ext/polars/src/functions/range.rs +88 -31
  53. data/ext/polars/src/functions/strings.rs +6 -0
  54. data/ext/polars/src/functions/utils.rs +8 -0
  55. data/ext/polars/src/interop/arrow/mod.rs +52 -1
  56. data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +37 -7
  57. data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
  58. data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
  59. data/ext/polars/src/interop/numo/to_numo_series.rs +72 -50
  60. data/ext/polars/src/io/cloud_options.rs +107 -0
  61. data/ext/polars/src/io/mod.rs +4 -0
  62. data/ext/polars/src/io/scan_options.rs +113 -0
  63. data/ext/polars/src/io/sink_options.rs +46 -0
  64. data/ext/polars/src/io/sink_output.rs +21 -0
  65. data/ext/polars/src/lazyframe/exitable.rs +39 -0
  66. data/ext/polars/src/lazyframe/general.rs +846 -368
  67. data/ext/polars/src/lazyframe/mod.rs +58 -5
  68. data/ext/polars/src/lazyframe/optflags.rs +59 -0
  69. data/ext/polars/src/lazyframe/serde.rs +36 -4
  70. data/ext/polars/src/lazyframe/sink.rs +46 -0
  71. data/ext/polars/src/lazygroupby.rs +38 -9
  72. data/ext/polars/src/lib.rs +574 -165
  73. data/ext/polars/src/map/lazy.rs +44 -74
  74. data/ext/polars/src/map/mod.rs +18 -254
  75. data/ext/polars/src/map/series.rs +241 -1087
  76. data/ext/polars/src/on_startup.rs +192 -9
  77. data/ext/polars/src/prelude.rs +1 -0
  78. data/ext/polars/src/rb_modules.rs +10 -57
  79. data/ext/polars/src/ruby/exceptions.rs +26 -0
  80. data/ext/polars/src/ruby/gvl.rs +104 -0
  81. data/ext/polars/src/ruby/lazy.rs +46 -0
  82. data/ext/polars/src/ruby/mod.rs +11 -0
  83. data/ext/polars/src/ruby/numo.rs +52 -0
  84. data/ext/polars/src/ruby/plan_callback.rs +198 -0
  85. data/ext/polars/src/ruby/rb_modules.rs +16 -0
  86. data/ext/polars/src/ruby/ruby_convert_registry.rs +51 -0
  87. data/ext/polars/src/ruby/ruby_function.rs +11 -0
  88. data/ext/polars/src/ruby/ruby_udf.rs +164 -0
  89. data/ext/polars/src/ruby/thread.rs +65 -0
  90. data/ext/polars/src/ruby/utils.rs +39 -0
  91. data/ext/polars/src/series/aggregation.rs +116 -91
  92. data/ext/polars/src/series/arithmetic.rs +16 -22
  93. data/ext/polars/src/series/comparison.rs +101 -222
  94. data/ext/polars/src/series/construction.rs +80 -70
  95. data/ext/polars/src/series/export.rs +98 -56
  96. data/ext/polars/src/series/general.rs +323 -440
  97. data/ext/polars/src/series/import.rs +22 -5
  98. data/ext/polars/src/series/map.rs +103 -0
  99. data/ext/polars/src/series/mod.rs +57 -15
  100. data/ext/polars/src/series/scatter.rs +139 -82
  101. data/ext/polars/src/sql.rs +16 -9
  102. data/ext/polars/src/testing/frame.rs +31 -0
  103. data/ext/polars/src/testing/mod.rs +5 -0
  104. data/ext/polars/src/testing/series.rs +31 -0
  105. data/ext/polars/src/timeout.rs +105 -0
  106. data/ext/polars/src/utils.rs +105 -4
  107. data/lib/polars/array_expr.rb +500 -22
  108. data/lib/polars/array_name_space.rb +384 -10
  109. data/lib/polars/batched_csv_reader.rb +48 -66
  110. data/lib/polars/binary_expr.rb +217 -0
  111. data/lib/polars/binary_name_space.rb +155 -1
  112. data/lib/polars/cat_expr.rb +224 -0
  113. data/lib/polars/cat_name_space.rb +132 -32
  114. data/lib/polars/catalog/unity/catalog_info.rb +20 -0
  115. data/lib/polars/catalog/unity/column_info.rb +31 -0
  116. data/lib/polars/catalog/unity/namespace_info.rb +21 -0
  117. data/lib/polars/catalog/unity/table_info.rb +50 -0
  118. data/lib/polars/catalog.rb +448 -0
  119. data/lib/polars/collect_batches.rb +22 -0
  120. data/lib/polars/config.rb +3 -3
  121. data/lib/polars/convert.rb +201 -36
  122. data/lib/polars/data_frame.rb +2851 -1017
  123. data/lib/polars/data_frame_plot.rb +173 -0
  124. data/lib/polars/data_type_expr.rb +52 -0
  125. data/lib/polars/data_type_group.rb +6 -0
  126. data/lib/polars/data_types.rb +118 -18
  127. data/lib/polars/date_time_expr.rb +426 -84
  128. data/lib/polars/date_time_name_space.rb +384 -111
  129. data/lib/polars/dynamic_group_by.rb +102 -10
  130. data/lib/polars/exceptions.rb +50 -5
  131. data/lib/polars/expr.rb +2159 -915
  132. data/lib/polars/extension_expr.rb +39 -0
  133. data/lib/polars/extension_name_space.rb +39 -0
  134. data/lib/polars/functions/aggregation/horizontal.rb +11 -6
  135. data/lib/polars/functions/aggregation/vertical.rb +2 -3
  136. data/lib/polars/functions/as_datatype.rb +290 -8
  137. data/lib/polars/functions/business.rb +95 -0
  138. data/lib/polars/functions/col.rb +6 -5
  139. data/lib/polars/functions/datatype.rb +62 -0
  140. data/lib/polars/functions/eager.rb +426 -24
  141. data/lib/polars/functions/escape_regex.rb +21 -0
  142. data/lib/polars/functions/lazy.rb +813 -195
  143. data/lib/polars/functions/lit.rb +21 -10
  144. data/lib/polars/functions/range/int_range.rb +74 -2
  145. data/lib/polars/functions/range/linear_space.rb +195 -0
  146. data/lib/polars/functions/range/time_range.rb +1 -1
  147. data/lib/polars/functions/repeat.rb +7 -12
  148. data/lib/polars/functions/whenthen.rb +2 -2
  149. data/lib/polars/group_by.rb +188 -58
  150. data/lib/polars/iceberg_dataset.rb +108 -0
  151. data/lib/polars/in_process_query.rb +37 -0
  152. data/lib/polars/io/cloud.rb +18 -0
  153. data/lib/polars/io/csv.rb +336 -128
  154. data/lib/polars/io/database.rb +19 -4
  155. data/lib/polars/io/delta.rb +134 -0
  156. data/lib/polars/io/iceberg.rb +34 -0
  157. data/lib/polars/io/ipc.rb +63 -63
  158. data/lib/polars/io/json.rb +16 -0
  159. data/lib/polars/io/lines.rb +172 -0
  160. data/lib/polars/io/ndjson.rb +176 -20
  161. data/lib/polars/io/parquet.rb +173 -95
  162. data/lib/polars/io/scan_options.rb +55 -0
  163. data/lib/polars/io/sink_options.rb +27 -0
  164. data/lib/polars/io/utils.rb +17 -0
  165. data/lib/polars/lazy_frame.rb +3017 -622
  166. data/lib/polars/lazy_group_by.rb +436 -2
  167. data/lib/polars/list_expr.rb +551 -59
  168. data/lib/polars/list_name_space.rb +465 -51
  169. data/lib/polars/meta_expr.rb +146 -24
  170. data/lib/polars/name_expr.rb +87 -2
  171. data/lib/polars/query_opt_flags.rb +264 -0
  172. data/lib/polars/rolling_group_by.rb +90 -5
  173. data/lib/polars/scan_cast_options.rb +86 -0
  174. data/lib/polars/schema.rb +128 -0
  175. data/lib/polars/selector.rb +245 -0
  176. data/lib/polars/selectors.rb +1048 -201
  177. data/lib/polars/series.rb +2522 -774
  178. data/lib/polars/series_plot.rb +72 -0
  179. data/lib/polars/slice.rb +1 -1
  180. data/lib/polars/sql_context.rb +13 -6
  181. data/lib/polars/string_cache.rb +19 -72
  182. data/lib/polars/string_expr.rb +561 -107
  183. data/lib/polars/string_name_space.rb +781 -109
  184. data/lib/polars/struct_expr.rb +139 -18
  185. data/lib/polars/struct_name_space.rb +19 -1
  186. data/lib/polars/testing.rb +24 -273
  187. data/lib/polars/utils/constants.rb +2 -0
  188. data/lib/polars/utils/construction/data_frame.rb +410 -0
  189. data/lib/polars/utils/construction/series.rb +350 -0
  190. data/lib/polars/utils/construction/utils.rb +9 -0
  191. data/lib/polars/utils/convert.rb +18 -8
  192. data/lib/polars/utils/deprecation.rb +11 -0
  193. data/lib/polars/utils/parse.rb +62 -9
  194. data/lib/polars/utils/reduce_balanced.rb +43 -0
  195. data/lib/polars/utils/serde.rb +22 -0
  196. data/lib/polars/utils/unstable.rb +19 -0
  197. data/lib/polars/utils/various.rb +86 -1
  198. data/lib/polars/utils.rb +63 -48
  199. data/lib/polars/version.rb +1 -1
  200. data/lib/polars.rb +85 -2
  201. metadata +80 -28
  202. data/ext/polars/src/allocator.rs +0 -13
  203. data/ext/polars/src/batched_csv.rs +0 -138
  204. data/ext/polars/src/functions/string_cache.rs +0 -25
  205. data/ext/polars/src/map/dataframe.rs +0 -338
  206. data/lib/polars/plot.rb +0 -109
data/lib/polars/series.rb CHANGED
@@ -16,9 +16,6 @@ module Polars
16
16
  # Throw error on numeric overflow.
17
17
  # @param nan_to_null [Boolean]
18
18
  # Not used.
19
- # @param dtype_if_empty [Symbol, nil]
20
- # If no dtype is specified and values contains `nil` or an empty array,
21
- # set the Polars dtype of the Series data. If not specified, Float32 is used.
22
19
  #
23
20
  # @example Constructing a Series by specifying name and values positionally:
24
21
  # s = Polars::Series.new("a", [1, 2, 3])
@@ -28,53 +25,56 @@ module Polars
28
25
  # # => Polars::Int64
29
26
  #
30
27
  # @example Constructing a Series with a specific dtype:
31
- # s2 = Polars::Series.new("a", [1, 2, 3], dtype: :f32)
28
+ # s2 = Polars::Series.new("a", [1, 2, 3], dtype: Polars::Float32)
32
29
  #
33
30
  # @example It is possible to construct a Series with values as the first positional argument. This syntax considered an anti-pattern, but it can be useful in certain scenarios. You must specify any other arguments through keywords.
34
31
  # s3 = Polars::Series.new([1, 2, 3])
35
- def initialize(name = nil, values = nil, dtype: nil, strict: true, nan_to_null: false, dtype_if_empty: nil)
32
+ def initialize(name = nil, values = nil, dtype: nil, strict: true, nan_to_null: false)
33
+ # If 'Unknown' treat as nil to trigger type inference
34
+ if dtype == Unknown
35
+ dtype = nil
36
+ elsif !dtype.nil? && !Utils.is_polars_dtype(dtype)
37
+ dtype = Utils.parse_into_dtype(dtype)
38
+ end
39
+
36
40
  # Handle case where values are passed as the first argument
37
- if !name.nil? && !name.is_a?(::String)
41
+ original_name = nil
42
+ if name.nil?
43
+ name = ""
44
+ elsif name.is_a?(::String)
45
+ original_name = name
46
+ else
38
47
  if values.nil?
39
48
  values = name
40
- name = nil
49
+ name = ""
41
50
  else
42
- raise ArgumentError, "Series name must be a string."
51
+ raise TypeError, "Series name must be a string"
43
52
  end
44
53
  end
45
54
 
46
- name = "" if name.nil?
47
-
48
- # TODO improve
49
- if values.is_a?(Range) && values.begin.is_a?(::String)
50
- values = values.to_a
51
- end
52
-
53
- if values.nil?
54
- self._s = sequence_to_rbseries(name, [], dtype: dtype, dtype_if_empty: dtype_if_empty)
55
- elsif values.is_a?(Series)
56
- self._s = series_to_rbseries(name, values)
57
- elsif values.is_a?(Range)
58
- self._s =
59
- Polars.arange(
60
- values.first,
61
- values.last + (values.exclude_end? ? 0 : 1),
62
- step: 1,
63
- eager: true,
64
- dtype: dtype
65
- )
66
- .rename(name, in_place: true)
67
- ._s
68
- elsif values.is_a?(::Array)
69
- self._s = sequence_to_rbseries(name, values, dtype: dtype, strict: strict, dtype_if_empty: dtype_if_empty)
55
+ if values.is_a?(::Array) || values.is_a?(Range)
56
+ self._s = Utils.sequence_to_rbseries(
57
+ name,
58
+ values,
59
+ dtype: dtype,
60
+ strict: strict
61
+ )
62
+ elsif values.nil?
63
+ self._s = Utils.sequence_to_rbseries(name, [], dtype: dtype)
70
64
  elsif defined?(Numo::NArray) && values.is_a?(Numo::NArray)
71
- self._s = numo_to_rbseries(name, values, strict: strict, nan_to_null: nan_to_null)
65
+ self._s = Utils.numo_to_rbseries(name, values, strict: strict, nan_to_null: nan_to_null)
72
66
 
73
67
  if !dtype.nil?
74
- self._s = self.cast(dtype, strict: true)._s
68
+ self._s = cast(dtype, strict: strict)._s
75
69
  end
70
+ elsif values.is_a?(Series)
71
+ self._s = Utils.series_to_rbseries(original_name, values, dtype: dtype, strict: strict)
72
+ elsif values.is_a?(DataFrame)
73
+ self._s = Utils.dataframe_to_rbseries(
74
+ original_name, values, dtype: dtype, strict: strict
75
+ )
76
76
  else
77
- raise ArgumentError, "Series constructor called with unsupported type; got #{values.class.name}"
77
+ raise TypeError, "Series constructor called with unsupported type; got #{values.class.name}"
78
78
  end
79
79
  end
80
80
 
@@ -287,7 +287,7 @@ module Polars
287
287
  self != other
288
288
  end
289
289
 
290
- # Method equivalent of equality operator `series != other` where `None == None`.
290
+ # Method equivalent of equality operator `series != other` where `nil == nil`.
291
291
  #
292
292
  # This differs from the standard `ne` where null values are propagated.
293
293
  #
@@ -358,7 +358,7 @@ module Polars
358
358
  #
359
359
  # @return [Series]
360
360
  def *(other)
361
- if is_temporal
361
+ if dtype.temporal?
362
362
  raise ArgumentError, "first cast to integer before multiplying datelike dtypes"
363
363
  elsif other.is_a?(DataFrame)
364
364
  other * self
@@ -371,11 +371,11 @@ module Polars
371
371
  #
372
372
  # @return [Series]
373
373
  def /(other)
374
- if is_temporal
374
+ if dtype.temporal?
375
375
  raise ArgumentError, "first cast to integer before dividing datelike dtypes"
376
376
  end
377
377
 
378
- if is_float
378
+ if dtype.float?
379
379
  return _arithmetic(other, :div)
380
380
  end
381
381
 
@@ -386,7 +386,7 @@ module Polars
386
386
  #
387
387
  # @return [Series]
388
388
  def %(other)
389
- if is_datelike
389
+ if dtype.temporal?
390
390
  raise ArgumentError, "first cast to integer before applying modulo on datelike dtypes"
391
391
  end
392
392
  _arithmetic(other, :rem)
@@ -396,7 +396,7 @@ module Polars
396
396
  #
397
397
  # @return [Series]
398
398
  def **(power)
399
- if is_datelike
399
+ if dtype.temporal?
400
400
  raise ArgumentError, "first cast to integer before raising datelike dtypes to a power"
401
401
  end
402
402
  to_frame.select(Polars.col(name).pow(power)).to_series
@@ -407,7 +407,7 @@ module Polars
407
407
  # @return [Series]
408
408
  def !
409
409
  if dtype == Boolean
410
- return Utils.wrap_s(_s.not)
410
+ return Utils.wrap_s(_s.not_)
411
411
  end
412
412
  raise NotImplementedError
413
413
  end
@@ -435,7 +435,7 @@ module Polars
435
435
  # @return [Object]
436
436
  def [](item)
437
437
  if item.is_a?(Series) && [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64].include?(item.dtype)
438
- return Utils.wrap_s(_s.take_with_series(_pos_idxs(item)._s))
438
+ return Utils.wrap_s(_s.gather_with_series(_pos_idxs(item)._s))
439
439
  end
440
440
 
441
441
  if item.is_a?(Series) && item.bool?
@@ -447,7 +447,7 @@ module Polars
447
447
  item = len + item
448
448
  end
449
449
 
450
- return _s.get_idx(item)
450
+ return _s.get_index(item)
451
451
  end
452
452
 
453
453
  if item.is_a?(Range)
@@ -455,7 +455,7 @@ module Polars
455
455
  end
456
456
 
457
457
  if Utils.is_int_sequence(item)
458
- return Utils.wrap_s(_s.take_with_series(_pos_idxs(Series.new("", item))._s))
458
+ return Utils.wrap_s(_s.gather_with_series(_pos_idxs(Series.new("", item))._s))
459
459
  end
460
460
 
461
461
  raise ArgumentError, "Cannot get item of type: #{item.class.name}"
@@ -466,7 +466,7 @@ module Polars
466
466
  # @return [Object]
467
467
  def []=(key, value)
468
468
  if value.is_a?(::Array)
469
- if is_numeric || is_datelike
469
+ if dtype.numeric? || dtype.temporal?
470
470
  scatter(key, value)
471
471
  return
472
472
  end
@@ -484,7 +484,7 @@ module Polars
484
484
  raise Todo
485
485
  end
486
486
  elsif key.is_a?(::Array)
487
- s = Utils.wrap_s(sequence_to_rbseries("", key, dtype: UInt32))
487
+ s = Utils.wrap_s(Utils.sequence_to_rbseries("", key, dtype: UInt32))
488
488
  self[s] = value
489
489
  elsif key.is_a?(Range)
490
490
  s = Series.new("", key, dtype: UInt32)
@@ -496,6 +496,37 @@ module Polars
496
496
  end
497
497
  end
498
498
 
499
+ # Return the Series as a scalar, or return the element at the given index.
500
+ #
501
+ # If no index is provided, this is equivalent to `s[0]`, with a check
502
+ # that the shape is (1,). With an index, this is equivalent to `s[index]`.
503
+ #
504
+ # @return [Object]
505
+ #
506
+ # @example
507
+ # s1 = Polars::Series.new("a", [1])
508
+ # s1.item
509
+ # # => 1
510
+ #
511
+ # @example
512
+ # s2 = Polars::Series.new("a", [9, 8, 7])
513
+ # s2.cum_sum.item(-1)
514
+ # # => 24
515
+ def item(index = nil)
516
+ if index.nil?
517
+ if len != 1
518
+ msg = (
519
+ "can only call '.item' if the Series is of length 1," +
520
+ " or an explicit index is provided (Series is of length #{len})"
521
+ )
522
+ raise ArgumentError, msg
523
+ end
524
+ return _s.get_index(0)
525
+ end
526
+
527
+ _s.get_index_signed(index)
528
+ end
529
+
499
530
  # Return an estimation of the total (heap) allocated size of the Series.
500
531
  #
501
532
  # Estimated size is given in the specified unit (bytes by default).
@@ -517,7 +548,7 @@ module Polars
517
548
  # @return [Numeric]
518
549
  #
519
550
  # @example
520
- # s = Polars::Series.new("values", 1..1_000_000, dtype: :u32)
551
+ # s = Polars::Series.new("values", 1..1_000_000, dtype: Polars::UInt32)
521
552
  # s.estimated_size
522
553
  # # => 4000000
523
554
  # s.estimated_size("mb")
@@ -543,7 +574,26 @@ module Polars
543
574
  # # 1.732051
544
575
  # # ]
545
576
  def sqrt
546
- self**0.5
577
+ super
578
+ end
579
+
580
+ # Compute the cube root of the elements.
581
+ #
582
+ # @return [Series]
583
+ #
584
+ # @example
585
+ # s = Polars::Series.new([1, 2, 3])
586
+ # s.cbrt
587
+ # # =>
588
+ # # shape: (3,)
589
+ # # Series: '' [f64]
590
+ # # [
591
+ # # 1.0
592
+ # # 1.259921
593
+ # # 1.44225
594
+ # # ]
595
+ def cbrt
596
+ super
547
597
  end
548
598
 
549
599
  # Check if any boolean value in the column is `true`.
@@ -563,7 +613,7 @@ module Polars
563
613
  # # => false
564
614
  def any?(ignore_nulls: true, &block)
565
615
  if block_given?
566
- apply(skip_nulls: ignore_nulls, &block).any?
616
+ map_elements(return_dtype: Boolean, skip_nulls: ignore_nulls, &block).any?
567
617
  else
568
618
  _s.any(ignore_nulls)
569
619
  end
@@ -587,7 +637,7 @@ module Polars
587
637
  # # => true
588
638
  def all?(ignore_nulls: true, &block)
589
639
  if block_given?
590
- apply(skip_nulls: ignore_nulls, &block).all?
640
+ map_elements(return_dtype: Boolean, skip_nulls: ignore_nulls, &block).all?
591
641
  else
592
642
  _s.all(ignore_nulls)
593
643
  end
@@ -611,7 +661,7 @@ module Polars
611
661
  # # => true
612
662
  def none?(&block)
613
663
  if block_given?
614
- apply(&block).none?
664
+ map_elements(return_dtype: Boolean, &block).none?
615
665
  else
616
666
  to_frame.select(Polars.col(name).is_not.all).to_series[0]
617
667
  end
@@ -640,6 +690,25 @@ module Polars
640
690
  super
641
691
  end
642
692
 
693
+ # Compute the natural logarithm of the input array plus one, element-wise.
694
+ #
695
+ # @return [Series]
696
+ #
697
+ # @example
698
+ # s = Polars::Series.new([1, 2, 3])
699
+ # s.log1p
700
+ # # =>
701
+ # # shape: (3,)
702
+ # # Series: '' [f64]
703
+ # # [
704
+ # # 0.693147
705
+ # # 1.098612
706
+ # # 1.386294
707
+ # # ]
708
+ def log1p
709
+ super
710
+ end
711
+
643
712
  # Compute the base 10 logarithm of the input array, element-wise.
644
713
  #
645
714
  # @return [Series]
@@ -758,81 +827,60 @@ module Polars
758
827
  # Series with mixed datatypes will return summary statistics for the datatype of
759
828
  # the first value.
760
829
  #
830
+ # @param percentiles [Array]
831
+ # One or more percentiles to include in the summary statistics (if the
832
+ # Series has a numeric dtype). All values must be in the range `[0, 1]`.
833
+ # @param interpolation ['nearest', 'higher', 'lower', 'midpoint', 'linear', 'equiprobable']
834
+ # Interpolation method used when calculating percentiles.
835
+ #
761
836
  # @return [DataFrame]
762
837
  #
763
838
  # @example
764
- # series_num = Polars::Series.new([1, 2, 3, 4, 5])
765
- # series_num.describe
839
+ # s = Polars::Series.new([1, 2, 3, 4, 5])
840
+ # s.describe
766
841
  # # =>
767
- # # shape: (6, 2)
842
+ # # shape: (9, 2)
768
843
  # # ┌────────────┬──────────┐
769
844
  # # │ statistic ┆ value │
770
845
  # # │ --- ┆ --- │
771
846
  # # │ str ┆ f64 │
772
847
  # # ╞════════════╪══════════╡
773
- # # │ min 1.0 │
774
- # # │ max ┆ 5.0 │
848
+ # # │ count 5.0 │
775
849
  # # │ null_count ┆ 0.0 │
776
850
  # # │ mean ┆ 3.0 │
777
851
  # # │ std ┆ 1.581139 │
778
- # # │ count 5.0 │
852
+ # # │ min 1.0 │
853
+ # # │ 25% ┆ 2.0 │
854
+ # # │ 50% ┆ 3.0 │
855
+ # # │ 75% ┆ 4.0 │
856
+ # # │ max ┆ 5.0 │
779
857
  # # └────────────┴──────────┘
780
858
  #
781
- # @example
782
- # series_str = Polars::Series.new(["a", "a", nil, "b", "c"])
783
- # series_str.describe
859
+ # @example Non-numeric data types may not have all statistics available.
860
+ # s = Polars::Series.new(["aa", "aa", nil, "bb", "cc"])
861
+ # s.describe
784
862
  # # =>
785
- # # shape: (3, 2)
863
+ # # shape: (4, 2)
786
864
  # # ┌────────────┬───────┐
787
865
  # # │ statistic ┆ value │
788
866
  # # │ --- ┆ --- │
789
- # # │ str ┆ i64
867
+ # # │ str ┆ str
790
868
  # # ╞════════════╪═══════╡
791
- # # │ unique ┆ 4 │
869
+ # # │ count ┆ 4 │
792
870
  # # │ null_count ┆ 1 │
793
- # # │ count 5
871
+ # # │ min aa
872
+ # # │ max ┆ cc │
794
873
  # # └────────────┴───────┘
795
- def describe
796
- if len == 0
797
- raise ArgumentError, "Series must contain at least one value"
798
- elsif is_numeric
799
- s = cast(:f64)
800
- stats = {
801
- "min" => s.min,
802
- "max" => s.max,
803
- "null_count" => s.null_count,
804
- "mean" => s.mean,
805
- "std" => s.std,
806
- "count" => s.len
807
- }
808
- elsif is_boolean
809
- stats = {
810
- "sum" => sum,
811
- "null_count" => null_count,
812
- "count" => len
813
- }
814
- elsif is_utf8
815
- stats = {
816
- "unique" => unique.length,
817
- "null_count" => null_count,
818
- "count" => len
819
- }
820
- elsif is_datelike
821
- # we coerce all to string, because a polars column
822
- # only has a single dtype and dates: datetime and count: int don't match
823
- stats = {
824
- "min" => dt.min.to_s,
825
- "max" => dt.max.to_s,
826
- "null_count" => null_count.to_s,
827
- "count" => len.to_s
828
- }
829
- else
830
- raise TypeError, "This type is not supported"
831
- end
832
-
833
- Polars::DataFrame.new(
834
- {"statistic" => stats.keys, "value" => stats.values}
874
+ def describe(
875
+ percentiles: [0.25, 0.5, 0.75],
876
+ interpolation: "nearest"
877
+ )
878
+ stats = to_frame.describe(
879
+ percentiles: percentiles,
880
+ interpolation: interpolation
835
881
  )
882
+ stats.columns = ["statistic", "value"]
883
+ stats.filter(F.col("value").is_not_null)
836
884
  end
837
885
 
838
886
  # Reduce this Series to the sum value.
@@ -840,8 +888,8 @@ module Polars
840
888
  # @return [Numeric]
841
889
  #
842
890
  # @note
843
- # Dtypes `:i8`, `:u8`, `:i16`, and `:u16` are cast to
844
- # `:i64` before summing to prevent overflow issues.
891
+ # Dtypes in \\\\{Int8, UInt8, Int16, UInt16} are cast to
892
+ # Int64 before summing to prevent overflow issues.
845
893
  #
846
894
  # @example
847
895
  # s = Polars::Series.new("a", [1, 2, 3])
@@ -875,6 +923,44 @@ module Polars
875
923
  to_frame.select(Polars.col(name).product).to_series[0]
876
924
  end
877
925
 
926
+ # Raise to the power of the given exponent.
927
+ #
928
+ # If the exponent is float, the result follows the dtype of exponent.
929
+ # Otherwise, it follows dtype of base.
930
+ #
931
+ # @param exponent [Numeric]
932
+ # The exponent. Accepts Series input.
933
+ #
934
+ # @return [Series]
935
+ #
936
+ # @example Raising integers to positive integers results in integers:
937
+ # s = Polars::Series.new("foo", [1, 2, 3, 4])
938
+ # s.pow(3)
939
+ # # =>
940
+ # # shape: (4,)
941
+ # # Series: 'foo' [i64]
942
+ # # [
943
+ # # 1
944
+ # # 8
945
+ # # 27
946
+ # # 64
947
+ # # ]
948
+ #
949
+ # @example In order to raise integers to negative integers, you can cast either the base or the exponent to float:
950
+ # s.pow(-3.0)
951
+ # # =>
952
+ # # shape: (4,)
953
+ # # Series: 'foo' [f64]
954
+ # # [
955
+ # # 1.0
956
+ # # 0.125
957
+ # # 0.037037
958
+ # # 0.015625
959
+ # # ]
960
+ def pow(exponent)
961
+ to_frame.select_seq(F.col(name).pow(exponent)).to_series
962
+ end
963
+
878
964
  # Get the minimal value in this Series.
879
965
  #
880
966
  # @return [Object]
@@ -887,6 +973,29 @@ module Polars
887
973
  _s.min
888
974
  end
889
975
 
976
+ # Get the minimum value in this Series, ordered by an expression.
977
+ #
978
+ # If the by expression has multiple values equal to the minimum it is not
979
+ # defined which value will be chosen.
980
+ #
981
+ # @note
982
+ # This functionality is considered **unstable**. It may be changed
983
+ # at any point without it being considered a breaking change.
984
+ #
985
+ # @param by [Object]
986
+ # Column used to determine the smallest element.
987
+ # Accepts expression input. Strings are parsed as column names.
988
+ #
989
+ # @return [Expr]
990
+ #
991
+ # @example
992
+ # s = Polars::Series.new("a", [-2.0, Float::NAN, 1.0])
993
+ # s.min_by(Polars.col("a").abs)
994
+ # # => 1.0
995
+ def min_by(by)
996
+ to_frame.select_seq(F.col(name).min_by(by)).item
997
+ end
998
+
890
999
  # Get the maximum value in this Series.
891
1000
  #
892
1001
  # @return [Object]
@@ -899,6 +1008,29 @@ module Polars
899
1008
  _s.max
900
1009
  end
901
1010
 
1011
+ # Get the maximum value in this Series, ordered by an expression.
1012
+ #
1013
+ # If the by expression has multiple values equal to the maximum it is not
1014
+ # defined which value will be chosen.
1015
+ #
1016
+ # @note
1017
+ # This functionality is considered **unstable**. It may be changed
1018
+ # at any point without it being considered a breaking change.
1019
+ #
1020
+ # @param by [Object]
1021
+ # Column used to determine the largest element.
1022
+ # Accepts expression input. Strings are parsed as column names.
1023
+ #
1024
+ # @return [Object]
1025
+ #
1026
+ # @example
1027
+ # s = Polars::Series.new("a", [-2.0, Float::NAN, 1.0])
1028
+ # s.max_by(Polars.col("a").abs)
1029
+ # # => -2.0
1030
+ def max_by(by)
1031
+ to_frame.select_seq(F.col(name).max_by(by)).item
1032
+ end
1033
+
902
1034
  # Get maximum value, but propagate/poison encountered NaN values.
903
1035
  #
904
1036
  # @return [Object]
@@ -946,7 +1078,7 @@ module Polars
946
1078
  # s.std
947
1079
  # # => 1.0
948
1080
  def std(ddof: 1)
949
- if !is_numeric
1081
+ if !dtype.numeric?
950
1082
  nil
951
1083
  else
952
1084
  to_frame.select(Polars.col(name).std(ddof: ddof)).to_series[0]
@@ -966,7 +1098,7 @@ module Polars
966
1098
  # s.var
967
1099
  # # => 1.0
968
1100
  def var(ddof: 1)
969
- if !is_numeric
1101
+ if !dtype.numeric?
970
1102
  nil
971
1103
  else
972
1104
  to_frame.select(Polars.col(name).var(ddof: ddof)).to_series[0]
@@ -1004,6 +1136,13 @@ module Polars
1004
1136
 
1005
1137
  # Get dummy variables.
1006
1138
  #
1139
+ # @param separator [String]
1140
+ # Separator/delimiter used when generating column names.
1141
+ # @param drop_first [Boolean]
1142
+ # Remove the first category from the variable being encoded.
1143
+ # @param drop_nulls [Boolean]
1144
+ # If there are `nil` values in the series, a `null` column is not generated.
1145
+ #
1007
1146
  # @return [DataFrame]
1008
1147
  #
1009
1148
  # @example
@@ -1020,8 +1159,8 @@ module Polars
1020
1159
  # # │ 0 ┆ 1 ┆ 0 │
1021
1160
  # # │ 0 ┆ 0 ┆ 1 │
1022
1161
  # # └─────┴─────┴─────┘
1023
- def to_dummies(separator: "_", drop_first: false)
1024
- Utils.wrap_df(_s.to_dummies(separator, drop_first))
1162
+ def to_dummies(separator: "_", drop_first: false, drop_nulls: false)
1163
+ Utils.wrap_df(_s.to_dummies(separator, drop_first, drop_nulls))
1025
1164
  end
1026
1165
 
1027
1166
  # Bin continuous values into discrete categories.
@@ -1045,7 +1184,7 @@ module Polars
1045
1184
  # s.cut([-1, 1], labels: ["a", "b", "c"])
1046
1185
  # # =>
1047
1186
  # # shape: (5,)
1048
- # # Series: 'foo' [cat]
1187
+ # # Series: 'foo' [enum]
1049
1188
  # # [
1050
1189
  # # "a"
1051
1190
  # # "a"
@@ -1062,7 +1201,7 @@ module Polars
1062
1201
  # # ┌─────┬─────────────┬────────────┐
1063
1202
  # # │ foo ┆ break_point ┆ category │
1064
1203
  # # │ --- ┆ --- ┆ --- │
1065
- # # │ i64 ┆ f64 ┆ cat
1204
+ # # │ i64 ┆ f64 ┆ enum
1066
1205
  # # ╞═════╪═════════════╪════════════╡
1067
1206
  # # │ -2 ┆ -1.0 ┆ (-inf, -1] │
1068
1207
  # # │ -1 ┆ -1.0 ┆ (-inf, -1] │
@@ -1093,8 +1232,8 @@ module Polars
1093
1232
 
1094
1233
  # Bin continuous values into discrete categories based on their quantiles.
1095
1234
  #
1096
- # @param quantiles [Array]
1097
- # Either a list of quantile probabilities between 0 and 1 or a positive
1235
+ # @param quantiles [Object]
1236
+ # Either an array of quantile probabilities between 0 and 1 or a positive
1098
1237
  # integer determining the number of bins with uniform probability.
1099
1238
  # @param labels [Array]
1100
1239
  # Names of the categories. The number of labels must be equal to the number
@@ -1230,10 +1369,76 @@ module Polars
1230
1369
  super
1231
1370
  end
1232
1371
 
1372
+ # Bin values into buckets and count their occurrences.
1373
+ #
1374
+ # @note
1375
+ # This functionality is considered **unstable**. It may be changed
1376
+ # at any point without it being considered a breaking change.
1377
+ #
1378
+ # @param bins [Object]
1379
+ # Bin edges. If nil given, we determine the edges based on the data.
1380
+ # @param bin_count [Integer]
1381
+ # If `bins` is not provided, `bin_count` uniform bins are created that fully
1382
+ # encompass the data.
1383
+ # @param include_category [Boolean]
1384
+ # Include a column that shows the intervals as categories.
1385
+ # @param include_breakpoint [Boolean]
1386
+ # Include a column that indicates the upper breakpoint.
1387
+ #
1388
+ # @return [DataFrame]
1389
+ #
1390
+ # @example
1391
+ # a = Polars::Series.new("a", [1, 3, 8, 8, 2, 1, 3])
1392
+ # a.hist(bin_count: 4)
1393
+ # # =>
1394
+ # # shape: (4, 3)
1395
+ # # ┌────────────┬─────────────┬───────┐
1396
+ # # │ breakpoint ┆ category ┆ count │
1397
+ # # │ --- ┆ --- ┆ --- │
1398
+ # # │ f64 ┆ cat ┆ u32 │
1399
+ # # ╞════════════╪═════════════╪═══════╡
1400
+ # # │ 2.75 ┆ [1.0, 2.75] ┆ 3 │
1401
+ # # │ 4.5 ┆ (2.75, 4.5] ┆ 2 │
1402
+ # # │ 6.25 ┆ (4.5, 6.25] ┆ 0 │
1403
+ # # │ 8.0 ┆ (6.25, 8.0] ┆ 2 │
1404
+ # # └────────────┴─────────────┴───────┘
1405
+ def hist(
1406
+ bins: nil,
1407
+ bin_count: nil,
1408
+ include_category: true,
1409
+ include_breakpoint: true
1410
+ )
1411
+ out = (
1412
+ to_frame
1413
+ .select_seq(
1414
+ F.col(name).hist(
1415
+ bins: bins,
1416
+ bin_count: bin_count,
1417
+ include_category: include_category,
1418
+ include_breakpoint: include_breakpoint
1419
+ )
1420
+ )
1421
+ .to_series
1422
+ )
1423
+ if !include_breakpoint && !include_category
1424
+ out.to_frame
1425
+ else
1426
+ out.struct.unnest
1427
+ end
1428
+ end
1429
+
1233
1430
  # Count the unique values in a Series.
1234
1431
  #
1235
1432
  # @param sort [Boolean]
1236
1433
  # Ensure the output is sorted from most values to least.
1434
+ # @param parallel [Boolean]
1435
+ # Execute the computation in parallel.
1436
+ # @param name [String]
1437
+ # Give the resulting count column a specific name; if `normalize` is
1438
+ # true this defaults to "proportion", otherwise defaults to "count".
1439
+ # @param normalize [Boolean]
1440
+ # If true, the count is returned as the relative frequency of unique
1441
+ # values normalized to 1.0.
1237
1442
  #
1238
1443
  # @return [DataFrame]
1239
1444
  #
@@ -1310,7 +1515,7 @@ module Polars
1310
1515
  # b = Polars::Series.new([0.65, 0.10, 0.25])
1311
1516
  # b.entropy(normalize: true)
1312
1517
  # # => 0.8568409950394724
1313
- def entropy(base: Math::E, normalize: false)
1518
+ def entropy(base: Math::E, normalize: true)
1314
1519
  Polars.select(Polars.lit(self).entropy(base: base, normalize: normalize)).to_series[0]
1315
1520
  end
1316
1521
 
@@ -1318,12 +1523,9 @@ module Polars
1318
1523
  #
1319
1524
  # @param expr [Expr]
1320
1525
  # Expression to evaluate
1321
- # @param min_periods [Integer]
1526
+ # @param min_samples [Integer]
1322
1527
  # Number of valid values there should be in the window before the expression
1323
1528
  # is evaluated. valid values = `length - null_count`
1324
- # @param parallel [Boolean]
1325
- # Run in parallel. Don't do this in a group by or another operation that
1326
- # already has much parallelization.
1327
1529
  #
1328
1530
  # @return [Series]
1329
1531
  #
@@ -1348,7 +1550,7 @@ module Polars
1348
1550
  # # -15
1349
1551
  # # -24
1350
1552
  # # ]
1351
- def cumulative_eval(expr, min_periods: 1, parallel: false)
1553
+ def cumulative_eval(expr, min_samples: 1)
1352
1554
  super
1353
1555
  end
1354
1556
 
@@ -1360,8 +1562,16 @@ module Polars
1360
1562
  # @return [Series]
1361
1563
  #
1362
1564
  # @example
1363
- # s = Polars::Series.new("x", [1, 2, 3])
1364
- # s.alias("y")
1565
+ # s = Polars::Series.new("a", [1, 2, 3])
1566
+ # s.alias("b")
1567
+ # # =>
1568
+ # # shape: (3,)
1569
+ # # Series: 'b' [i64]
1570
+ # # [
1571
+ # # 1
1572
+ # # 2
1573
+ # # 3
1574
+ # # ]
1365
1575
  def alias(name)
1366
1576
  s = dup
1367
1577
  s._s.rename(name)
@@ -1372,21 +1582,22 @@ module Polars
1372
1582
  #
1373
1583
  # @param name [String]
1374
1584
  # New name.
1375
- # @param in_place [Boolean]
1376
- # Modify the Series in-place.
1377
1585
  #
1378
1586
  # @return [Series]
1379
1587
  #
1380
1588
  # @example
1381
1589
  # s = Polars::Series.new("a", [1, 2, 3])
1382
1590
  # s.rename("b")
1383
- def rename(name, in_place: false)
1384
- if in_place
1385
- _s.rename(name)
1386
- self
1387
- else
1388
- self.alias(name)
1389
- end
1591
+ # # =>
1592
+ # # shape: (3,)
1593
+ # # Series: 'b' [i64]
1594
+ # # [
1595
+ # # 1
1596
+ # # 2
1597
+ # # 3
1598
+ # # ]
1599
+ def rename(name)
1600
+ self.alias(name)
1390
1601
  end
1391
1602
 
1392
1603
  # Get the length of each individual chunk.
@@ -1398,7 +1609,7 @@ module Polars
1398
1609
  # s2 = Polars::Series.new("b", [4, 5, 6])
1399
1610
  #
1400
1611
  # @example Concatenate Series with rechunk: true
1401
- # Polars.concat([s, s2]).chunk_lengths
1612
+ # Polars.concat([s, s2], rechunk: true).chunk_lengths
1402
1613
  # # => [6]
1403
1614
  #
1404
1615
  # @example Concatenate Series with rechunk: false
@@ -1417,7 +1628,7 @@ module Polars
1417
1628
  # s2 = Polars::Series.new("b", [4, 5, 6])
1418
1629
  #
1419
1630
  # @example Concatenate Series with rechunk: true
1420
- # Polars.concat([s, s2]).n_chunks
1631
+ # Polars.concat([s, s2], rechunk: true).n_chunks
1421
1632
  # # => 1
1422
1633
  #
1423
1634
  # @example Concatenate Series with rechunk: false
@@ -1435,8 +1646,8 @@ module Polars
1435
1646
  # @return [Series]
1436
1647
  #
1437
1648
  # @note
1438
- # Dtypes `:i8`, `:u8`, `:i16`, and `:u16` are cast to
1439
- # `:i64` before summing to prevent overflow issues.
1649
+ # Dtypes in \\\\{Int8, UInt8, Int16, UInt16} are cast to
1650
+ # Int64 before summing to prevent overflow issues.
1440
1651
  #
1441
1652
  # @example
1442
1653
  # s = Polars::Series.new("a", [1, 2, 3])
@@ -1452,7 +1663,29 @@ module Polars
1452
1663
  def cum_sum(reverse: false)
1453
1664
  super
1454
1665
  end
1455
- alias_method :cumsum, :cum_sum
1666
+
1667
+ # Return the cumulative count of the non-null values in the column.
1668
+ #
1669
+ # @param reverse [Boolean]
1670
+ # Reverse the operation.
1671
+ #
1672
+ # @return [Series]
1673
+ #
1674
+ # @example
1675
+ # s = Polars::Series.new(["x", "k", nil, "d"])
1676
+ # s.cum_count
1677
+ # # =>
1678
+ # # shape: (4,)
1679
+ # # Series: '' [u32]
1680
+ # # [
1681
+ # # 1
1682
+ # # 2
1683
+ # # 2
1684
+ # # 3
1685
+ # # ]
1686
+ def cum_count(reverse: false)
1687
+ super
1688
+ end
1456
1689
 
1457
1690
  # Get an array with the cumulative min computed at every element.
1458
1691
  #
@@ -1475,7 +1708,6 @@ module Polars
1475
1708
  def cum_min(reverse: false)
1476
1709
  super
1477
1710
  end
1478
- alias_method :cummin, :cum_min
1479
1711
 
1480
1712
  # Get an array with the cumulative max computed at every element.
1481
1713
  #
@@ -1498,7 +1730,6 @@ module Polars
1498
1730
  def cum_max(reverse: false)
1499
1731
  super
1500
1732
  end
1501
- alias_method :cummax, :cum_max
1502
1733
 
1503
1734
  # Get an array with the cumulative product computed at every element.
1504
1735
  #
@@ -1508,8 +1739,8 @@ module Polars
1508
1739
  # @return [Series]
1509
1740
  #
1510
1741
  # @note
1511
- # Dtypes `:i8`, `:u8`, `:i16`, and `:u16` are cast to
1512
- # `:i64` before multiplying to prevent overflow issues.
1742
+ # Dtypes in \\\\{Int8, UInt8, Int16, UInt16} are cast to
1743
+ # Int64 before summing to prevent overflow issues.
1513
1744
  #
1514
1745
  # @example
1515
1746
  # s = Polars::Series.new("a", [1, 2, 3])
@@ -1525,30 +1756,6 @@ module Polars
1525
1756
  def cum_prod(reverse: false)
1526
1757
  super
1527
1758
  end
1528
- alias_method :cumprod, :cum_prod
1529
-
1530
- # Get the first `n` rows.
1531
- #
1532
- # Alias for {#head}.
1533
- #
1534
- # @param n [Integer]
1535
- # Number of rows to return.
1536
- #
1537
- # @return [Series]
1538
- #
1539
- # @example
1540
- # s = Polars::Series.new("a", [1, 2, 3])
1541
- # s.limit(2)
1542
- # # =>
1543
- # # shape: (2,)
1544
- # # Series: 'a' [i64]
1545
- # # [
1546
- # # 1
1547
- # # 2
1548
- # # ]
1549
- def limit(n = 10)
1550
- to_frame.select(F.col(name).limit(n)).to_series
1551
- end
1552
1759
 
1553
1760
  # Get a slice of this Series.
1554
1761
  #
@@ -1578,29 +1785,6 @@ module Polars
1578
1785
  #
1579
1786
  # @param other [Series]
1580
1787
  # Series to append.
1581
- # @param append_chunks [Boolean]
1582
- # If set to `true` the append operation will add the chunks from `other` to
1583
- # self. This is super cheap.
1584
- #
1585
- # If set to `false` the append operation will do the same as
1586
- # {DataFrame#extend} which extends the memory backed by this Series with
1587
- # the values from `other`.
1588
- #
1589
- # Different from `append_chunks`, `extend` appends the data from `other` to
1590
- # the underlying memory locations and thus may cause a reallocation (which is
1591
- # expensive).
1592
- #
1593
- # If this does not cause a reallocation, the resulting data structure will not
1594
- # have any extra chunks and thus will yield faster queries.
1595
- #
1596
- # Prefer `extend` over `append_chunks` when you want to do a query after a
1597
- # single append. For instance during online operations where you add `n` rows
1598
- # and rerun a query.
1599
- #
1600
- # Prefer `append_chunks` over `extend` when you want to append many times
1601
- # before doing a query. For instance, when you read in multiple files and when
1602
- # to store them in a single Series. In the latter case, finish the sequence
1603
- # of `append_chunks` operations with a `rechunk`.
1604
1788
  #
1605
1789
  # @return [Series]
1606
1790
  #
@@ -1619,20 +1803,60 @@ module Polars
1619
1803
  # # 5
1620
1804
  # # 6
1621
1805
  # # ]
1622
- def append(other, append_chunks: true)
1623
- begin
1624
- if append_chunks
1625
- _s.append(other._s)
1626
- else
1627
- _s.extend(other._s)
1628
- end
1629
- rescue => e
1630
- if e.message == "Already mutably borrowed"
1631
- append(other.clone, append_chunks)
1632
- else
1633
- raise e
1634
- end
1635
- end
1806
+ def append(other)
1807
+ Utils.require_same_type(self, other)
1808
+ _s.append(other._s)
1809
+ self
1810
+ end
1811
+
1812
+ # Extend the memory backed by this Series with the values from another.
1813
+ #
1814
+ # Different from `append`, which adds the chunks from `other` to the chunks of
1815
+ # this series, `extend` appends the data from `other` to the underlying memory
1816
+ # locations and thus may cause a reallocation (which is expensive).
1817
+ #
1818
+ # If this does `not` cause a reallocation, the resulting data structure will not
1819
+ # have any extra chunks and thus will yield faster queries.
1820
+ #
1821
+ # Prefer `extend` over `append` when you want to do a query after a single
1822
+ # append. For instance, during online operations where you add `n` rows
1823
+ # and rerun a query.
1824
+ #
1825
+ # Prefer `append` over `extend` when you want to append many times
1826
+ # before doing a query. For instance, when you read in multiple files and want
1827
+ # to store them in a single `Series`. In the latter case, finish the sequence
1828
+ # of `append` operations with a `rechunk`.
1829
+ #
1830
+ # @param other [Series]
1831
+ # Series to extend the series with.
1832
+ #
1833
+ # @return [Series]
1834
+ #
1835
+ # @note
1836
+ # This method modifies the series in-place. The series is returned for
1837
+ # convenience only.
1838
+ #
1839
+ # @example
1840
+ # a = Polars::Series.new("a", [1, 2, 3])
1841
+ # b = Polars::Series.new("b", [4, 5])
1842
+ # a.extend(b)
1843
+ # # =>
1844
+ # # shape: (5,)
1845
+ # # Series: 'a' [i64]
1846
+ # # [
1847
+ # # 1
1848
+ # # 2
1849
+ # # 3
1850
+ # # 4
1851
+ # # 5
1852
+ # # ]
1853
+ #
1854
+ # @example The resulting series will consist of a single chunk.
1855
+ # a.n_chunks
1856
+ # # => 1
1857
+ def extend(other)
1858
+ Utils.require_same_type(self, other)
1859
+ _s.extend(other._s)
1636
1860
  self
1637
1861
  end
1638
1862
 
@@ -1679,7 +1903,10 @@ module Polars
1679
1903
  # # 2
1680
1904
  # # ]
1681
1905
  def head(n = 10)
1682
- to_frame.select(F.col(name).head(n)).to_series
1906
+ if n < 0
1907
+ n = [0, len + n].max
1908
+ end
1909
+ self.class._from_rbseries(_s.head(n))
1683
1910
  end
1684
1911
 
1685
1912
  # Get the last `n` rows.
@@ -1700,33 +1927,147 @@ module Polars
1700
1927
  # # 3
1701
1928
  # # ]
1702
1929
  def tail(n = 10)
1703
- to_frame.select(F.col(name).tail(n)).to_series
1930
+ if n < 0
1931
+ n = [0, len + n].max
1932
+ end
1933
+ self.class._from_rbseries(_s.tail(n))
1704
1934
  end
1705
1935
 
1706
- # Take every nth value in the Series and return as new Series.
1936
+ # Get the first `n` rows.
1937
+ #
1938
+ # Alias for {#head}.
1939
+ #
1940
+ # @param n [Integer]
1941
+ # Number of rows to return.
1707
1942
  #
1708
1943
  # @return [Series]
1709
1944
  #
1710
1945
  # @example
1711
- # s = Polars::Series.new("a", [1, 2, 3, 4])
1712
- # s.take_every(2)
1946
+ # s = Polars::Series.new("a", [1, 2, 3])
1947
+ # s.limit(2)
1713
1948
  # # =>
1714
1949
  # # shape: (2,)
1715
1950
  # # Series: 'a' [i64]
1716
1951
  # # [
1717
1952
  # # 1
1718
- # # 3
1953
+ # # 2
1719
1954
  # # ]
1720
- def take_every(n)
1721
- super
1955
+ def limit(n = 10)
1956
+ head(n)
1722
1957
  end
1723
1958
 
1724
- # Sort this Series.
1725
- #
1726
- # @param reverse [Boolean]
1727
- # Reverse sort.
1728
- # @param in_place [Boolean]
1729
- # Sort in place.
1959
+ # Take every nth value in the Series and return as new Series.
1960
+ #
1961
+ # @param n [Integer]
1962
+ # Gather every *n*-th row.
1963
+ # @param offset [Integer]
1964
+ # Start the row index at this offset.
1965
+ #
1966
+ # @return [Series]
1967
+ #
1968
+ # @example
1969
+ # s = Polars::Series.new("a", [1, 2, 3, 4])
1970
+ # s.gather_every(2)
1971
+ # # =>
1972
+ # # shape: (2,)
1973
+ # # Series: 'a' [i64]
1974
+ # # [
1975
+ # # 1
1976
+ # # 3
1977
+ # # ]
1978
+ #
1979
+ # @example
1980
+ # s.gather_every(2, 1)
1981
+ # # =>
1982
+ # # shape: (2,)
1983
+ # # Series: 'a' [i64]
1984
+ # # [
1985
+ # # 2
1986
+ # # 4
1987
+ # # ]
1988
+ def gather_every(n, offset = 0)
1989
+ super
1990
+ end
1991
+
1992
+ # Execute a SQL query against the Series.
1993
+ #
1994
+ # @note
1995
+ # This functionality is considered **unstable**, although it is close to
1996
+ # being considered stable. It may be changed at any point without it being
1997
+ # considered a breaking change.
1998
+ #
1999
+ # @param query [String]
2000
+ # SQL query to execute.
2001
+ # @param table_name [String]
2002
+ # Optionally provide an explicit name for the table that represents the
2003
+ # calling frame (defaults to "self").
2004
+ #
2005
+ # @return [DataFrame]
2006
+ #
2007
+ # @note
2008
+ # * The calling Series is automatically registered as a table in the SQLContext
2009
+ # under the name "self". If you want access to the DataFrames, LazyFrames, and
2010
+ # other Series found in the current globals, use :meth:`pl.sql <polars.sql>`.
2011
+ # * More control over registration and execution behaviour is available by
2012
+ # using the :class:`SQLContext` object.
2013
+ # * The SQL query executes in lazy mode before being collected and returned
2014
+ # as a DataFrame.
2015
+ # * It is recommended to name your Series for use with SQL, otherwise the default
2016
+ # Series name (an empty string) is used; while `""` is valid, it is awkward.
2017
+ #
2018
+ # @example Query the Series using SQL:
2019
+ # s = Polars::Series.new(
2020
+ # "dt",
2021
+ # [Date.new(1999, 12, 31), Date.new(2099, 2, 14), Date.new(2026, 3, 5)]
2022
+ # )
2023
+ # s.sql("
2024
+ # SELECT
2025
+ # EXTRACT('year',dt) AS y,
2026
+ # EXTRACT('month',dt) AS m,
2027
+ # EXTRACT('day',dt) AS d,
2028
+ # FROM self
2029
+ # WHERE dt > '2020-01-01'
2030
+ # ORDER BY dt DESC
2031
+ # ")
2032
+ # # =>
2033
+ # # shape: (2, 3)
2034
+ # # ┌──────┬─────┬─────┐
2035
+ # # │ y ┆ m ┆ d │
2036
+ # # │ --- ┆ --- ┆ --- │
2037
+ # # │ i32 ┆ i8 ┆ i8 │
2038
+ # # ╞══════╪═════╪═════╡
2039
+ # # │ 2099 ┆ 2 ┆ 14 │
2040
+ # # │ 2026 ┆ 3 ┆ 5 │
2041
+ # # └──────┴─────┴─────┘
2042
+ #
2043
+ # @example While you can refer to an unnamed Series column using the default empty string, it is not recommended:
2044
+ # s = Polars::Series.new([1, 2, 3])
2045
+ # s.sql('SELECT "" AS x, "" * 2 AS "2x" FROM self')
2046
+ # # =>
2047
+ # # shape: (3, 2)
2048
+ # # ┌─────┬─────┐
2049
+ # # │ x ┆ 2x │
2050
+ # # │ --- ┆ --- │
2051
+ # # │ i64 ┆ i64 │
2052
+ # # ╞═════╪═════╡
2053
+ # # │ 1 ┆ 2 │
2054
+ # # │ 2 ┆ 4 │
2055
+ # # │ 3 ┆ 6 │
2056
+ # # └─────┴─────┘
2057
+ def sql(query, table_name: "self")
2058
+ to_frame.sql(query, table_name: table_name)
2059
+ end
2060
+
2061
+ # Sort this Series.
2062
+ #
2063
+ # @param descending [Boolean]
2064
+ # Reverse sort.
2065
+ # @param nulls_last [Boolean]
2066
+ # Place null values last instead of first.
2067
+ # @param multithreaded [Boolean]
2068
+ # Sort using multiple threads.
2069
+ # @param in_place [Boolean]
2070
+ # Sort in place.
1730
2071
  #
1731
2072
  # @return [Series]
1732
2073
  #
@@ -1742,7 +2083,7 @@ module Polars
1742
2083
  # # 3
1743
2084
  # # 4
1744
2085
  # # ]
1745
- # s.sort(reverse: true)
2086
+ # s.sort(descending: true)
1746
2087
  # # =>
1747
2088
  # # shape: (4,)
1748
2089
  # # Series: 'a' [i64]
@@ -1752,12 +2093,12 @@ module Polars
1752
2093
  # # 2
1753
2094
  # # 1
1754
2095
  # # ]
1755
- def sort(reverse: false, nulls_last: false, multithreaded: true, in_place: false)
2096
+ def sort(descending: false, nulls_last: false, multithreaded: true, in_place: false)
1756
2097
  if in_place
1757
- self._s = _s.sort(reverse, nulls_last, multithreaded)
2098
+ self._s = _s.sort(descending, nulls_last, multithreaded)
1758
2099
  self
1759
2100
  else
1760
- Utils.wrap_s(_s.sort(reverse, nulls_last, multithreaded))
2101
+ Utils.wrap_s(_s.sort(descending, nulls_last, multithreaded))
1761
2102
  end
1762
2103
  end
1763
2104
 
@@ -1783,6 +2124,44 @@ module Polars
1783
2124
  super
1784
2125
  end
1785
2126
 
2127
+ # Return the `k` largest elements of the `by` column.
2128
+ #
2129
+ # Non-null elements are always preferred over null elements, regardless of
2130
+ # the value of `reverse`. The output is not guaranteed to be in any
2131
+ # particular order, call `sort` after this function if you wish the
2132
+ # output to be sorted.
2133
+ #
2134
+ # @param by [Object]
2135
+ # Column used to determine the largest elements.
2136
+ # Accepts expression input. Strings are parsed as column names.
2137
+ # @param k [Integer]
2138
+ # Number of elements to return.
2139
+ # @param reverse [Object]
2140
+ # Consider the `k` smallest elements of the `by` column (instead of the `k`
2141
+ # largest). This can be specified per column by passing an array of
2142
+ # booleans.
2143
+ #
2144
+ # @return [Series]
2145
+ #
2146
+ # @example
2147
+ # s = Polars::Series.new("a", [2, 5, 1, 4, 3])
2148
+ # s.top_k_by("a", k: 3)
2149
+ # # =>
2150
+ # # shape: (3,)
2151
+ # # Series: 'a' [i64]
2152
+ # # [
2153
+ # # 5
2154
+ # # 4
2155
+ # # 3
2156
+ # # ]
2157
+ def top_k_by(
2158
+ by,
2159
+ k: 5,
2160
+ reverse: false
2161
+ )
2162
+ super
2163
+ end
2164
+
1786
2165
  # Return the `k` smallest elements.
1787
2166
  #
1788
2167
  # @param k [Integer]
@@ -1805,9 +2184,47 @@ module Polars
1805
2184
  super
1806
2185
  end
1807
2186
 
2187
+ # Return the `k` smallest elements of the `by` column.
2188
+ #
2189
+ # Non-null elements are always preferred over null elements, regardless of
2190
+ # the value of `reverse`. The output is not guaranteed to be in any
2191
+ # particular order, call `sort` after this function if you wish the
2192
+ # output to be sorted.
2193
+ #
2194
+ # @param by [Object]
2195
+ # Column used to determine the smallest elements.
2196
+ # Accepts expression input. Strings are parsed as column names.
2197
+ # @param k [Integer]
2198
+ # Number of elements to return.
2199
+ # @param reverse [Object]
2200
+ # Consider the `k` largest elements of the `by` column( (instead of the `k`
2201
+ # smallest). This can be specified per column by passing an array of
2202
+ # booleans.
2203
+ #
2204
+ # @return [Series]
2205
+ #
2206
+ # @example
2207
+ # s = Polars::Series.new("a", [2, 5, 1, 4, 3])
2208
+ # s.bottom_k_by("a", k: 3)
2209
+ # # =>
2210
+ # # shape: (3,)
2211
+ # # Series: 'a' [i64]
2212
+ # # [
2213
+ # # 1
2214
+ # # 2
2215
+ # # 3
2216
+ # # ]
2217
+ def bottom_k_by(
2218
+ by,
2219
+ k: 5,
2220
+ reverse: false
2221
+ )
2222
+ super
2223
+ end
2224
+
1808
2225
  # Get the index values that would sort this Series.
1809
2226
  #
1810
- # @param reverse [Boolean]
2227
+ # @param descending [Boolean]
1811
2228
  # Sort in reverse (descending) order.
1812
2229
  # @param nulls_last [Boolean]
1813
2230
  # Place null values last instead of first.
@@ -1827,10 +2244,9 @@ module Polars
1827
2244
  # # 2
1828
2245
  # # 0
1829
2246
  # # ]
1830
- def arg_sort(reverse: false, nulls_last: false)
2247
+ def arg_sort(descending: false, nulls_last: false)
1831
2248
  super
1832
2249
  end
1833
- alias_method :argsort, :arg_sort
1834
2250
 
1835
2251
  # Get unique index as Series.
1836
2252
  #
@@ -1879,6 +2295,13 @@ module Polars
1879
2295
  #
1880
2296
  # @param element [Object]
1881
2297
  # Expression or scalar value.
2298
+ # @param side ['any', 'left', 'right']
2299
+ # If 'any', the index of the first suitable location found is given.
2300
+ # If 'left', the index of the leftmost suitable location found is given.
2301
+ # If 'right', return the rightmost suitable location found is given.
2302
+ # @param descending [Boolean]
2303
+ # Boolean indicating whether the values are descending or not (they
2304
+ # are required to be sorted either way).
1882
2305
  #
1883
2306
  # @return [Integer]
1884
2307
  #
@@ -1927,12 +2350,12 @@ module Polars
1927
2350
  # # 5
1928
2351
  # # 6
1929
2352
  # # ]
1930
- def search_sorted(element, side: "any")
2353
+ def search_sorted(element, side: "any", descending: false)
1931
2354
  if element.is_a?(Integer) || element.is_a?(Float)
1932
- return Polars.select(Polars.lit(self).search_sorted(element, side: side)).item
2355
+ return Polars.select(Polars.lit(self).search_sorted(element, side: side, descending: descending)).item
1933
2356
  end
1934
2357
  element = Series.new(element)
1935
- Polars.select(Polars.lit(self).search_sorted(element, side: side)).to_series
2358
+ Polars.select(Polars.lit(self).search_sorted(element, side: side, descending: descending)).to_series
1936
2359
  end
1937
2360
 
1938
2361
  # Get unique elements in series.
@@ -1962,12 +2385,17 @@ module Polars
1962
2385
  #
1963
2386
  # @param indices [Array]
1964
2387
  # Index location used for selection.
2388
+ # @param null_on_oob [Boolean]
2389
+ # Behavior if an index is out of bounds:
2390
+ #
2391
+ # - true -> set the result to null
2392
+ # - false -> raise an error
1965
2393
  #
1966
2394
  # @return [Series]
1967
2395
  #
1968
2396
  # @example
1969
2397
  # s = Polars::Series.new("a", [1, 2, 3, 4])
1970
- # s.take([1, 3])
2398
+ # s.gather([1, 3])
1971
2399
  # # =>
1972
2400
  # # shape: (2,)
1973
2401
  # # Series: 'a' [i64]
@@ -1975,8 +2403,8 @@ module Polars
1975
2403
  # # 2
1976
2404
  # # 4
1977
2405
  # # ]
1978
- def take(indices)
1979
- to_frame.select(Polars.col(name).take(indices)).to_series
2406
+ def gather(indices, null_on_oob: false)
2407
+ super
1980
2408
  end
1981
2409
 
1982
2410
  # Count the null values in this Series.
@@ -2009,21 +2437,71 @@ module Polars
2009
2437
  def has_nulls
2010
2438
  _s.has_nulls
2011
2439
  end
2012
- alias_method :has_validity, :has_nulls
2013
2440
 
2014
2441
  # Check if the Series is empty.
2015
2442
  #
2443
+ # @param ignore_nulls [Boolean]
2444
+ # If true a series containing only nulls will also be considered empty.
2445
+ # The default is false.
2446
+ #
2016
2447
  # @return [Boolean]
2017
2448
  #
2018
2449
  # @example
2019
2450
  # s = Polars::Series.new("a", [])
2020
2451
  # s.is_empty
2021
2452
  # # => true
2022
- def is_empty
2023
- len == 0
2453
+ def is_empty(ignore_nulls: false)
2454
+ if ignore_nulls
2455
+ msg = "the `ignore_nulls` parameter of `Series.is_empty()` is considered unstable."
2456
+ Utils.issue_unstable_warning(msg)
2457
+ end
2458
+
2459
+ _s.is_empty(ignore_nulls: ignore_nulls)
2024
2460
  end
2025
2461
  alias_method :empty?, :is_empty
2026
2462
 
2463
+ # Check if the Series is sorted.
2464
+ #
2465
+ # @param descending [Boolean]
2466
+ # Check if the Series is sorted in descending order
2467
+ # @param nulls_last [Boolean]
2468
+ # Set nulls at the end of the Series in sorted check.
2469
+ #
2470
+ # @return [Boolean]
2471
+ #
2472
+ # @example
2473
+ # s = Polars::Series.new([1, 3, 2])
2474
+ # s.is_sorted
2475
+ # # => false
2476
+ #
2477
+ # @example
2478
+ # s = Polars::Series.new([3, 2, 1])
2479
+ # s.is_sorted(descending: true)
2480
+ # # => true
2481
+ def is_sorted(descending: false, nulls_last: false)
2482
+ _s.is_sorted(descending, nulls_last)
2483
+ end
2484
+ alias_method :sorted?, :is_sorted
2485
+
2486
+ # Negate a boolean Series.
2487
+ #
2488
+ # @return [Series]
2489
+ #
2490
+ # @example
2491
+ # s = Polars::Series.new("a", [true, false, false])
2492
+ # s.not_
2493
+ # # =>
2494
+ # # shape: (3,)
2495
+ # # Series: 'a' [bool]
2496
+ # # [
2497
+ # # false
2498
+ # # true
2499
+ # # true
2500
+ # # ]
2501
+ def not_
2502
+ self.class._from_rbseries(_s.not_)
2503
+ end
2504
+
2027
2505
  # Returns a boolean Series indicating which values are null.
2028
2506
  #
2029
2507
  # @return [Series]
@@ -2144,18 +2622,33 @@ module Polars
2144
2622
 
2145
2623
  # Check if elements of this Series are in the other Series.
2146
2624
  #
2625
+ # @param nulls_equal [Boolean]
2626
+ # If true, treat null as a distinct value. Null values will not propagate.
2627
+ #
2147
2628
  # @return [Series]
2148
2629
  #
2149
2630
  # @example
2150
- # s = Polars::Series.new("a", [1, 2, 3])
2151
- # s2 = Polars::Series.new("b", [2, 4])
2631
+ # s = Polars::Series.new("a", [[1, 2, 3]])
2632
+ # s2 = Polars::Series.new("b", [2, 4, nil])
2152
2633
  # s2.is_in(s)
2153
2634
  # # =>
2154
- # # shape: (2,)
2635
+ # # shape: (3,)
2636
+ # # Series: 'b' [bool]
2637
+ # # [
2638
+ # # true
2639
+ # # false
2640
+ # # null
2641
+ # # ]
2642
+ #
2643
+ # @example
2644
+ # s2.is_in(s, nulls_equal: true)
2645
+ # # =>
2646
+ # # shape: (3,)
2155
2647
  # # Series: 'b' [bool]
2156
2648
  # # [
2157
2649
  # # true
2158
2650
  # # false
2651
+ # # false
2159
2652
  # # ]
2160
2653
  #
2161
2654
  # @example
@@ -2190,7 +2683,7 @@ module Polars
2190
2683
  # # true
2191
2684
  # # false
2192
2685
  # # ]
2193
- def is_in(other)
2686
+ def is_in(other, nulls_equal: false)
2194
2687
  super
2195
2688
  end
2196
2689
  alias_method :in?, :is_in
@@ -2252,7 +2745,27 @@ module Polars
2252
2745
  def is_first_distinct
2253
2746
  super
2254
2747
  end
2255
- alias_method :is_first, :is_first_distinct
2748
+
2749
+ # Return a boolean mask indicating the last occurrence of each distinct value.
2750
+ #
2751
+ # @return [Series]
2752
+ #
2753
+ # @example
2754
+ # s = Polars::Series.new([1, 1, 2, 3, 2])
2755
+ # s.is_last_distinct
2756
+ # # =>
2757
+ # # shape: (5,)
2758
+ # # Series: '' [bool]
2759
+ # # [
2760
+ # # false
2761
+ # # true
2762
+ # # false
2763
+ # # true
2764
+ # # true
2765
+ # # ]
2766
+ def is_last_distinct
2767
+ super
2768
+ end
2256
2769
 
2257
2770
  # Get mask of all duplicated values.
2258
2771
  #
@@ -2278,6 +2791,11 @@ module Polars
2278
2791
  #
2279
2792
  # This means that every item is expanded to a new row.
2280
2793
  #
2794
+ # @param empty_as_null [Boolean]
2795
+ # Explode an empty list into a `null`.
2796
+ # @param keep_nulls [Boolean]
2797
+ # Explode a `null` list into a `null`.
2798
+ #
2281
2799
  # @return [Series]
2282
2800
  #
2283
2801
  # @example
@@ -2294,7 +2812,7 @@ module Polars
2294
2812
  # # 9
2295
2813
  # # 10
2296
2814
  # # ]
2297
- def explode
2815
+ def explode(empty_as_null: true, keep_nulls: true)
2298
2816
  super
2299
2817
  end
2300
2818
 
@@ -2302,7 +2820,7 @@ module Polars
2302
2820
  #
2303
2821
  # @param other [Series]
2304
2822
  # Series to compare with.
2305
- # @param strict [Boolean]
2823
+ # @param check_dtypes [Boolean]
2306
2824
  # Require data types to match.
2307
2825
  # @param check_names [Boolean]
2308
2826
  # Require names to match.
@@ -2318,10 +2836,9 @@ module Polars
2318
2836
  # # => true
2319
2837
  # s.equals(s2)
2320
2838
  # # => false
2321
- def equals(other, strict: false, check_names: false, null_equal: false)
2322
- _s.equals(other._s, strict, check_names, null_equal)
2839
+ def equals(other, check_dtypes: false, check_names: false, null_equal: true)
2840
+ _s.equals(other._s, check_dtypes, check_names, null_equal)
2323
2841
  end
2324
- alias_method :series_equal, :equals
2325
2842
 
2326
2843
  # Return the number of elements in the Series.
2327
2844
  #
@@ -2351,16 +2868,19 @@ module Polars
2351
2868
 
2352
2869
  # Cast between data types.
2353
2870
  #
2354
- # @param dtype [Symbol]
2871
+ # @param dtype [Object]
2355
2872
  # DataType to cast to
2356
2873
  # @param strict [Boolean]
2357
2874
  # Throw an error if a cast could not be done for instance due to an overflow
2875
+ # @param wrap_numerical [Boolean]
2876
+ # If true numeric casts wrap overflowing values instead of
2877
+ # marking the cast as invalid.
2358
2878
  #
2359
2879
  # @return [Series]
2360
2880
  #
2361
2881
  # @example
2362
2882
  # s = Polars::Series.new("a", [true, false, true])
2363
- # s.cast(:u32)
2883
+ # s.cast(Polars::UInt32)
2364
2884
  # # =>
2365
2885
  # # shape: (3,)
2366
2886
  # # Series: 'a' [u32]
@@ -2369,24 +2889,18 @@ module Polars
2369
2889
  # # 0
2370
2890
  # # 1
2371
2891
  # # ]
2372
- def cast(dtype, strict: true)
2373
- super
2892
+ def cast(dtype, strict: true, wrap_numerical: false)
2893
+ dtype = Utils.parse_into_dtype(dtype)
2894
+ self.class._from_rbseries(_s.cast(dtype, strict, wrap_numerical))
2374
2895
  end
2375
2896
 
2376
2897
  # Cast to physical representation of the logical dtype.
2377
2898
  #
2378
- # - `:date` -> `:i32`
2379
- # - `:datetime` -> `:i64`
2380
- # - `:time` -> `:i64`
2381
- # - `:duration` -> `:i64`
2382
- # - `:cat` -> `:u32`
2383
- # - other data types will be left unchanged.
2384
- #
2385
2899
  # @return [Series]
2386
2900
  #
2387
2901
  # @example
2388
2902
  # s = Polars::Series.new("values", ["a", nil, "x", "a"])
2389
- # s.cast(:cat).to_physical
2903
+ # s.cast(Polars::Categorical).to_physical
2390
2904
  # # =>
2391
2905
  # # shape: (4,)
2392
2906
  # # Series: 'values' [u32]
@@ -2457,7 +2971,7 @@ module Polars
2457
2971
  # @return [Series]
2458
2972
  #
2459
2973
  # @example
2460
- # s = Polars::Series.new("a", [1, 2, 3], dtype: :i8)
2974
+ # s = Polars::Series.new("a", [1, 2, 3], dtype: Polars::Int8)
2461
2975
  # s.reverse
2462
2976
  # # =>
2463
2977
  # # shape: (3,)
@@ -2471,77 +2985,123 @@ module Polars
2471
2985
  super
2472
2986
  end
2473
2987
 
2474
- # Check if this Series datatype is numeric.
2988
+ # Get a boolean mask of the values that are between the given lower/upper bounds.
2475
2989
  #
2476
- # @return [Boolean]
2990
+ # @param lower_bound [Object]
2991
+ # Lower bound value. Accepts expression input. Non-expression inputs
2992
+ # (including strings) are parsed as literals.
2993
+ # @param upper_bound [Object]
2994
+ # Upper bound value. Accepts expression input. Non-expression inputs
2995
+ # (including strings) are parsed as literals.
2996
+ # @param closed ['both', 'left', 'right', 'none']
2997
+ # Define which sides of the interval are closed (inclusive).
2477
2998
  #
2478
- # @example
2479
- # s = Polars::Series.new("a", [1, 2, 3])
2480
- # s.is_numeric
2481
- # # => true
2482
- def is_numeric
2483
- [Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, Float32, Float64].include?(dtype)
2484
- end
2485
- alias_method :numeric?, :is_numeric
2486
-
2487
- # Check if this Series datatype is datelike.
2999
+ # @return [Series]
2488
3000
  #
2489
- # @return [Boolean]
3001
+ # @note
3002
+ # If the value of the `lower_bound` is greater than that of the `upper_bound`
3003
+ # then the result will be false, as no value can satisfy the condition.
2490
3004
  #
2491
3005
  # @example
2492
- # s = Polars::Series.new([Date.new(2021, 1, 1), Date.new(2021, 1, 2), Date.new(2021, 1, 3)])
2493
- # s.is_datelike
2494
- # # => true
2495
- def is_datelike
2496
- [Date, Time].include?(dtype) || dtype.is_a?(Datetime) || dtype.is_a?(Duration)
2497
- end
2498
- alias_method :datelike?, :is_datelike
2499
- alias_method :is_temporal, :is_datelike
2500
- alias_method :temporal?, :is_datelike
2501
-
2502
- # Check if this Series has floating point numbers.
3006
+ # s = Polars::Series.new("num", [1, 2, 3, 4, 5])
3007
+ # s.is_between(2, 4)
3008
+ # # =>
3009
+ # # shape: (5,)
3010
+ # # Series: 'num' [bool]
3011
+ # # [
3012
+ # # false
3013
+ # # true
3014
+ # # true
3015
+ # # true
3016
+ # # false
3017
+ # # ]
2503
3018
  #
2504
- # @return [Boolean]
3019
+ # @example Use the `closed` argument to include or exclude the values at the bounds:
3020
+ # s.is_between(2, 4, closed: "left")
3021
+ # # =>
3022
+ # # shape: (5,)
3023
+ # # Series: 'num' [bool]
3024
+ # # [
3025
+ # # false
3026
+ # # true
3027
+ # # true
3028
+ # # false
3029
+ # # false
3030
+ # # ]
2505
3031
  #
2506
- # @example
2507
- # s = Polars::Series.new("a", [1.0, 2.0, 3.0])
2508
- # s.is_float
2509
- # # => true
2510
- def is_float
2511
- [Float32, Float64].include?(dtype)
2512
- end
2513
- alias_method :float?, :is_float
3032
+ # @example You can also use strings as well as numeric/temporal values:
3033
+ # s = Polars::Series.new("s", ["a", "b", "c", "d", "e"])
3034
+ # s.is_between("b", "d", closed: "both")
3035
+ # # =>
3036
+ # # shape: (5,)
3037
+ # # Series: 's' [bool]
3038
+ # # [
3039
+ # # false
3040
+ # # true
3041
+ # # true
3042
+ # # true
3043
+ # # false
3044
+ # # ]
3045
+ def is_between(
3046
+ lower_bound,
3047
+ upper_bound,
3048
+ closed: "both"
3049
+ )
3050
+ if closed == "none"
3051
+ out = (self > lower_bound) & (self < upper_bound)
3052
+ elsif closed == "both"
3053
+ out = (self >= lower_bound) & (self <= upper_bound)
3054
+ elsif closed == "right"
3055
+ out = (self > lower_bound) & (self <= upper_bound)
3056
+ elsif closed == "left"
3057
+ out = (self >= lower_bound) & (self < upper_bound)
3058
+ end
2514
3059
 
2515
- # Check if this Series is a Boolean.
2516
- #
2517
- # @return [Boolean]
2518
- #
2519
- # @example
2520
- # s = Polars::Series.new("a", [true, false, true])
2521
- # s.is_boolean
2522
- # # => true
2523
- def is_boolean
2524
- dtype == Boolean
3060
+ if out.is_a?(Expr)
3061
+ out = F.select(out).to_series
3062
+ end
3063
+
3064
+ out
2525
3065
  end
2526
- alias_method :boolean?, :is_boolean
2527
- alias_method :is_bool, :is_boolean
2528
- alias_method :bool?, :is_boolean
2529
3066
 
2530
- # Check if this Series datatype is a Utf8.
3067
+ # Get a boolean mask of the values being close to the other values.
2531
3068
  #
2532
- # @return [Boolean]
3069
+ # @param abs_tol [Float]
3070
+ # Absolute tolerance. This is the maximum allowed absolute difference between
3071
+ # two values. Must be non-negative.
3072
+ # @param rel_tol [Float]
3073
+ # Relative tolerance. This is the maximum allowed difference between two
3074
+ # values, relative to the larger absolute value. Must be in the range [0, 1).
3075
+ # @param nans_equal [Boolean]
3076
+ # Whether NaN values should be considered equal.
3077
+ #
3078
+ # @return [Series]
2533
3079
  #
2534
3080
  # @example
2535
- # s = Polars::Series.new("x", ["a", "b", "c"])
2536
- # s.is_utf8
2537
- # # => true
2538
- def is_utf8
2539
- dtype == String
3081
+ # s = Polars::Series.new("s", [1.0, 1.2, 1.4, 1.45, 1.6])
3082
+ # s.is_close(1.4, abs_tol: 0.1)
3083
+ # # =>
3084
+ # # shape: (5,)
3085
+ # # Series: 's' [bool]
3086
+ # # [
3087
+ # # false
3088
+ # # false
3089
+ # # true
3090
+ # # true
3091
+ # # false
3092
+ # # ]
3093
+ def is_close(
3094
+ other,
3095
+ abs_tol: 0.0,
3096
+ rel_tol: 1.0e-09,
3097
+ nans_equal: false
3098
+ )
3099
+ F.select(
3100
+ F.lit(self).is_close(
3101
+ other, abs_tol: abs_tol, rel_tol: rel_tol, nans_equal: nans_equal
3102
+ )
3103
+ ).to_series
2540
3104
  end
2541
- alias_method :utf8?, :is_utf8
2542
-
2543
- # def view
2544
- # end
2545
3105
 
2546
3106
  # Convert this Series to a Numo array. This operation clones data but is completely safe.
2547
3107
  #
@@ -2554,29 +3114,7 @@ module Polars
2554
3114
  # # Numo::Int64#shape=[3]
2555
3115
  # # [1, 2, 3]
2556
3116
  def to_numo
2557
- if !has_validity
2558
- if is_datelike
2559
- Numo::RObject.cast(to_a)
2560
- elsif is_numeric
2561
- # TODO make more efficient
2562
- {
2563
- UInt8 => Numo::UInt8,
2564
- UInt16 => Numo::UInt16,
2565
- UInt32 => Numo::UInt32,
2566
- UInt64 => Numo::UInt64,
2567
- Int8 => Numo::Int8,
2568
- Int16 => Numo::Int16,
2569
- Int32 => Numo::Int32,
2570
- Int64 => Numo::Int64,
2571
- Float32 => Numo::SFloat,
2572
- Float64 => Numo::DFloat
2573
- }.fetch(dtype.class).cast(to_a)
2574
- elsif is_boolean
2575
- Numo::Bit.cast(to_a)
2576
- else
2577
- _s.to_numo
2578
- end
2579
- elsif is_datelike
3117
+ if dtype.temporal?
2580
3118
  Numo::RObject.cast(to_a)
2581
3119
  else
2582
3120
  _s.to_numo
@@ -2614,16 +3152,16 @@ module Polars
2614
3152
 
2615
3153
  # Set values at the index locations.
2616
3154
  #
2617
- # @param idx [Object]
3155
+ # @param indices [Object]
2618
3156
  # Integers representing the index locations.
2619
- # @param value [Object]
3157
+ # @param values [Object]
2620
3158
  # Replacement values.
2621
3159
  #
2622
3160
  # @return [Series]
2623
3161
  #
2624
3162
  # @example
2625
3163
  # s = Polars::Series.new("a", [1, 2, 3])
2626
- # s.set_at_idx(1, 10)
3164
+ # s.scatter(1, 10)
2627
3165
  # # =>
2628
3166
  # # shape: (3,)
2629
3167
  # # Series: 'a' [i64]
@@ -2632,56 +3170,100 @@ module Polars
2632
3170
  # # 10
2633
3171
  # # 3
2634
3172
  # # ]
2635
- def scatter(idx, value)
2636
- if idx.is_a?(Integer)
2637
- idx = [idx]
3173
+ def scatter(indices, values)
3174
+ if indices.is_a?(Integer)
3175
+ indices = [indices]
2638
3176
  end
2639
- if idx.length == 0
3177
+ if indices.length == 0
2640
3178
  return self
2641
3179
  end
2642
3180
 
2643
- idx = Series.new("", idx)
2644
- if value.is_a?(Integer) || value.is_a?(Float) || Utils.bool?(value) || value.is_a?(::String) || value.nil?
2645
- value = Series.new("", [value])
3181
+ indices = Series.new("", indices)
3182
+ if values.is_a?(Integer) || values.is_a?(Float) || Utils.bool?(values) || values.is_a?(::String) || values.nil?
3183
+ values = Series.new("", [values])
2646
3184
 
2647
3185
  # if we need to set more than a single value, we extend it
2648
- if idx.length > 0
2649
- value = value.extend_constant(value[0], idx.length - 1)
3186
+ if indices.length > 0
3187
+ values = values.extend_constant(values[0], indices.length - 1)
2650
3188
  end
2651
- elsif !value.is_a?(Series)
2652
- value = Series.new("", value)
3189
+ elsif !values.is_a?(Series)
3190
+ values = Series.new("", values)
2653
3191
  end
2654
- _s.scatter(idx._s, value._s)
3192
+ _s.scatter(indices._s, values._s)
2655
3193
  self
2656
3194
  end
2657
- alias_method :set_at_idx, :scatter
3195
+
3196
+ # Get the index of the first occurrence of a value, or `nil` if it's not found.
3197
+ #
3198
+ # @param element [Object]
3199
+ # Value to find.
3200
+ #
3201
+ # @return [Object]
3202
+ #
3203
+ # @example
3204
+ # s = Polars::Series.new("a", [1, nil, 17])
3205
+ # s.index_of(17)
3206
+ # # => 2
3207
+ #
3208
+ # @example
3209
+ # s.index_of(nil) # search for a null
3210
+ # # => 1
3211
+ #
3212
+ # @example
3213
+ # s.index_of(55).nil?
3214
+ # # => true
3215
+ def index_of(element)
3216
+ F.select(F.lit(self).index_of(element)).item
3217
+ end
2658
3218
 
2659
3219
  # Create an empty copy of the current Series.
2660
3220
  #
2661
3221
  # The copy has identical name/dtype but no data.
2662
3222
  #
3223
+ # @param n [Integer]
3224
+ # Number of (empty) elements to return in the cleared frame.
3225
+ #
2663
3226
  # @return [Series]
2664
3227
  #
2665
3228
  # @example
2666
3229
  # s = Polars::Series.new("a", [nil, true, false])
2667
- # s.cleared
3230
+ # s.clear
2668
3231
  # # =>
2669
3232
  # # shape: (0,)
2670
3233
  # # Series: 'a' [bool]
2671
3234
  # # [
2672
3235
  # # ]
2673
- def cleared
2674
- len > 0 ? limit(0) : clone
2675
- end
2676
-
2677
- # clone handled by initialize_copy
2678
-
2679
- # Fill floating point NaN value with a fill value.
2680
3236
  #
2681
- # @param fill_value [Object]
2682
- # Value used to fill nan values.
2683
- #
2684
- # @return [Series]
3237
+ # @example
3238
+ # s.clear(n: 2)
3239
+ # # =>
3240
+ # # shape: (2,)
3241
+ # # Series: 'a' [bool]
3242
+ # # [
3243
+ # # null
3244
+ # # null
3245
+ # # ]
3246
+ def clear(n: 0)
3247
+ if n < 0
3248
+ msg = "`n` should be greater than or equal to 0, got #{n}"
3249
+ raise ArgumentError, msg
3250
+ end
3251
+ # faster path
3252
+ if n == 0
3253
+ return self.class._from_rbseries(_s.clear)
3254
+ end
3255
+ s = len > 0 ? self.class.new(name, [], dtype: dtype) : clone
3256
+ n > 0 ? s.extend_constant(nil, n) : s
3257
+ end
3258
+
3259
+ # clone handled by initialize_copy
3260
+
3261
+ # Fill floating point NaN value with a fill value.
3262
+ #
3263
+ # @param value [Object]
3264
+ # Value used to fill nan values.
3265
+ #
3266
+ # @return [Series]
2685
3267
  #
2686
3268
  # @example
2687
3269
  # s = Polars::Series.new("a", [1.0, 2.0, 3.0, Float::NAN])
@@ -2695,7 +3277,7 @@ module Polars
2695
3277
  # # 3.0
2696
3278
  # # 0.0
2697
3279
  # # ]
2698
- def fill_nan(fill_value)
3280
+ def fill_nan(value)
2699
3281
  super
2700
3282
  end
2701
3283
 
@@ -2751,6 +3333,30 @@ module Polars
2751
3333
  super
2752
3334
  end
2753
3335
 
3336
+ # Fill missing values with the next non-null value.
3337
+ #
3338
+ # This is an alias of `.fill_null(strategy: "backward")`.
3339
+ #
3340
+ # @param limit [Integer]
3341
+ # The number of consecutive null values to backward fill.
3342
+ #
3343
+ # @return [Series]
3344
+ def backward_fill(limit: nil)
3345
+ fill_null(strategy: "backward", limit: limit)
3346
+ end
3347
+
3348
+ # Fill missing values with the next non-null value.
3349
+ #
3350
+ # This is an alias of `.fill_null(strategy: "forward")`.
3351
+ #
3352
+ # @param limit [Integer]
3353
+ # The number of consecutive null values to forward fill.
3354
+ #
3355
+ # @return [Series]
3356
+ def forward_fill(limit: nil)
3357
+ fill_null(strategy: "forward", limit: limit)
3358
+ end
3359
+
2754
3360
  # Rounds down to the nearest integer value.
2755
3361
  #
2756
3362
  # Only works on floating point Series.
@@ -2793,10 +3399,59 @@ module Polars
2793
3399
  super
2794
3400
  end
2795
3401
 
3402
+ # Truncate numeric data toward zero to `decimals` number of decimal places.
3403
+ #
3404
+ # @param decimals [Integer]
3405
+ # Number of decimal places to truncate to.
3406
+ #
3407
+ # @return [Series]
3408
+ #
3409
+ # @note
3410
+ # Truncation discards the fractional part beyond the given number of decimals.
3411
+ # For example, when rounding to 0 decimals 0.25, -0.25, 0.99, and -0.99 will
3412
+ # all round to 0. When rounding to 1 decimal 1.9999 rounds to 1.9 and -1.9999
3413
+ # rounds to -1.9. There is no tiebreak behaviour at midpoint values as there
3414
+ # is with :meth:`round` so 0.5 and -0.5 will also round to 0 when decimals=1.
3415
+ #
3416
+ # @note
3417
+ # This method performs numeric truncation. For truncating temporal
3418
+ # data (dates/datetimes), use :func:`Series.dt.truncate` instead.
3419
+ #
3420
+ # @example
3421
+ # s = Polars::Series.new("a", [1.12345, 2.56789, 3.991234])
3422
+ # s.truncate(2)
3423
+ # # =>
3424
+ # # shape: (3,)
3425
+ # # Series: 'a' [f64]
3426
+ # # [
3427
+ # # 1.12
3428
+ # # 2.56
3429
+ # # 3.99
3430
+ # # ]
3431
+ #
3432
+ # @example
3433
+ # s = Polars::Series.new("a", [-1.78, 2.56, -3.99])
3434
+ # s.truncate(0)
3435
+ # # =>
3436
+ # # shape: (3,)
3437
+ # # Series: 'a' [f64]
3438
+ # # [
3439
+ # # -1.0
3440
+ # # 2.0
3441
+ # # -3.0
3442
+ # # ]
3443
+ def truncate(decimals = 0)
3444
+ super
3445
+ end
3446
+
2796
3447
  # Round underlying floating point data by `decimals` digits.
2797
3448
  #
3449
+ # The default rounding mode is "half to even" (also known as "bankers' rounding").
3450
+ #
2798
3451
  # @param decimals [Integer]
2799
- # number of decimals to round by.
3452
+ # Number of decimals to round by.
3453
+ # @param mode ['half_to_even', 'half_away_from_zero']
3454
+ # Rounding mode.
2800
3455
  #
2801
3456
  # @return [Series]
2802
3457
  #
@@ -2811,7 +3466,29 @@ module Polars
2811
3466
  # # 2.57
2812
3467
  # # 3.9
2813
3468
  # # ]
2814
- def round(decimals = 0)
3469
+ def round(decimals = 0, mode: "half_to_even")
3470
+ super
3471
+ end
3472
+
3473
+ # Round to a number of significant figures.
3474
+ #
3475
+ # @param digits [Integer]
3476
+ # Number of significant figures to round to.
3477
+ #
3478
+ # @return [Series]
3479
+ #
3480
+ # @example
3481
+ # s = Polars::Series.new([0.01234, 3.333, 3450.0])
3482
+ # s.round_sig_figs(2)
3483
+ # # =>
3484
+ # # shape: (3,)
3485
+ # # Series: '' [f64]
3486
+ # # [
3487
+ # # 0.012
3488
+ # # 3.3
3489
+ # # 3500.0
3490
+ # # ]
3491
+ def round_sig_figs(digits)
2815
3492
  super
2816
3493
  end
2817
3494
 
@@ -2842,6 +3519,9 @@ module Polars
2842
3519
  #
2843
3520
  # Can return multiple Values.
2844
3521
  #
3522
+ # @param maintain_order [Boolean]
3523
+ # Maintain order of data. This requires more work.
3524
+ #
2845
3525
  # @return [Series]
2846
3526
  #
2847
3527
  # @example
@@ -2853,7 +3533,7 @@ module Polars
2853
3533
  # # [
2854
3534
  # # 2
2855
3535
  # # ]
2856
- def mode
3536
+ def mode(maintain_order: false)
2857
3537
  super
2858
3538
  end
2859
3539
 
@@ -2935,6 +3615,25 @@ module Polars
2935
3615
  super
2936
3616
  end
2937
3617
 
3618
+ # Compute the element-wise value for the cotangent.
3619
+ #
3620
+ # @return [Series]
3621
+ #
3622
+ # @example
3623
+ # s = Polars::Series.new("a", [0.0, Math::PI / 2.0, Math::PI])
3624
+ # s.cot
3625
+ # # =>
3626
+ # # shape: (3,)
3627
+ # # Series: 'a' [f64]
3628
+ # # [
3629
+ # # inf
3630
+ # # 6.1232e-17
3631
+ # # -8.1656e15
3632
+ # # ]
3633
+ def cot
3634
+ super
3635
+ end
3636
+
2938
3637
  # Compute the element-wise value for the inverse sine.
2939
3638
  #
2940
3639
  # @return [Series]
@@ -2953,7 +3652,6 @@ module Polars
2953
3652
  def arcsin
2954
3653
  super
2955
3654
  end
2956
- alias_method :asin, :arcsin
2957
3655
 
2958
3656
  # Compute the element-wise value for the inverse cosine.
2959
3657
  #
@@ -2973,7 +3671,6 @@ module Polars
2973
3671
  def arccos
2974
3672
  super
2975
3673
  end
2976
- alias_method :acos, :arccos
2977
3674
 
2978
3675
  # Compute the element-wise value for the inverse tangent.
2979
3676
  #
@@ -2993,7 +3690,6 @@ module Polars
2993
3690
  def arctan
2994
3691
  super
2995
3692
  end
2996
- alias_method :atan, :arctan
2997
3693
 
2998
3694
  # Compute the element-wise value for the inverse hyperbolic sine.
2999
3695
  #
@@ -3013,7 +3709,6 @@ module Polars
3013
3709
  def arcsinh
3014
3710
  super
3015
3711
  end
3016
- alias_method :asinh, :arcsinh
3017
3712
 
3018
3713
  # Compute the element-wise value for the inverse hyperbolic cosine.
3019
3714
  #
@@ -3034,7 +3729,6 @@ module Polars
3034
3729
  def arccosh
3035
3730
  super
3036
3731
  end
3037
- alias_method :acosh, :arccosh
3038
3732
 
3039
3733
  # Compute the element-wise value for the inverse hyperbolic tangent.
3040
3734
  #
@@ -3058,7 +3752,6 @@ module Polars
3058
3752
  def arctanh
3059
3753
  super
3060
3754
  end
3061
- alias_method :atanh, :arctanh
3062
3755
 
3063
3756
  # Compute the element-wise value for the hyperbolic sine.
3064
3757
  #
@@ -3135,7 +3828,7 @@ module Polars
3135
3828
  #
3136
3829
  # @example
3137
3830
  # s = Polars::Series.new("a", [1, 2, 3])
3138
- # s.map_elements { |x| x + 10 }
3831
+ # s.map_elements(return_dtype: Polars::Int64) { |x| x + 10 }
3139
3832
  # # =>
3140
3833
  # # shape: (3,)
3141
3834
  # # Series: 'a' [i64]
@@ -3144,21 +3837,23 @@ module Polars
3144
3837
  # # 12
3145
3838
  # # 13
3146
3839
  # # ]
3147
- def map_elements(return_dtype: nil, skip_nulls: true, &func)
3840
+ def map_elements(return_dtype: nil, skip_nulls: true, &function)
3148
3841
  if return_dtype.nil?
3149
3842
  pl_return_dtype = nil
3150
3843
  else
3151
- pl_return_dtype = Utils.rb_type_to_dtype(return_dtype)
3844
+ pl_return_dtype = Utils.parse_into_dtype(return_dtype)
3152
3845
  end
3153
- Utils.wrap_s(_s.apply_lambda(func, pl_return_dtype, skip_nulls))
3846
+ Utils.wrap_s(_s.map_elements(function, pl_return_dtype, skip_nulls))
3154
3847
  end
3155
3848
  alias_method :map, :map_elements
3156
- alias_method :apply, :map_elements
3157
3849
 
3158
3850
  # Shift the values by a given period.
3159
3851
  #
3160
- # @param periods [Integer]
3852
+ # @param n [Integer]
3161
3853
  # Number of places to shift (may be negative).
3854
+ # @param fill_value [Object]
3855
+ # Fill the resulting null values with this value. Accepts scalar expression
3856
+ # input. Non-expression inputs are parsed as literals.
3162
3857
  #
3163
3858
  # @return [Series]
3164
3859
  #
@@ -3184,19 +3879,7 @@ module Polars
3184
3879
  # # 3
3185
3880
  # # null
3186
3881
  # # ]
3187
- def shift(periods = 1)
3188
- super
3189
- end
3190
-
3191
- # Shift the values by a given period and fill the resulting null values.
3192
- #
3193
- # @param periods [Integer]
3194
- # Number of places to shift (may be negative).
3195
- # @param fill_value [Object]
3196
- # Fill None values with the result of this expression.
3197
- #
3198
- # @return [Series]
3199
- def shift_and_fill(periods, fill_value)
3882
+ def shift(n = 1, fill_value: nil)
3200
3883
  super
3201
3884
  end
3202
3885
 
@@ -3244,6 +3927,90 @@ module Polars
3244
3927
  Utils.wrap_s(_s.zip_with(mask._s, other._s))
3245
3928
  end
3246
3929
 
3930
+ # Compute a rolling min based on another series.
3931
+ #
3932
+ # @note
3933
+ # This functionality is considered **unstable**. It may be changed
3934
+ # at any point without it being considered a breaking change.
3935
+ #
3936
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed: "right"`
3937
+ # (the default) means the windows will be:
3938
+ #
3939
+ # - (t_0 - window_size, t_0]
3940
+ # - (t_1 - window_size, t_1]
3941
+ # - ...
3942
+ # - (t_n - window_size, t_n]
3943
+ #
3944
+ # @param by [Object]
3945
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
3946
+ # or `Int32` data type (note that the integral ones require using `'i'`
3947
+ # in `window size`).
3948
+ # @param window_size [String]
3949
+ # The length of the window. Can be a dynamic temporal
3950
+ # size indicated by a timedelta or the following string language:
3951
+ #
3952
+ # - 1ns (1 nanosecond)
3953
+ # - 1us (1 microsecond)
3954
+ # - 1ms (1 millisecond)
3955
+ # - 1s (1 second)
3956
+ # - 1m (1 minute)
3957
+ # - 1h (1 hour)
3958
+ # - 1d (1 calendar day)
3959
+ # - 1w (1 calendar week)
3960
+ # - 1mo (1 calendar month)
3961
+ # - 1q (1 calendar quarter)
3962
+ # - 1y (1 calendar year)
3963
+ # - 1i (1 index count)
3964
+ #
3965
+ # By "calendar day", we mean the corresponding time on the next day
3966
+ # (which may not be 24 hours, due to daylight savings). Similarly for
3967
+ # "calendar week", "calendar month", "calendar quarter", and
3968
+ # "calendar year".
3969
+ # @param min_samples [Integer]
3970
+ # The number of values in the window that should be non-null before computing
3971
+ # a result.
3972
+ # @param closed ['left', 'right', 'both', 'none']
3973
+ # Define which sides of the temporal interval are closed (inclusive),
3974
+ # defaults to `'right'`.
3975
+ #
3976
+ # @return [Series]
3977
+ #
3978
+ # @note
3979
+ # If you want to compute multiple aggregation statistics over the same dynamic
3980
+ # window, consider using `rolling` - this method can cache the window size
3981
+ # computation.
3982
+ #
3983
+ # @example
3984
+ # start = DateTime.new(2001, 1, 1)
3985
+ # stop = DateTime.new(2001, 1, 2)
3986
+ # s = Polars::Series.new("index", 25.times.to_a)
3987
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
3988
+ # s.rolling_min_by(d, "3h")
3989
+ # # =>
3990
+ # # shape: (25,)
3991
+ # # Series: 'index' [i64]
3992
+ # # [
3993
+ # # 0
3994
+ # # 0
3995
+ # # 0
3996
+ # # 1
3997
+ # # 2
3998
+ # # …
3999
+ # # 18
4000
+ # # 19
4001
+ # # 20
4002
+ # # 21
4003
+ # # 22
4004
+ # # ]
4005
+ def rolling_min_by(
4006
+ by,
4007
+ window_size,
4008
+ min_samples: 1,
4009
+ closed: "right"
4010
+ )
4011
+ super
4012
+ end
4013
+
3247
4014
  # Apply a rolling min (moving min) over the values in this array.
3248
4015
  #
3249
4016
  # A window of length `window_size` will traverse the array. The values that fill
@@ -3255,9 +4022,9 @@ module Polars
3255
4022
  # @param weights [Array]
3256
4023
  # An optional slice with the same length as the window that will be multiplied
3257
4024
  # elementwise with the values in the window.
3258
- # @param min_periods [Integer]
4025
+ # @param min_samples [Integer]
3259
4026
  # The number of values in the window that should be non-null before computing
3260
- # a result. If None, it will be set equal to window size.
4027
+ # a result. If nil, it will be set equal to window size.
3261
4028
  # @param center [Boolean]
3262
4029
  # Set the labels at the center of the window
3263
4030
  #
@@ -3279,12 +4046,96 @@ module Polars
3279
4046
  def rolling_min(
3280
4047
  window_size,
3281
4048
  weights: nil,
3282
- min_periods: nil,
4049
+ min_samples: nil,
3283
4050
  center: false
3284
4051
  )
3285
4052
  super
3286
4053
  end
3287
4054
 
4055
+ # Compute a rolling max based on another series.
4056
+ #
4057
+ # @note
4058
+ # This functionality is considered **unstable**. It may be changed
4059
+ # at any point without it being considered a breaking change.
4060
+ #
4061
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed="right"`
4062
+ # (the default) means the windows will be:
4063
+ #
4064
+ # - (t_0 - window_size, t_0]
4065
+ # - (t_1 - window_size, t_1]
4066
+ # - ...
4067
+ # - (t_n - window_size, t_n]
4068
+ #
4069
+ # @param by [Object]
4070
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4071
+ # or `Int32` data type (note that the integral ones require using `'i'`
4072
+ # in `window size`).
4073
+ # @param window_size [String]
4074
+ # The length of the window. Can be a dynamic temporal
4075
+ # size indicated by a timedelta or the following string language:
4076
+ #
4077
+ # - 1ns (1 nanosecond)
4078
+ # - 1us (1 microsecond)
4079
+ # - 1ms (1 millisecond)
4080
+ # - 1s (1 second)
4081
+ # - 1m (1 minute)
4082
+ # - 1h (1 hour)
4083
+ # - 1d (1 calendar day)
4084
+ # - 1w (1 calendar week)
4085
+ # - 1mo (1 calendar month)
4086
+ # - 1q (1 calendar quarter)
4087
+ # - 1y (1 calendar year)
4088
+ # - 1i (1 index count)
4089
+ #
4090
+ # By "calendar day", we mean the corresponding time on the next day
4091
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4092
+ # "calendar week", "calendar month", "calendar quarter", and
4093
+ # "calendar year".
4094
+ # @param min_samples [Integer]
4095
+ # The number of values in the window that should be non-null before computing
4096
+ # a result.
4097
+ # @param closed ['left', 'right', 'both', 'none']
4098
+ # Define which sides of the temporal interval are closed (inclusive),
4099
+ # defaults to `'right'`.
4100
+ #
4101
+ # @return [Series]
4102
+ #
4103
+ # @note
4104
+ # If you want to compute multiple aggregation statistics over the same dynamic
4105
+ # window, consider using `rolling` - this method can cache the window size
4106
+ # computation.
4107
+ #
4108
+ # @example
4109
+ # start = DateTime.new(2001, 1, 1)
4110
+ # stop = DateTime.new(2001, 1, 2)
4111
+ # s = Polars::Series.new("index", 25.times.to_a)
4112
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4113
+ # s.rolling_max_by(d, "3h")
4114
+ # # =>
4115
+ # # shape: (25,)
4116
+ # # Series: 'index' [i64]
4117
+ # # [
4118
+ # # 0
4119
+ # # 1
4120
+ # # 2
4121
+ # # 3
4122
+ # # 4
4123
+ # # …
4124
+ # # 20
4125
+ # # 21
4126
+ # # 22
4127
+ # # 23
4128
+ # # 24
4129
+ # # ]
4130
+ def rolling_max_by(
4131
+ by,
4132
+ window_size,
4133
+ min_samples: 1,
4134
+ closed: "right"
4135
+ )
4136
+ super
4137
+ end
4138
+
3288
4139
  # Apply a rolling max (moving max) over the values in this array.
3289
4140
  #
3290
4141
  # A window of length `window_size` will traverse the array. The values that fill
@@ -3296,9 +4147,9 @@ module Polars
3296
4147
  # @param weights [Array]
3297
4148
  # An optional slice with the same length as the window that will be multiplied
3298
4149
  # elementwise with the values in the window.
3299
- # @param min_periods [Integer]
4150
+ # @param min_samples [Integer]
3300
4151
  # The number of values in the window that should be non-null before computing
3301
- # a result. If None, it will be set equal to window size.
4152
+ # a result. If nil, it will be set equal to window size.
3302
4153
  # @param center [Boolean]
3303
4154
  # Set the labels at the center of the window
3304
4155
  #
@@ -3320,12 +4171,96 @@ module Polars
3320
4171
  def rolling_max(
3321
4172
  window_size,
3322
4173
  weights: nil,
3323
- min_periods: nil,
4174
+ min_samples: nil,
3324
4175
  center: false
3325
4176
  )
3326
4177
  super
3327
4178
  end
3328
4179
 
4180
+ # Compute a rolling mean based on another series.
4181
+ #
4182
+ # @note
4183
+ # This functionality is considered **unstable**. It may be changed
4184
+ # at any point without it being considered a breaking change.
4185
+ #
4186
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed: "right"`
4187
+ # (the default) means the windows will be:
4188
+ #
4189
+ # - (t_0 - window_size, t_0]
4190
+ # - (t_1 - window_size, t_1]
4191
+ # - ...
4192
+ # - (t_n - window_size, t_n]
4193
+ #
4194
+ # @param by [Object]
4195
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4196
+ # or `Int32` data type (note that the integral ones require using `'i'`
4197
+ # in `window size`).
4198
+ # @param window_size [String]
4199
+ # The length of the window. Can be a dynamic temporal
4200
+ # size indicated by a timedelta or the following string language:
4201
+ #
4202
+ # - 1ns (1 nanosecond)
4203
+ # - 1us (1 microsecond)
4204
+ # - 1ms (1 millisecond)
4205
+ # - 1s (1 second)
4206
+ # - 1m (1 minute)
4207
+ # - 1h (1 hour)
4208
+ # - 1d (1 calendar day)
4209
+ # - 1w (1 calendar week)
4210
+ # - 1mo (1 calendar month)
4211
+ # - 1q (1 calendar quarter)
4212
+ # - 1y (1 calendar year)
4213
+ # - 1i (1 index count)
4214
+ #
4215
+ # By "calendar day", we mean the corresponding time on the next day
4216
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4217
+ # "calendar week", "calendar month", "calendar quarter", and
4218
+ # "calendar year".
4219
+ # @param min_samples [Integer]
4220
+ # The number of values in the window that should be non-null before computing
4221
+ # a result.
4222
+ # @param closed ['left', 'right', 'both', 'none']
4223
+ # Define which sides of the temporal interval are closed (inclusive),
4224
+ # defaults to `'right'`.
4225
+ #
4226
+ # @return [Series]
4227
+ #
4228
+ # @note
4229
+ # If you want to compute multiple aggregation statistics over the same dynamic
4230
+ # window, consider using `rolling` - this method can cache the window size
4231
+ # computation.
4232
+ #
4233
+ # @example
4234
+ # start = DateTime.new(2001, 1, 1)
4235
+ # stop = DateTime.new(2001, 1, 2)
4236
+ # s = Polars::Series.new("index", 25.times.to_a)
4237
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4238
+ # s.rolling_mean_by(d, "3h")
4239
+ # # =>
4240
+ # # shape: (25,)
4241
+ # # Series: 'index' [f64]
4242
+ # # [
4243
+ # # 0.0
4244
+ # # 0.5
4245
+ # # 1.0
4246
+ # # 2.0
4247
+ # # 3.0
4248
+ # # …
4249
+ # # 19.0
4250
+ # # 20.0
4251
+ # # 21.0
4252
+ # # 22.0
4253
+ # # 23.0
4254
+ # # ]
4255
+ def rolling_mean_by(
4256
+ by,
4257
+ window_size,
4258
+ min_samples: 1,
4259
+ closed: "right"
4260
+ )
4261
+ super
4262
+ end
4263
+
3329
4264
  # Apply a rolling mean (moving mean) over the values in this array.
3330
4265
  #
3331
4266
  # A window of length `window_size` will traverse the array. The values that fill
@@ -3337,9 +4272,9 @@ module Polars
3337
4272
  # @param weights [Array]
3338
4273
  # An optional slice with the same length as the window that will be multiplied
3339
4274
  # elementwise with the values in the window.
3340
- # @param min_periods [Integer]
4275
+ # @param min_samples [Integer]
3341
4276
  # The number of values in the window that should be non-null before computing
3342
- # a result. If None, it will be set equal to window size.
4277
+ # a result. If nil, it will be set equal to window size.
3343
4278
  # @param center [Boolean]
3344
4279
  # Set the labels at the center of the window
3345
4280
  #
@@ -3361,12 +4296,96 @@ module Polars
3361
4296
  def rolling_mean(
3362
4297
  window_size,
3363
4298
  weights: nil,
3364
- min_periods: nil,
4299
+ min_samples: nil,
3365
4300
  center: false
3366
4301
  )
3367
4302
  super
3368
4303
  end
3369
4304
 
4305
+ # Compute a rolling sum based on another series.
4306
+ #
4307
+ # @note
4308
+ # This functionality is considered **unstable**. It may be changed
4309
+ # at any point without it being considered a breaking change.
4310
+ #
4311
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed: "right"`
4312
+ # (the default) means the windows will be:
4313
+ #
4314
+ # - (t_0 - window_size, t_0]
4315
+ # - (t_1 - window_size, t_1]
4316
+ # - ...
4317
+ # - (t_n - window_size, t_n]
4318
+ #
4319
+ # @param by [Object]
4320
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4321
+ # or `Int32` data type (note that the integral ones require using `'i'`
4322
+ # in `window size`).
4323
+ # @param window_size [String]
4324
+ # The length of the window. Can be a dynamic temporal
4325
+ # size indicated by a timedelta or the following string language:
4326
+ #
4327
+ # - 1ns (1 nanosecond)
4328
+ # - 1us (1 microsecond)
4329
+ # - 1ms (1 millisecond)
4330
+ # - 1s (1 second)
4331
+ # - 1m (1 minute)
4332
+ # - 1h (1 hour)
4333
+ # - 1d (1 calendar day)
4334
+ # - 1w (1 calendar week)
4335
+ # - 1mo (1 calendar month)
4336
+ # - 1q (1 calendar quarter)
4337
+ # - 1y (1 calendar year)
4338
+ # - 1i (1 index count)
4339
+ #
4340
+ # By "calendar day", we mean the corresponding time on the next day
4341
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4342
+ # "calendar week", "calendar month", "calendar quarter", and
4343
+ # "calendar year".
4344
+ # @param min_samples [Integer]
4345
+ # The number of values in the window that should be non-null before computing
4346
+ # a result.
4347
+ # @param closed ['left', 'right', 'both', 'none']
4348
+ # Define which sides of the temporal interval are closed (inclusive),
4349
+ # defaults to `'right'`.
4350
+ #
4351
+ # @return [Series]
4352
+ #
4353
+ # @note
4354
+ # If you want to compute multiple aggregation statistics over the same dynamic
4355
+ # window, consider using `rolling` - this method can cache the window size
4356
+ # computation.
4357
+ #
4358
+ # @example
4359
+ # start = DateTime.new(2001, 1, 1)
4360
+ # stop = DateTime.new(2001, 1, 2)
4361
+ # s = Polars::Series.new("index", 25.times.to_a)
4362
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4363
+ # s.rolling_sum_by(d, "3h")
4364
+ # # =>
4365
+ # # shape: (25,)
4366
+ # # Series: 'index' [i64]
4367
+ # # [
4368
+ # # 0
4369
+ # # 1
4370
+ # # 3
4371
+ # # 6
4372
+ # # 9
4373
+ # # …
4374
+ # # 57
4375
+ # # 60
4376
+ # # 63
4377
+ # # 66
4378
+ # # 69
4379
+ # # ]
4380
+ def rolling_sum_by(
4381
+ by,
4382
+ window_size,
4383
+ min_samples: 0,
4384
+ closed: "right"
4385
+ )
4386
+ super
4387
+ end
4388
+
3370
4389
  # Apply a rolling sum (moving sum) over the values in this array.
3371
4390
  #
3372
4391
  # A window of length `window_size` will traverse the array. The values that fill
@@ -3378,9 +4397,9 @@ module Polars
3378
4397
  # @param weights [Array]
3379
4398
  # An optional slice with the same length as the window that will be multiplied
3380
4399
  # elementwise with the values in the window.
3381
- # @param min_periods [Integer]
4400
+ # @param min_samples [Integer]
3382
4401
  # The number of values in the window that should be non-null before computing
3383
- # a result. If None, it will be set equal to window size.
4402
+ # a result. If nil, it will be set equal to window size.
3384
4403
  # @param center [Boolean]
3385
4404
  # Set the labels at the center of the window
3386
4405
  #
@@ -3402,12 +4421,99 @@ module Polars
3402
4421
  def rolling_sum(
3403
4422
  window_size,
3404
4423
  weights: nil,
3405
- min_periods: nil,
4424
+ min_samples: nil,
3406
4425
  center: false
3407
4426
  )
3408
4427
  super
3409
4428
  end
3410
4429
 
4430
+ # Compute a rolling standard deviation based on another series.
4431
+ #
4432
+ # @note
4433
+ # This functionality is considered **unstable**. It may be changed
4434
+ # at any point without it being considered a breaking change.
4435
+ #
4436
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed="right"`
4437
+ # (the default) means the windows will be:
4438
+ #
4439
+ # - (t_0 - window_size, t_0]
4440
+ # - (t_1 - window_size, t_1]
4441
+ # - ...
4442
+ # - (t_n - window_size, t_n]
4443
+ #
4444
+ # @param by [Object]
4445
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4446
+ # or `Int32` data type (note that the integral ones require using `'i'`
4447
+ # in `window size`).
4448
+ # @param window_size [String]
4449
+ # The length of the window. Can be a dynamic temporal
4450
+ # size indicated by a timedelta or the following string language:
4451
+ #
4452
+ # - 1ns (1 nanosecond)
4453
+ # - 1us (1 microsecond)
4454
+ # - 1ms (1 millisecond)
4455
+ # - 1s (1 second)
4456
+ # - 1m (1 minute)
4457
+ # - 1h (1 hour)
4458
+ # - 1d (1 calendar day)
4459
+ # - 1w (1 calendar week)
4460
+ # - 1mo (1 calendar month)
4461
+ # - 1q (1 calendar quarter)
4462
+ # - 1y (1 calendar year)
4463
+ # - 1i (1 index count)
4464
+ #
4465
+ # By "calendar day", we mean the corresponding time on the next day
4466
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4467
+ # "calendar week", "calendar month", "calendar quarter", and
4468
+ # "calendar year".
4469
+ # @param min_samples [Integer]
4470
+ # The number of values in the window that should be non-null before computing
4471
+ # a result.
4472
+ # @param closed ['left', 'right', 'both', 'none']
4473
+ # Define which sides of the temporal interval are closed (inclusive),
4474
+ # defaults to `'right'`.
4475
+ # @param ddof [Integer]
4476
+ # "Delta Degrees of Freedom": The divisor for a length N window is N - ddof
4477
+ #
4478
+ # @return [Series]
4479
+ #
4480
+ # @note
4481
+ # If you want to compute multiple aggregation statistics over the same dynamic
4482
+ # window, consider using `rolling` - this method can cache the window size
4483
+ # computation.
4484
+ #
4485
+ # @example
4486
+ # start = DateTime.new(2001, 1, 1)
4487
+ # stop = DateTime.new(2001, 1, 2)
4488
+ # s = Polars::Series.new("index", 25.times.to_a)
4489
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4490
+ # s.rolling_std_by(d, "3h")
4491
+ # # =>
4492
+ # # shape: (25,)
4493
+ # # Series: 'index' [f64]
4494
+ # # [
4495
+ # # null
4496
+ # # 0.707107
4497
+ # # 1.0
4498
+ # # 1.0
4499
+ # # 1.0
4500
+ # # …
4501
+ # # 1.0
4502
+ # # 1.0
4503
+ # # 1.0
4504
+ # # 1.0
4505
+ # # 1.0
4506
+ # # ]
4507
+ def rolling_std_by(
4508
+ by,
4509
+ window_size,
4510
+ min_samples: 1,
4511
+ closed: "right",
4512
+ ddof: 1
4513
+ )
4514
+ super
4515
+ end
4516
+
3411
4517
  # Compute a rolling std dev.
3412
4518
  #
3413
4519
  # A window of length `window_size` will traverse the array. The values that fill
@@ -3419,11 +4525,13 @@ module Polars
3419
4525
  # @param weights [Array]
3420
4526
  # An optional slice with the same length as the window that will be multiplied
3421
4527
  # elementwise with the values in the window.
3422
- # @param min_periods [Integer]
4528
+ # @param min_samples [Integer]
3423
4529
  # The number of values in the window that should be non-null before computing
3424
- # a result. If None, it will be set equal to window size.
4530
+ # a result. If nil, it will be set equal to window size.
3425
4531
  # @param center [Boolean]
3426
4532
  # Set the labels at the center of the window
4533
+ # @param ddof [Integer]
4534
+ # "Delta Degrees of Freedom": The divisor for a length N window is N - ddof
3427
4535
  #
3428
4536
  # @return [Series]
3429
4537
  #
@@ -3444,13 +4552,100 @@ module Polars
3444
4552
  def rolling_std(
3445
4553
  window_size,
3446
4554
  weights: nil,
3447
- min_periods: nil,
4555
+ min_samples: nil,
3448
4556
  center: false,
3449
4557
  ddof: 1
3450
4558
  )
3451
4559
  super
3452
4560
  end
3453
4561
 
4562
+ # Compute a rolling variance based on another series.
4563
+ #
4564
+ # @note
4565
+ # This functionality is considered **unstable**. It may be changed
4566
+ # at any point without it being considered a breaking change.
4567
+ #
4568
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed: "right"`
4569
+ # (the default) means the windows will be:
4570
+ #
4571
+ # - (t_0 - window_size, t_0]
4572
+ # - (t_1 - window_size, t_1]
4573
+ # - ...
4574
+ # - (t_n - window_size, t_n]
4575
+ #
4576
+ # @param by
4577
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4578
+ # or `Int32` data type (note that the integral ones require using `'i'`
4579
+ # in `window size`).
4580
+ # @param window_size
4581
+ # The length of the window. Can be a dynamic temporal
4582
+ # size indicated by a timedelta or the following string language:
4583
+ #
4584
+ # - 1ns (1 nanosecond)
4585
+ # - 1us (1 microsecond)
4586
+ # - 1ms (1 millisecond)
4587
+ # - 1s (1 second)
4588
+ # - 1m (1 minute)
4589
+ # - 1h (1 hour)
4590
+ # - 1d (1 calendar day)
4591
+ # - 1w (1 calendar week)
4592
+ # - 1mo (1 calendar month)
4593
+ # - 1q (1 calendar quarter)
4594
+ # - 1y (1 calendar year)
4595
+ # - 1i (1 index count)
4596
+ #
4597
+ # By "calendar day", we mean the corresponding time on the next day
4598
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4599
+ # "calendar week", "calendar month", "calendar quarter", and
4600
+ # "calendar year".
4601
+ # @param min_samples [Integer]
4602
+ # The number of values in the window that should be non-null before computing
4603
+ # a result.
4604
+ # @param closed ['left', 'right', 'both', 'none']
4605
+ # Define which sides of the temporal interval are closed (inclusive),
4606
+ # defaults to `'right'`.
4607
+ # @param ddof
4608
+ # "Delta Degrees of Freedom": The divisor for a length N window is N - ddof
4609
+ #
4610
+ # @return [Series]
4611
+ #
4612
+ # @note
4613
+ # If you want to compute multiple aggregation statistics over the same dynamic
4614
+ # window, consider using `rolling` - this method can cache the window size
4615
+ # computation.
4616
+ #
4617
+ # @example
4618
+ # start = DateTime.new(2001, 1, 1)
4619
+ # stop = DateTime.new(2001, 1, 2)
4620
+ # s = Polars::Series.new("index", 25.times.to_a)
4621
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4622
+ # s.rolling_var_by(d, "3h")
4623
+ # # =>
4624
+ # # shape: (25,)
4625
+ # # Series: 'index' [f64]
4626
+ # # [
4627
+ # # null
4628
+ # # 0.5
4629
+ # # 1.0
4630
+ # # 1.0
4631
+ # # 1.0
4632
+ # # …
4633
+ # # 1.0
4634
+ # # 1.0
4635
+ # # 1.0
4636
+ # # 1.0
4637
+ # # 1.0
4638
+ # # ]
4639
+ def rolling_var_by(
4640
+ by,
4641
+ window_size,
4642
+ min_samples: 1,
4643
+ closed: "right",
4644
+ ddof: 1
4645
+ )
4646
+ super
4647
+ end
4648
+
3454
4649
  # Compute a rolling variance.
3455
4650
  #
3456
4651
  # A window of length `window_size` will traverse the array. The values that fill
@@ -3462,11 +4657,13 @@ module Polars
3462
4657
  # @param weights [Array]
3463
4658
  # An optional slice with the same length as the window that will be multiplied
3464
4659
  # elementwise with the values in the window.
3465
- # @param min_periods [Integer]
4660
+ # @param min_samples [Integer]
3466
4661
  # The number of values in the window that should be non-null before computing
3467
- # a result. If None, it will be set equal to window size.
4662
+ # a result. If nil, it will be set equal to window size.
3468
4663
  # @param center [Boolean]
3469
4664
  # Set the labels at the center of the window
4665
+ # @param ddof [Integer]
4666
+ # "Delta Degrees of Freedom": The divisor for a length N window is N - ddof
3470
4667
  #
3471
4668
  # @return [Series]
3472
4669
  #
@@ -3487,26 +4684,149 @@ module Polars
3487
4684
  def rolling_var(
3488
4685
  window_size,
3489
4686
  weights: nil,
3490
- min_periods: nil,
4687
+ min_samples: nil,
3491
4688
  center: false,
3492
4689
  ddof: 1
3493
4690
  )
3494
4691
  super
3495
4692
  end
3496
4693
 
3497
- # def rolling_apply
3498
- # end
3499
-
3500
- # Compute a rolling median.
4694
+ # Compute a custom rolling window function.
4695
+ #
4696
+ # @note
4697
+ # This functionality is considered **unstable**. It may be changed
4698
+ # at any point without it being considered a breaking change.
3501
4699
  #
3502
4700
  # @param window_size [Integer]
3503
- # The length of the window.
4701
+ # The length of the window in number of elements.
4702
+ # @param weights [Object]
4703
+ # An optional slice with the same length as the window that will be multiplied
4704
+ # elementwise with the values in the window.
4705
+ # @param min_samples [Integer]
4706
+ # The number of values in the window that should be non-null before computing
4707
+ # a result. If set to `nil` (default), it will be set equal to `window_size`.
4708
+ # @param center [Boolean]
4709
+ # Set the labels at the center of the window.
4710
+ #
4711
+ # @return [Series]
4712
+ #
4713
+ # @example
4714
+ # s = Polars::Series.new([11.0, 2.0, 9.0, Float::NAN, 8.0])
4715
+ # s.rolling_map(3) { |v| v.drop_nans.sum }
4716
+ # # =>
4717
+ # # shape: (5,)
4718
+ # # Series: '' [f64]
4719
+ # # [
4720
+ # # null
4721
+ # # null
4722
+ # # 22.0
4723
+ # # 11.0
4724
+ # # 17.0
4725
+ # # ]
4726
+ def rolling_map(
4727
+ window_size,
4728
+ weights: nil,
4729
+ min_samples: nil,
4730
+ center: false,
4731
+ &function
4732
+ )
4733
+ super
4734
+ end
4735
+
4736
+ # Compute a rolling median based on another series.
4737
+ #
4738
+ # @note
4739
+ # This functionality is considered **unstable**. It may be changed
4740
+ # at any point without it being considered a breaking change.
4741
+ #
4742
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed: "right"`
4743
+ # (the default) means the windows will be:
4744
+ #
4745
+ # - (t_0 - window_size, t_0]
4746
+ # - (t_1 - window_size, t_1]
4747
+ # - ...
4748
+ # - (t_n - window_size, t_n]
4749
+ #
4750
+ # @param by [Object]
4751
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4752
+ # or `Int32` data type (note that the integral ones require using `'i'`
4753
+ # in `window size`).
4754
+ # @param window_size [String]
4755
+ # The length of the window. Can be a dynamic temporal
4756
+ # size indicated by a timedelta or the following string language:
4757
+ #
4758
+ # - 1ns (1 nanosecond)
4759
+ # - 1us (1 microsecond)
4760
+ # - 1ms (1 millisecond)
4761
+ # - 1s (1 second)
4762
+ # - 1m (1 minute)
4763
+ # - 1h (1 hour)
4764
+ # - 1d (1 calendar day)
4765
+ # - 1w (1 calendar week)
4766
+ # - 1mo (1 calendar month)
4767
+ # - 1q (1 calendar quarter)
4768
+ # - 1y (1 calendar year)
4769
+ # - 1i (1 index count)
4770
+ #
4771
+ # By "calendar day", we mean the corresponding time on the next day
4772
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4773
+ # "calendar week", "calendar month", "calendar quarter", and
4774
+ # "calendar year".
4775
+ # @param min_samples [Integer]
4776
+ # The number of values in the window that should be non-null before computing
4777
+ # a result.
4778
+ # @param closed ['left', 'right', 'both', 'none']
4779
+ # Define which sides of the temporal interval are closed (inclusive),
4780
+ # defaults to `'right'`.
4781
+ #
4782
+ # @return [Series]
4783
+ #
4784
+ # @note
4785
+ # If you want to compute multiple aggregation statistics over the same dynamic
4786
+ # window, consider using `rolling` - this method can cache the window size
4787
+ # computation.
4788
+ #
4789
+ # @example
4790
+ # start = DateTime.new(2001, 1, 1)
4791
+ # stop = DateTime.new(2001, 1, 2)
4792
+ # s = Polars::Series.new("index", 25.times.to_a)
4793
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4794
+ # s.rolling_median_by(d, "3h")
4795
+ # # =>
4796
+ # # shape: (25,)
4797
+ # # Series: 'index' [f64]
4798
+ # # [
4799
+ # # 0.0
4800
+ # # 0.5
4801
+ # # 1.0
4802
+ # # 2.0
4803
+ # # 3.0
4804
+ # # …
4805
+ # # 19.0
4806
+ # # 20.0
4807
+ # # 21.0
4808
+ # # 22.0
4809
+ # # 23.0
4810
+ # # ]
4811
+ def rolling_median_by(
4812
+ by,
4813
+ window_size,
4814
+ min_samples: 1,
4815
+ closed: "right"
4816
+ )
4817
+ super
4818
+ end
4819
+
4820
+ # Compute a rolling median.
4821
+ #
4822
+ # @param window_size [Integer]
4823
+ # The length of the window.
3504
4824
  # @param weights [Array]
3505
4825
  # An optional slice with the same length as the window that will be multiplied
3506
4826
  # elementwise with the values in the window.
3507
- # @param min_periods [Integer]
4827
+ # @param min_samples [Integer]
3508
4828
  # The number of values in the window that should be non-null before computing
3509
- # a result. If None, it will be set equal to window size.
4829
+ # a result. If nil, it will be set equal to window size.
3510
4830
  # @param center [Boolean]
3511
4831
  # Set the labels at the center of the window
3512
4832
  #
@@ -3529,12 +4849,102 @@ module Polars
3529
4849
  def rolling_median(
3530
4850
  window_size,
3531
4851
  weights: nil,
3532
- min_periods: nil,
4852
+ min_samples: nil,
3533
4853
  center: false
3534
4854
  )
3535
4855
  super
3536
4856
  end
3537
4857
 
4858
+ # Compute a rolling quantile based on another series.
4859
+ #
4860
+ # @note
4861
+ # This functionality is considered **unstable**. It may be changed
4862
+ # at any point without it being considered a breaking change.
4863
+ #
4864
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed: "right"`
4865
+ # (the default) means the windows will be:
4866
+ #
4867
+ # - (t_0 - window_size, t_0]
4868
+ # - (t_1 - window_size, t_1]
4869
+ # - ...
4870
+ # - (t_n - window_size, t_n]
4871
+ #
4872
+ # @param by [Object]
4873
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
4874
+ # or `Int32` data type (note that the integral ones require using `'i'`
4875
+ # in `window size`).
4876
+ # @param window_size [String]
4877
+ # The length of the window. Can be a dynamic
4878
+ # temporal size indicated by a timedelta or the following string language:
4879
+ #
4880
+ # - 1ns (1 nanosecond)
4881
+ # - 1us (1 microsecond)
4882
+ # - 1ms (1 millisecond)
4883
+ # - 1s (1 second)
4884
+ # - 1m (1 minute)
4885
+ # - 1h (1 hour)
4886
+ # - 1d (1 calendar day)
4887
+ # - 1w (1 calendar week)
4888
+ # - 1mo (1 calendar month)
4889
+ # - 1q (1 calendar quarter)
4890
+ # - 1y (1 calendar year)
4891
+ # - 1i (1 index count)
4892
+ #
4893
+ # By "calendar day", we mean the corresponding time on the next day
4894
+ # (which may not be 24 hours, due to daylight savings). Similarly for
4895
+ # "calendar week", "calendar month", "calendar quarter", and
4896
+ # "calendar year".
4897
+ # @param quantile [Float]
4898
+ # Quantile between 0.0 and 1.0.
4899
+ # @param interpolation ['nearest', 'higher', 'lower', 'midpoint', 'linear', 'equiprobable']
4900
+ # Interpolation method.
4901
+ # @param min_samples [Integer]
4902
+ # The number of values in the window that should be non-null before computing
4903
+ # a result.
4904
+ # @param closed ['left', 'right', 'both', 'none']
4905
+ # Define which sides of the temporal interval are closed (inclusive),
4906
+ # defaults to `'right'`.
4907
+ #
4908
+ # @return [Series]
4909
+ #
4910
+ # @note
4911
+ # If you want to compute multiple aggregation statistics over the same dynamic
4912
+ # window, consider using `rolling` - this method can cache the window size
4913
+ # computation.
4914
+ #
4915
+ # @example
4916
+ # start = DateTime.new(2001, 1, 1)
4917
+ # stop = DateTime.new(2001, 1, 2)
4918
+ # s = Polars::Series.new("index", 25.times.to_a)
4919
+ # d = Polars::Series.new("date", Polars.datetime_range(start, stop, "1h", eager: true))
4920
+ # s.rolling_quantile_by(d, "3h", quantile: 0.5)
4921
+ # # =>
4922
+ # # shape: (25,)
4923
+ # # Series: 'index' [f64]
4924
+ # # [
4925
+ # # 0.0
4926
+ # # 1.0
4927
+ # # 1.0
4928
+ # # 2.0
4929
+ # # 3.0
4930
+ # # …
4931
+ # # 19.0
4932
+ # # 20.0
4933
+ # # 21.0
4934
+ # # 22.0
4935
+ # # 23.0
4936
+ # # ]
4937
+ def rolling_quantile_by(
4938
+ by,
4939
+ window_size,
4940
+ quantile:,
4941
+ interpolation: "nearest",
4942
+ min_samples: 1,
4943
+ closed: "right"
4944
+ )
4945
+ super
4946
+ end
4947
+
3538
4948
  # Compute a rolling quantile.
3539
4949
  #
3540
4950
  # @param quantile [Float]
@@ -3546,9 +4956,9 @@ module Polars
3546
4956
  # @param weights [Array]
3547
4957
  # An optional slice with the same length as the window that will be multiplied
3548
4958
  # elementwise with the values in the window.
3549
- # @param min_periods [Integer]
4959
+ # @param min_samples [Integer]
3550
4960
  # The number of values in the window that should be non-null before computing
3551
- # a result. If None, it will be set equal to window size.
4961
+ # a result. If nil, it will be set equal to window size.
3552
4962
  # @param center [Boolean]
3553
4963
  # Set the labels at the center of the window
3554
4964
  #
@@ -3563,10 +4973,10 @@ module Polars
3563
4973
  # # [
3564
4974
  # # null
3565
4975
  # # null
3566
- # # 1.0
3567
4976
  # # 2.0
3568
4977
  # # 3.0
3569
4978
  # # 4.0
4979
+ # # 6.0
3570
4980
  # # ]
3571
4981
  #
3572
4982
  # @example
@@ -3587,7 +4997,144 @@ module Polars
3587
4997
  interpolation: "nearest",
3588
4998
  window_size: 2,
3589
4999
  weights: nil,
3590
- min_periods: nil,
5000
+ min_samples: nil,
5001
+ center: false
5002
+ )
5003
+ super
5004
+ end
5005
+
5006
+ # Compute a rolling rank based on another column.
5007
+ #
5008
+ # @note
5009
+ # This functionality is considered **unstable**. It may be changed
5010
+ # at any point without it being considered a breaking change.
5011
+ #
5012
+ # Given a `by` column `<t_0, t_1, ..., t_n>`, then `closed="right"`
5013
+ # (the default) means the windows will be:
5014
+ #
5015
+ # - (t_0 - window_size, t_0]
5016
+ # - (t_1 - window_size, t_1]
5017
+ # - ...
5018
+ # - (t_n - window_size, t_n]
5019
+ #
5020
+ # @param by [Expr]
5021
+ # Should be `DateTime`, `Date`, `UInt64`, `UInt32`, `Int64`,
5022
+ # or `Int32` data type (note that the integral ones require using `'i'`
5023
+ # in `window size`).
5024
+ # @param window_size [String]
5025
+ # The length of the window. Can be a dynamic
5026
+ # temporal size indicated by a timedelta or the following string language:
5027
+ #
5028
+ # - 1ns (1 nanosecond)
5029
+ # - 1us (1 microsecond)
5030
+ # - 1ms (1 millisecond)
5031
+ # - 1s (1 second)
5032
+ # - 1m (1 minute)
5033
+ # - 1h (1 hour)
5034
+ # - 1d (1 calendar day)
5035
+ # - 1w (1 calendar week)
5036
+ # - 1mo (1 calendar month)
5037
+ # - 1q (1 calendar quarter)
5038
+ # - 1y (1 calendar year)
5039
+ # - 1i (1 index count)
5040
+ #
5041
+ # By "calendar day", we mean the corresponding time on the next day
5042
+ # (which may not be 24 hours, due to daylight savings). Similarly for
5043
+ # "calendar week", "calendar month", "calendar quarter", and
5044
+ # "calendar year".
5045
+ # @param method ['average', 'min', 'max', 'dense', 'random']
5046
+ # The method used to assign ranks to tied elements.
5047
+ # The following methods are available (default is 'average'):
5048
+ #
5049
+ # - 'average' : The average of the ranks that would have been assigned to
5050
+ # all the tied values is assigned to each value.
5051
+ # - 'min' : The minimum of the ranks that would have been assigned to all
5052
+ # the tied values is assigned to each value. (This is also referred to
5053
+ # as "competition" ranking.)
5054
+ # - 'max' : The maximum of the ranks that would have been assigned to all
5055
+ # the tied values is assigned to each value.
5056
+ # - 'dense' : Like 'min', but the rank of the next highest element is
5057
+ # assigned the rank immediately after those assigned to the tied
5058
+ # elements.
5059
+ # - 'random' : Choose a random rank for each value in a tie.
5060
+ # @param seed [Integer]
5061
+ # Random seed used when `method: 'random'`. If set to nil (default), a
5062
+ # random seed is generated for each rolling rank operation.
5063
+ # @param min_samples [Integer]
5064
+ # The number of values in the window that should be non-null before computing
5065
+ # a result.
5066
+ # @param closed ['left', 'right', 'both', 'none']
5067
+ # Define which sides of the temporal interval are closed (inclusive),
5068
+ # defaults to `'right'`.
5069
+ #
5070
+ # @return [Series]
5071
+ def rolling_rank_by(
5072
+ by,
5073
+ window_size,
5074
+ method: "average",
5075
+ seed: nil,
5076
+ min_samples: 1,
5077
+ closed: "right"
5078
+ )
5079
+ super
5080
+ end
5081
+
5082
+ # Compute a rolling rank.
5083
+ #
5084
+ # @note
5085
+ # This functionality is considered **unstable**. It may be changed
5086
+ # at any point without it being considered a breaking change.
5087
+ #
5088
+ # A window of length `window_size` will traverse the array. The values
5089
+ # that fill this window will be ranked according to the `method`
5090
+ # parameter. The resulting values will be the rank of the value that is
5091
+ # at the end of the sliding window.
5092
+ #
5093
+ # @param window_size [Integer]
5094
+ # Integer size of the rolling window.
5095
+ # @param method ['average', 'min', 'max', 'dense', 'random']
5096
+ # The method used to assign ranks to tied elements.
5097
+ # The following methods are available (default is 'average'):
5098
+ #
5099
+ # - 'average' : The average of the ranks that would have been assigned to
5100
+ # all the tied values is assigned to each value.
5101
+ # - 'min' : The minimum of the ranks that would have been assigned to all
5102
+ # the tied values is assigned to each value. (This is also referred to
5103
+ # as "competition" ranking.)
5104
+ # - 'max' : The maximum of the ranks that would have been assigned to all
5105
+ # the tied values is assigned to each value.
5106
+ # - 'dense' : Like 'min', but the rank of the next highest element is
5107
+ # assigned the rank immediately after those assigned to the tied
5108
+ # elements.
5109
+ # - 'random' : Choose a random rank for each value in a tie.
5110
+ # @param seed [Integer]
5111
+ # Random seed used when `method: 'random'`. If set to nil (default), a
5112
+ # random seed is generated for each rolling rank operation.
5113
+ # @param min_samples [Integer]
5114
+ # The number of values in the window that should be non-null before computing
5115
+ # a result. If set to `nil` (default), it will be set equal to `window_size`.
5116
+ # @param center [Boolean]
5117
+ # Set the labels at the center of the window.
5118
+ #
5119
+ # @return [Series]
5120
+ #
5121
+ # @example
5122
+ # Polars::Series.new([1, 4, 4, 1, 9]).rolling_rank(3, method: "average")
5123
+ # # =>
5124
+ # # shape: (5,)
5125
+ # # Series: '' [f64]
5126
+ # # [
5127
+ # # null
5128
+ # # null
5129
+ # # 2.5
5130
+ # # 1.0
5131
+ # # 3.0
5132
+ # # ]
5133
+ def rolling_rank(
5134
+ window_size,
5135
+ method: "average",
5136
+ seed: nil,
5137
+ min_samples: nil,
3591
5138
  center: false
3592
5139
  )
3593
5140
  super
@@ -3599,40 +5146,87 @@ module Polars
3599
5146
  # Integer size of the rolling window.
3600
5147
  # @param bias [Boolean]
3601
5148
  # If false, the calculations are corrected for statistical bias.
5149
+ # @param min_samples [Integer]
5150
+ # The number of values in the window that should be non-null before computing
5151
+ # a result. If set to `nil` (default), it will be set equal to `window_size`.
5152
+ # @param center [Boolean]
5153
+ # Set the labels at the center of the window.
3602
5154
  #
3603
5155
  # @return [Series]
3604
5156
  #
3605
5157
  # @example
3606
- # s = Polars::Series.new("a", [1.0, 2.0, 3.0, 4.0, 6.0, 8.0])
3607
- # s.rolling_skew(3)
5158
+ # Polars::Series.new([1, 4, 2, 9]).rolling_skew(3)
3608
5159
  # # =>
3609
- # # shape: (6,)
3610
- # # Series: 'a' [f64]
5160
+ # # shape: (4,)
5161
+ # # Series: '' [f64]
3611
5162
  # # [
3612
5163
  # # null
3613
5164
  # # null
3614
- # # 0.0
3615
- # # 0.0
3616
5165
  # # 0.381802
3617
- # # 0.0
5166
+ # # 0.47033
5167
+ # # ]
5168
+ def rolling_skew(window_size, bias: true, min_samples: nil, center: false)
5169
+ super
5170
+ end
5171
+
5172
+ # Compute a rolling kurtosis.
5173
+ #
5174
+ # @note
5175
+ # This functionality is considered **unstable**. It may be changed
5176
+ # at any point without it being considered a breaking change.
5177
+ #
5178
+ # The window at a given row will include the row itself, and the `window_size - 1`
5179
+ # elements before it.
5180
+ #
5181
+ # @param window_size [Integer]
5182
+ # Integer size of the rolling window.
5183
+ # @param fisher [Boolean]
5184
+ # If true, Fisher's definition is used (normal ==> 0.0). If false,
5185
+ # Pearson's definition is used (normal ==> 3.0).
5186
+ # @param bias [Boolean]
5187
+ # If false, the calculations are corrected for statistical bias.
5188
+ # @param min_samples [Integer]
5189
+ # The number of values in the window that should be non-null before computing
5190
+ # a result. If set to `nil` (default), it will be set equal to `window_size`.
5191
+ # @param center [Boolean]
5192
+ # Set the labels at the center of the window.
5193
+ #
5194
+ # @return [Series]
5195
+ #
5196
+ # @example
5197
+ # Polars::Series.new([1, 4, 2, 9]).rolling_kurtosis(3)
5198
+ # # =>
5199
+ # # shape: (4,)
5200
+ # # Series: '' [f64]
5201
+ # # [
5202
+ # # null
5203
+ # # null
5204
+ # # -1.5
5205
+ # # -1.5
3618
5206
  # # ]
3619
- def rolling_skew(window_size, bias: true)
5207
+ def rolling_kurtosis(
5208
+ window_size,
5209
+ fisher: true,
5210
+ bias: true,
5211
+ min_samples: nil,
5212
+ center: false
5213
+ )
3620
5214
  super
3621
5215
  end
3622
5216
 
3623
5217
  # Sample from this Series.
3624
5218
  #
3625
5219
  # @param n [Integer]
3626
- # Number of items to return. Cannot be used with `frac`. Defaults to 1 if
3627
- # `frac` is None.
3628
- # @param frac [Float]
5220
+ # Number of items to return. Cannot be used with `fraction`. Defaults to 1 if
5221
+ # `fraction` is nil.
5222
+ # @param fraction [Float]
3629
5223
  # Fraction of items to return. Cannot be used with `n`.
3630
5224
  # @param with_replacement [Boolean]
3631
5225
  # Allow values to be sampled more than once.
3632
5226
  # @param shuffle [Boolean]
3633
5227
  # Shuffle the order of sampled data points.
3634
5228
  # @param seed [Integer]
3635
- # Seed for the random number generator. If set to None (default), a random
5229
+ # Seed for the random number generator. If set to nil (default), a random
3636
5230
  # seed is used.
3637
5231
  #
3638
5232
  # @return [Series]
@@ -3644,28 +5238,17 @@ module Polars
3644
5238
  # # shape: (2,)
3645
5239
  # # Series: 'a' [i64]
3646
5240
  # # [
5241
+ # # 2
3647
5242
  # # 5
3648
- # # 3
3649
5243
  # # ]
3650
5244
  def sample(
3651
5245
  n: nil,
3652
- frac: nil,
5246
+ fraction: nil,
3653
5247
  with_replacement: false,
3654
5248
  shuffle: false,
3655
5249
  seed: nil
3656
5250
  )
3657
- if !n.nil? && !frac.nil?
3658
- raise ArgumentError, "cannot specify both `n` and `frac`"
3659
- end
3660
-
3661
- if n.nil? && !frac.nil?
3662
- return Utils.wrap_s(_s.sample_frac(frac, with_replacement, shuffle, seed))
3663
- end
3664
-
3665
- if n.nil?
3666
- n = 1
3667
- end
3668
- Utils.wrap_s(_s.sample_n(n, with_replacement, shuffle, seed))
5251
+ super
3669
5252
  end
3670
5253
 
3671
5254
  # Get a boolean mask of the local maximum peaks.
@@ -3741,7 +5324,7 @@ module Polars
3741
5324
 
3742
5325
  # Hash the Series.
3743
5326
  #
3744
- # The hash value is of type `:u64`.
5327
+ # The hash value is of type `UInt64`.
3745
5328
  #
3746
5329
  # @param seed [Integer]
3747
5330
  # Random seed parameter. Defaults to 0.
@@ -3756,7 +5339,7 @@ module Polars
3756
5339
  #
3757
5340
  # @example
3758
5341
  # s = Polars::Series.new("a", [1, 2, 3])
3759
- # s._hash(42)
5342
+ # s.hash_(42)
3760
5343
  # # =>
3761
5344
  # # shape: (3,)
3762
5345
  # # Series: 'a' [u64]
@@ -3765,17 +5348,22 @@ module Polars
3765
5348
  # # 10386026231460783898
3766
5349
  # # 17796317186427479491
3767
5350
  # # ]
3768
- def _hash(seed = 0, seed_1 = nil, seed_2 = nil, seed_3 = nil)
5351
+ def hash_(seed = 0, seed_1 = nil, seed_2 = nil, seed_3 = nil)
3769
5352
  super
3770
5353
  end
3771
5354
 
3772
- # Reinterpret the underlying bits as a signed/unsigned integer.
5355
+ # Reinterpret the underlying bits as a signed/unsigned integer or float.
3773
5356
  #
3774
- # This operation is only allowed for 64bit integers. For lower bits integers,
3775
- # you can safely use that cast operation.
5357
+ # This operation is only allowed for numeric types of the same size.
5358
+ # For lower bits numbers, you can safely use the cast operation.
5359
+ #
5360
+ # Either `signed` or `dtype` can be specified.
3776
5361
  #
3777
5362
  # @param signed [Boolean]
3778
- # If true, reinterpret as `:i64`. Otherwise, reinterpret as `:u64`.
5363
+ # If true, reinterpret as signed integer. Otherwise, reinterpret
5364
+ # as unsigned integer.
5365
+ # @param dtype [Object]
5366
+ # DataType to reinterpret to.
3779
5367
  #
3780
5368
  # @return [Series]
3781
5369
  #
@@ -3790,7 +5378,18 @@ module Polars
3790
5378
  # # 18446744073709551614
3791
5379
  # # 3
3792
5380
  # # ]
3793
- def reinterpret(signed: true)
5381
+ #
5382
+ # @example
5383
+ # s.reinterpret(dtype: Polars::Int64)
5384
+ # # =>
5385
+ # # shape: (3,)
5386
+ # # Series: 'a' [i64]
5387
+ # # [
5388
+ # # -1152921504606846976
5389
+ # # -2
5390
+ # # 3
5391
+ # # ]
5392
+ def reinterpret(signed: nil, dtype: nil)
3794
5393
  super
3795
5394
  end
3796
5395
 
@@ -3815,6 +5414,30 @@ module Polars
3815
5414
  super
3816
5415
  end
3817
5416
 
5417
+ # Fill null values using interpolation based on another column.
5418
+ #
5419
+ # @param by [Expr]
5420
+ # Column to interpolate values based on.
5421
+ #
5422
+ # @return [Series]
5423
+ #
5424
+ # @example Fill null values using linear interpolation.
5425
+ # s = Polars::Series.new("a", [1, nil, nil, 3])
5426
+ # by = Polars::Series.new("b", [1, 2, 7, 8])
5427
+ # s.interpolate_by(by)
5428
+ # # =>
5429
+ # # shape: (4,)
5430
+ # # Series: 'a' [f64]
5431
+ # # [
5432
+ # # 1.0
5433
+ # # 1.285714
5434
+ # # 2.714286
5435
+ # # 3.0
5436
+ # # ]
5437
+ def interpolate_by(by)
5438
+ super
5439
+ end
5440
+
3818
5441
  # Compute absolute values.
3819
5442
  #
3820
5443
  # @return [Series]
@@ -3854,7 +5477,7 @@ module Polars
3854
5477
  # the order that the values occur in the Series.
3855
5478
  # - 'random' : Like 'ordinal', but the rank for ties is not dependent
3856
5479
  # on the order that the values occur in the Series.
3857
- # @param reverse [Boolean]
5480
+ # @param descending [Boolean]
3858
5481
  # Reverse the operation.
3859
5482
  # @param seed [Integer]
3860
5483
  # If `method: "random"`, use this as seed.
@@ -3888,7 +5511,7 @@ module Polars
3888
5511
  # # 2
3889
5512
  # # 5
3890
5513
  # # ]
3891
- def rank(method: "average", reverse: false, seed: nil)
5514
+ def rank(method: "average", descending: false, seed: nil)
3892
5515
  super
3893
5516
  end
3894
5517
 
@@ -4041,22 +5664,21 @@ module Polars
4041
5664
  #
4042
5665
  # @example
4043
5666
  # s.kurtosis(fisher: false, bias: false)
4044
- # # => 2.1040361802642726
5667
+ # # => 2.1040361802642717
4045
5668
  def kurtosis(fisher: true, bias: true)
4046
5669
  _s.kurtosis(fisher, bias)
4047
5670
  end
4048
5671
 
4049
- # Clip (limit) the values in an array to a `min` and `max` boundary.
5672
+ # Set values outside the given boundaries to the boundary value.
4050
5673
  #
4051
- # Only works for numerical types.
4052
- #
4053
- # If you want to clip other dtypes, consider writing a "when, then, otherwise"
4054
- # expression. See {#when} for more information.
4055
- #
4056
- # @param min_val [Numeric]
4057
- # Minimum value.
4058
- # @param max_val [Numeric]
4059
- # Maximum value.
5674
+ # @param lower_bound [Numeric]
5675
+ # Lower bound. Accepts expression input.
5676
+ # Non-expression inputs are parsed as literals.
5677
+ # If set to `nil` (default), no lower bound is applied.
5678
+ # @param upper_bound [Numeric]
5679
+ # Upper bound. Accepts expression input.
5680
+ # Non-expression inputs are parsed as literals.
5681
+ # If set to `nil` (default), no upper bound is applied.
4060
5682
  #
4061
5683
  # @return [Series]
4062
5684
  #
@@ -4072,47 +5694,71 @@ module Polars
4072
5694
  # # null
4073
5695
  # # 10
4074
5696
  # # ]
4075
- def clip(min_val = nil, max_val = nil)
5697
+ def clip(lower_bound = nil, upper_bound = nil)
4076
5698
  super
4077
5699
  end
4078
5700
 
4079
- # Clip (limit) the values in an array to a `min` boundary.
5701
+ # Return the lower bound of this Series' dtype as a unit Series.
4080
5702
  #
4081
- # Only works for numerical types.
4082
- #
4083
- # If you want to clip other dtypes, consider writing a "when, then, otherwise"
4084
- # expression. See {#when} for more information.
5703
+ # @return [Series]
4085
5704
  #
4086
- # @param min_val [Numeric]
4087
- # Minimum value.
5705
+ # @example
5706
+ # s = Polars::Series.new("s", [-1, 0, 1], dtype: Polars::Int32)
5707
+ # s.lower_bound
5708
+ # # =>
5709
+ # # shape: (1,)
5710
+ # # Series: 's' [i32]
5711
+ # # [
5712
+ # # -2147483648
5713
+ # # ]
4088
5714
  #
4089
- # @return [Series]
4090
- def clip_min(min_val)
5715
+ # @example
5716
+ # s = Polars::Series.new("s", [1.0, 2.5, 3.0], dtype: Polars::Float32)
5717
+ # s.lower_bound
5718
+ # # =>
5719
+ # # shape: (1,)
5720
+ # # Series: 's' [f32]
5721
+ # # [
5722
+ # # -inf
5723
+ # # ]
5724
+ def lower_bound
4091
5725
  super
4092
5726
  end
4093
5727
 
4094
- # Clip (limit) the values in an array to a `max` boundary.
5728
+ # Return the upper bound of this Series' dtype as a unit Series.
4095
5729
  #
4096
- # Only works for numerical types.
4097
- #
4098
- # If you want to clip other dtypes, consider writing a "when, then, otherwise"
4099
- # expression. See {#when} for more information.
5730
+ # @return [Series]
4100
5731
  #
4101
- # @param max_val [Numeric]
4102
- # Maximum value.
5732
+ # @example
5733
+ # s = Polars::Series.new("s", [-1, 0, 1], dtype: Polars::Int8)
5734
+ # s.upper_bound
5735
+ # # =>
5736
+ # # shape: (1,)
5737
+ # # Series: 's' [i8]
5738
+ # # [
5739
+ # # 127
5740
+ # # ]
4103
5741
  #
4104
- # @return [Series]
4105
- def clip_max(max_val)
5742
+ # @example
5743
+ # s = Polars::Series.new("s", [1.0, 2.5, 3.0], dtype: Polars::Float64)
5744
+ # s.upper_bound
5745
+ # # =>
5746
+ # # shape: (1,)
5747
+ # # Series: 's' [f64]
5748
+ # # [
5749
+ # # inf
5750
+ # # ]
5751
+ def upper_bound
4106
5752
  super
4107
5753
  end
4108
5754
 
4109
5755
  # Replace values by different values.
4110
5756
  #
4111
5757
  # @param old [Object]
4112
- # Value or sequence of values to replace.
5758
+ # Value or array of values to replace.
4113
5759
  # Also accepts a mapping of values to their replacement.
4114
5760
  # @param new [Object]
4115
- # Value or sequence of values to replace by.
5761
+ # Value or array of values to replace by.
4116
5762
  # Length must match the length of `old` or have length 1.
4117
5763
  # @param default [Object]
4118
5764
  # Set values that were not replaced to this value.
@@ -4137,7 +5783,7 @@ module Polars
4137
5783
  # # 3
4138
5784
  # # ]
4139
5785
  #
4140
- # @example Replace multiple values by passing sequences to the `old` and `new` parameters.
5786
+ # @example Replace multiple values by passing arrays to the `old` and `new` parameters.
4141
5787
  # s.replace([2, 3], [100, 200])
4142
5788
  # # =>
4143
5789
  # # shape: (4,)
@@ -4174,20 +5820,134 @@ module Polars
4174
5820
  # # "2"
4175
5821
  # # "3"
4176
5822
  # # ]
4177
- def replace(old, new = Expr::NO_DEFAULT, default: Expr::NO_DEFAULT, return_dtype: nil)
5823
+ def replace(old, new = NO_DEFAULT, default: NO_DEFAULT, return_dtype: nil)
4178
5824
  super
4179
5825
  end
4180
5826
 
4181
- # Reshape this Series to a flat Series or a Series of Lists.
5827
+ # Replace all values by different values.
4182
5828
  #
4183
- # @param dims [Array]
4184
- # Tuple of the dimension sizes. If a -1 is used in any of the dimensions, that
4185
- # dimension is inferred.
5829
+ # @param old [Object]
5830
+ # Value or array of values to replace.
5831
+ # Also accepts a mapping of values to their replacement as syntactic sugar for
5832
+ # `replace_strict(old: Polars::Series.new(mapping.keys), new: Polars::Series.new(mapping.values))`.
5833
+ # @param new [Object]
5834
+ # Value or array of values to replace by.
5835
+ # Length must match the length of `old` or have length 1.
5836
+ # @param default [Object]
5837
+ # Set values that were not replaced to this value. If no default is specified,
5838
+ # (default), an error is raised if any values were not replaced.
5839
+ # Accepts expression input. Non-expression inputs are parsed as literals.
5840
+ # @param return_dtype [Object]
5841
+ # The data type of the resulting Series. If set to `nil` (default),
5842
+ # the data type is determined automatically based on the other inputs.
4186
5843
  #
4187
5844
  # @return [Series]
4188
5845
  #
4189
- # @example
4190
- # s = Polars::Series.new("foo", [1, 2, 3, 4, 5, 6, 7, 8, 9])
5846
+ # @example Replace values by passing arrays to the `old` and `new` parameters.
5847
+ # s = Polars::Series.new([1, 2, 2, 3])
5848
+ # s.replace_strict([1, 2, 3], [100, 200, 300])
5849
+ # # =>
5850
+ # # shape: (4,)
5851
+ # # Series: '' [i64]
5852
+ # # [
5853
+ # # 100
5854
+ # # 200
5855
+ # # 200
5856
+ # # 300
5857
+ # # ]
5858
+ #
5859
+ # @example Passing a mapping with replacements is also supported as syntactic sugar.
5860
+ # mapping = {1 => 100, 2 => 200, 3 => 300}
5861
+ # s.replace_strict(mapping)
5862
+ # # =>
5863
+ # # shape: (4,)
5864
+ # # Series: '' [i64]
5865
+ # # [
5866
+ # # 100
5867
+ # # 200
5868
+ # # 200
5869
+ # # 300
5870
+ # # ]
5871
+ #
5872
+ # @example By default, an error is raised if any non-null values were not replaced. Specify a default to set all values that were not matched.
5873
+ # mapping = {2 => 200, 3 => 300}
5874
+ # s.replace_strict(mapping, default: -1)
5875
+ # # =>
5876
+ # # shape: (4,)
5877
+ # # Series: '' [i64]
5878
+ # # [
5879
+ # # -1
5880
+ # # 200
5881
+ # # 200
5882
+ # # 300
5883
+ # # ]
5884
+ #
5885
+ # @example The default can be another Series.
5886
+ # default = Polars::Series.new([2.5, 5.0, 7.5, 10.0])
5887
+ # s.replace_strict(2, 200, default: default)
5888
+ # # =>
5889
+ # # shape: (4,)
5890
+ # # Series: '' [f64]
5891
+ # # [
5892
+ # # 2.5
5893
+ # # 200.0
5894
+ # # 200.0
5895
+ # # 10.0
5896
+ # # ]
5897
+ #
5898
+ # @example Replacing by values of a different data type sets the return type based on a combination of the `new` data type and the `default` data type.
5899
+ # s = Polars::Series.new(["x", "y", "z"])
5900
+ # mapping = {"x" => 1, "y" => 2, "z" => 3}
5901
+ # s.replace_strict(mapping)
5902
+ # # =>
5903
+ # # shape: (3,)
5904
+ # # Series: '' [i64]
5905
+ # # [
5906
+ # # 1
5907
+ # # 2
5908
+ # # 3
5909
+ # # ]
5910
+ #
5911
+ # @example
5912
+ # s.replace_strict(mapping, default: "x")
5913
+ # # =>
5914
+ # # shape: (3,)
5915
+ # # Series: '' [str]
5916
+ # # [
5917
+ # # "1"
5918
+ # # "2"
5919
+ # # "3"
5920
+ # # ]
5921
+ #
5922
+ # @example Set the `return_dtype` parameter to control the resulting data type directly.
5923
+ # s.replace_strict(mapping, return_dtype: Polars::UInt8)
5924
+ # # =>
5925
+ # # shape: (3,)
5926
+ # # Series: '' [u8]
5927
+ # # [
5928
+ # # 1
5929
+ # # 2
5930
+ # # 3
5931
+ # # ]
5932
+ def replace_strict(
5933
+ old,
5934
+ new = NO_DEFAULT,
5935
+ default: NO_DEFAULT,
5936
+ return_dtype: nil
5937
+ )
5938
+ super
5939
+ end
5940
+
5941
+ # Reshape this Series to a flat Series or a Series of Lists.
5942
+ #
5943
+ # @param dimensions [Array]
5944
+ # Tuple of the dimension sizes. If a -1 is used in any of the dimensions, that
5945
+ # dimension is inferred.
5946
+ #
5947
+ # @return [Series]
5948
+ #
5949
+ # @example
5950
+ # s = Polars::Series.new("foo", [1, 2, 3, 4, 5, 6, 7, 8, 9])
4191
5951
  # square = s.reshape([3, 3])
4192
5952
  # # =>
4193
5953
  # # shape: (3,)
@@ -4214,8 +5974,8 @@ module Polars
4214
5974
  # # 8
4215
5975
  # # 9
4216
5976
  # # ]
4217
- def reshape(dims)
4218
- super
5977
+ def reshape(dimensions)
5978
+ self.class._from_rbseries(_s.reshape(dimensions))
4219
5979
  end
4220
5980
 
4221
5981
  # Shuffle the contents of this Series.
@@ -4233,8 +5993,8 @@ module Polars
4233
5993
  # # Series: 'a' [i64]
4234
5994
  # # [
4235
5995
  # # 2
4236
- # # 1
4237
5996
  # # 3
5997
+ # # 1
4238
5998
  # # ]
4239
5999
  def shuffle(seed: nil)
4240
6000
  super
@@ -4261,8 +6021,70 @@ module Polars
4261
6021
  half_life: nil,
4262
6022
  alpha: nil,
4263
6023
  adjust: true,
4264
- min_periods: 1,
4265
- ignore_nulls: true
6024
+ min_samples: 1,
6025
+ ignore_nulls: false
6026
+ )
6027
+ super
6028
+ end
6029
+
6030
+ # Compute time-based exponentially weighted moving average.
6031
+ #
6032
+ # @param by [Object]
6033
+ # Times to calculate average by. Should be `DateTime`, `Date`, `UInt64`,
6034
+ # `UInt32`, `Int64`, or `Int32` data type.
6035
+ # @param half_life [String]
6036
+ # Unit over which observation decays to half its value.
6037
+ #
6038
+ # Can be created either from a timedelta, or
6039
+ # by using the following string language:
6040
+ #
6041
+ # - 1ns (1 nanosecond)
6042
+ # - 1us (1 microsecond)
6043
+ # - 1ms (1 millisecond)
6044
+ # - 1s (1 second)
6045
+ # - 1m (1 minute)
6046
+ # - 1h (1 hour)
6047
+ # - 1d (1 day)
6048
+ # - 1w (1 week)
6049
+ # - 1i (1 index count)
6050
+ #
6051
+ # Or combine them:
6052
+ # "3d12h4m25s" # 3 days, 12 hours, 4 minutes, and 25 seconds
6053
+ #
6054
+ # Note that `half_life` is treated as a constant duration - calendar
6055
+ # durations such as months (or even days in the time-zone-aware case)
6056
+ # are not supported, please express your duration in an approximately
6057
+ # equivalent number of hours (e.g. '370h' instead of '1mo').
6058
+ #
6059
+ # @return [Series]
6060
+ #
6061
+ # @example
6062
+ # df = Polars::DataFrame.new(
6063
+ # {
6064
+ # "values" => [0, 1, 2, nil, 4],
6065
+ # "times" => [
6066
+ # Date.new(2020, 1, 1),
6067
+ # Date.new(2020, 1, 3),
6068
+ # Date.new(2020, 1, 10),
6069
+ # Date.new(2020, 1, 15),
6070
+ # Date.new(2020, 1, 17)
6071
+ # ]
6072
+ # }
6073
+ # ).sort("times")
6074
+ # df["values"].ewm_mean_by(df["times"], half_life: "4d")
6075
+ # # =>
6076
+ # # shape: (5,)
6077
+ # # Series: 'values' [f64]
6078
+ # # [
6079
+ # # 0.0
6080
+ # # 0.292893
6081
+ # # 1.492474
6082
+ # # null
6083
+ # # 3.254508
6084
+ # # ]
6085
+ def ewm_mean_by(
6086
+ by,
6087
+ half_life:
4266
6088
  )
4267
6089
  super
4268
6090
  end
@@ -4289,8 +6111,8 @@ module Polars
4289
6111
  alpha: nil,
4290
6112
  adjust: true,
4291
6113
  bias: false,
4292
- min_periods: 1,
4293
- ignore_nulls: true
6114
+ min_samples: 1,
6115
+ ignore_nulls: false
4294
6116
  )
4295
6117
  super
4296
6118
  end
@@ -4317,8 +6139,8 @@ module Polars
4317
6139
  alpha: nil,
4318
6140
  adjust: true,
4319
6141
  bias: false,
4320
- min_periods: 1,
4321
- ignore_nulls: true
6142
+ min_samples: 1,
6143
+ ignore_nulls: false
4322
6144
  )
4323
6145
  super
4324
6146
  end
@@ -4347,14 +6169,14 @@ module Polars
4347
6169
  # # 99
4348
6170
  # # ]
4349
6171
  def extend_constant(value, n)
4350
- Utils.wrap_s(_s.extend_constant(value, n))
6172
+ super
4351
6173
  end
4352
6174
 
4353
6175
  # Flags the Series as sorted.
4354
6176
  #
4355
6177
  # Enables downstream code to user fast paths for sorted arrays.
4356
6178
  #
4357
- # @param reverse [Boolean]
6179
+ # @param descending [Boolean]
4358
6180
  # If the Series order is reversed, e.g. descending.
4359
6181
  #
4360
6182
  # @return [Series]
@@ -4367,8 +6189,8 @@ module Polars
4367
6189
  # s = Polars::Series.new("a", [1, 2, 3])
4368
6190
  # s.set_sorted.max
4369
6191
  # # => 3
4370
- def set_sorted(reverse: false)
4371
- Utils.wrap_s(_s.set_sorted(reverse))
6192
+ def set_sorted(descending: false)
6193
+ Utils.wrap_s(_s.set_sorted(descending))
4372
6194
  end
4373
6195
 
4374
6196
  # Create a new Series filled with values from the given index.
@@ -4412,9 +6234,153 @@ module Polars
4412
6234
  # # 6
4413
6235
  # # ]
4414
6236
  def shrink_dtype
6237
+ Utils.wrap_s(_s.shrink_dtype)
6238
+ end
6239
+
6240
+ # Get the chunks of this Series as a list of Series.
6241
+ #
6242
+ # @return [Array]
6243
+ #
6244
+ # @example
6245
+ # s1 = Polars::Series.new("a", [1, 2, 3])
6246
+ # s2 = Polars::Series.new("a", [4, 5, 6])
6247
+ # s = Polars.concat([s1, s2], rechunk: false)
6248
+ # s.get_chunks
6249
+ # # =>
6250
+ # # [shape: (3,)
6251
+ # # Series: 'a' [i64]
6252
+ # # [
6253
+ # # 1
6254
+ # # 2
6255
+ # # 3
6256
+ # # ], shape: (3,)
6257
+ # # Series: 'a' [i64]
6258
+ # # [
6259
+ # # 4
6260
+ # # 5
6261
+ # # 6
6262
+ # # ]]
6263
+ def get_chunks
6264
+ _s.get_chunks
6265
+ end
6266
+
6267
+ # Aggregate values into a list.
6268
+ #
6269
+ # @return [Series]
6270
+ #
6271
+ # @example
6272
+ # s = Polars::Series.new("a", [1, 2, 3])
6273
+ # s.implode
6274
+ # # =>
6275
+ # # shape: (1,)
6276
+ # # Series: 'a' [list[i64]]
6277
+ # # [
6278
+ # # [1, 2, 3]
6279
+ # # ]
6280
+ def implode
6281
+ super
6282
+ end
6283
+
6284
+ # Evaluate the number of set bits.
6285
+ #
6286
+ # @return [Series]
6287
+ def bitwise_count_ones
6288
+ super
6289
+ end
6290
+
6291
+ # Evaluate the number of unset bits.
6292
+ #
6293
+ # @return [Series]
6294
+ def bitwise_count_zeros
6295
+ super
6296
+ end
6297
+
6298
+ # Evaluate the number most-significant set bits before seeing an unset bit.
6299
+ #
6300
+ # @return [Series]
6301
+ def bitwise_leading_ones
4415
6302
  super
4416
6303
  end
4417
6304
 
6305
+ # Evaluate the number most-significant unset bits before seeing a set bit.
6306
+ #
6307
+ # @return [Series]
6308
+ def bitwise_leading_zeros
6309
+ super
6310
+ end
6311
+
6312
+ # Evaluate the number least-significant set bits before seeing an unset bit.
6313
+ #
6314
+ # @return [Series]
6315
+ def bitwise_trailing_ones
6316
+ super
6317
+ end
6318
+
6319
+ # Evaluate the number least-significant unset bits before seeing a set bit.
6320
+ #
6321
+ # @return [Series]
6322
+ def bitwise_trailing_zeros
6323
+ super
6324
+ end
6325
+
6326
+ # Perform an aggregation of bitwise ANDs.
6327
+ #
6328
+ # @return [Object]
6329
+ def bitwise_and
6330
+ _s.bitwise_and
6331
+ end
6332
+
6333
+ # Perform an aggregation of bitwise ORs.
6334
+ #
6335
+ # @return [Object]
6336
+ def bitwise_or
6337
+ _s.bitwise_or
6338
+ end
6339
+
6340
+ # Perform an aggregation of bitwise XORs.
6341
+ #
6342
+ # @return [Object]
6343
+ def bitwise_xor
6344
+ _s.bitwise_xor
6345
+ end
6346
+
6347
+ # Get the first element of the Series.
6348
+ #
6349
+ # Returns `nil` if the Series is empty.
6350
+ #
6351
+ # @param ignore_nulls [Boolean]
6352
+ # Ignore null values (default `false`).
6353
+ # If set to `true`, the first non-null value is returned, otherwise `nil` is
6354
+ # returned if no non-null value exists.
6355
+ #
6356
+ # @return [Object]
6357
+ def first(ignore_nulls: false)
6358
+ _s.first(ignore_nulls)
6359
+ end
6360
+
6361
+ # Get the last element of the Series.
6362
+ #
6363
+ # Returns `nil` if the Series is empty.
6364
+ #
6365
+ # @param ignore_nulls [Boolean]
6366
+ # Ignore null values (default `false`).
6367
+ # If set to `true`, the last non-null value is returned, otherwise `nil` is
6368
+ # returned if no non-null value exists.
6369
+ #
6370
+ # @return [Object]
6371
+ def last(ignore_nulls: false)
6372
+ _s.last(ignore_nulls)
6373
+ end
6374
+
6375
+ # Approximate count of unique values.
6376
+ #
6377
+ # This is done using the HyperLogLog++ algorithm for cardinality estimation.
6378
+ #
6379
+ # @return [Object]
6380
+ def approx_n_unique
6381
+ _s.approx_n_unique
6382
+ end
6383
+
4418
6384
  # Create an object namespace of all list related methods.
4419
6385
  #
4420
6386
  # @return [ListNameSpace]
@@ -4464,6 +6430,42 @@ module Polars
4464
6430
  StructNameSpace.new(self)
4465
6431
  end
4466
6432
 
6433
+ # Create an object namespace of all extension type related methods.
6434
+ #
6435
+ # @return [ExtensionNameSpace]
6436
+ def ext
6437
+ ExtensionNameSpace.new(self)
6438
+ end
6439
+
6440
+ # Create a plot namespace.
6441
+ #
6442
+ # @note
6443
+ # This functionality is currently considered **unstable**. It may be
6444
+ # changed at any point without it being considered a breaking change.
6445
+ #
6446
+ # @return [SeriesPlot]
6447
+ #
6448
+ # @example Histogram:
6449
+ # s = Polars::Series.new([1, 4, 4, 6, 2, 4, 3, 5, 5, 7, 1])
6450
+ # s.plot.hist
6451
+ def plot
6452
+ SeriesPlot.new(self)
6453
+ end
6454
+
6455
+ # Repeat the elements in this Series as specified in the given expression.
6456
+ #
6457
+ # The repeated elements are expanded into a List.
6458
+ #
6459
+ # @param by [Object]
6460
+ # Numeric column that determines how often the values will be repeated.
6461
+ # The column will be coerced to UInt32. Give this dtype to make the coercion
6462
+ # a no-op.
6463
+ #
6464
+ # @return [Object]
6465
+ def repeat_by(by)
6466
+ super
6467
+ end
6468
+
4467
6469
  private
4468
6470
 
4469
6471
  def initialize_copy(other)
@@ -4547,12 +6549,12 @@ module Polars
4547
6549
  ts = Utils.datetime_to_int(other, time_unit)
4548
6550
  f = ffi_func("#{op}_<>", Int64, _s)
4549
6551
  fail if f.nil?
4550
- return Utils.wrap_s(f.call(ts))
6552
+ return Utils.wrap_s(f.(ts))
4551
6553
  elsif other.is_a?(::Date) && dtype == Date
4552
6554
  d = Utils.date_to_int(other)
4553
6555
  f = ffi_func("#{op}_<>", Int32, _s)
4554
6556
  fail if f.nil?
4555
- return Utils.wrap_s(f.call(d))
6557
+ return Utils.wrap_s(f.(d))
4556
6558
  end
4557
6559
 
4558
6560
  if other.is_a?(Series)
@@ -4563,7 +6565,7 @@ module Polars
4563
6565
  if f.nil?
4564
6566
  raise NotImplementedError
4565
6567
  end
4566
- Utils.wrap_s(f.call(other))
6568
+ Utils.wrap_s(f.(other))
4567
6569
  end
4568
6570
 
4569
6571
  def ffi_func(name, dtype, _s)
@@ -4578,8 +6580,8 @@ module Polars
4578
6580
  return Utils.wrap_s(_s.send(op, other._s))
4579
6581
  end
4580
6582
 
4581
- if (other.is_a?(Float) || other.is_a?(::Date) || other.is_a?(::DateTime) || other.is_a?(::Time) || other.is_a?(::String)) && !is_float
4582
- _s2 = sequence_to_rbseries(name, [other])
6583
+ if (other.is_a?(Float) || other.is_a?(::Date) || other.is_a?(::DateTime) || other.is_a?(::Time) || other.is_a?(::String)) && !dtype.float?
6584
+ _s2 = Utils.sequence_to_rbseries(name, [other])
4583
6585
  return Utils.wrap_s(_s.send(op, _s2))
4584
6586
  end
4585
6587
 
@@ -4587,7 +6589,7 @@ module Polars
4587
6589
  if f.nil?
4588
6590
  raise ArgumentError, "cannot do arithmetic with series of dtype: #{dtype} and argument of type: #{other.class.name}"
4589
6591
  end
4590
- Utils.wrap_s(f.call(other))
6592
+ Utils.wrap_s(f.(other))
4591
6593
  end
4592
6594
 
4593
6595
  DTYPE_TO_FFINAME = {
@@ -4595,10 +6597,13 @@ module Polars
4595
6597
  Int16 => "i16",
4596
6598
  Int32 => "i32",
4597
6599
  Int64 => "i64",
6600
+ Int128 => "i128",
4598
6601
  UInt8 => "u8",
4599
6602
  UInt16 => "u16",
4600
6603
  UInt32 => "u32",
4601
6604
  UInt64 => "u64",
6605
+ UInt128 => "u128",
6606
+ Float16 => "f16",
4602
6607
  Float32 => "f32",
4603
6608
  Float64 => "f64",
4604
6609
  Boolean => "bool",
@@ -4613,262 +6618,5 @@ module Polars
4613
6618
  Struct => "struct",
4614
6619
  Binary => "binary"
4615
6620
  }
4616
-
4617
- def series_to_rbseries(name, values)
4618
- # should not be in-place?
4619
- values.rename(name, in_place: true)
4620
- values._s
4621
- end
4622
-
4623
- def numo_to_rbseries(name, values, strict: true, nan_to_null: false)
4624
- # not needed yet
4625
- # if !values.contiguous?
4626
- # end
4627
-
4628
- if values.shape.length == 1
4629
- values, dtype = numo_values_and_dtype(values)
4630
- strict = nan_to_null if [Numo::SFloat, Numo::DFloat].include?(dtype)
4631
- if dtype == Numo::RObject
4632
- sequence_to_rbseries(name, values.to_a, strict: strict)
4633
- else
4634
- constructor = numo_type_to_constructor(dtype)
4635
- # TODO improve performance
4636
- constructor.call(name, values.to_a, strict)
4637
- end
4638
- elsif values.shape.sum == 0
4639
- raise Todo
4640
- else
4641
- original_shape = values.shape
4642
- values = values.reshape(original_shape.inject(&:*))
4643
- rb_s = numo_to_rbseries(
4644
- name,
4645
- values,
4646
- strict: strict,
4647
- nan_to_null: nan_to_null
4648
- )
4649
- Utils.wrap_s(rb_s).reshape(original_shape)._s
4650
- end
4651
- end
4652
-
4653
- def numo_values_and_dtype(values)
4654
- [values, values.class]
4655
- end
4656
-
4657
- def numo_type_to_constructor(dtype)
4658
- {
4659
- Numo::Float32 => RbSeries.method(:new_opt_f32),
4660
- Numo::Float64 => RbSeries.method(:new_opt_f64),
4661
- Numo::Int8 => RbSeries.method(:new_opt_i8),
4662
- Numo::Int16 => RbSeries.method(:new_opt_i16),
4663
- Numo::Int32 => RbSeries.method(:new_opt_i32),
4664
- Numo::Int64 => RbSeries.method(:new_opt_i64),
4665
- Numo::UInt8 => RbSeries.method(:new_opt_u8),
4666
- Numo::UInt16 => RbSeries.method(:new_opt_u16),
4667
- Numo::UInt32 => RbSeries.method(:new_opt_u32),
4668
- Numo::UInt64 => RbSeries.method(:new_opt_u64)
4669
- }.fetch(dtype)
4670
- rescue KeyError
4671
- RbSeries.method(:new_object)
4672
- end
4673
-
4674
- def sequence_to_rbseries(name, values, dtype: nil, strict: true, dtype_if_empty: nil)
4675
- ruby_dtype = nil
4676
-
4677
- if (values.nil? || values.empty?) && dtype.nil?
4678
- dtype = dtype_if_empty || Float32
4679
- elsif dtype == List
4680
- ruby_dtype = ::Array
4681
- end
4682
-
4683
- rb_temporal_types = [::Date, ::DateTime, ::Time]
4684
- rb_temporal_types << ActiveSupport::TimeWithZone if defined?(ActiveSupport::TimeWithZone)
4685
-
4686
- value = _get_first_non_none(values)
4687
- if !value.nil?
4688
- if value.is_a?(Hash)
4689
- return DataFrame.new(values).to_struct(name)._s
4690
- end
4691
- end
4692
-
4693
- if !dtype.nil? && ![List, Struct, Unknown].include?(dtype) && Utils.is_polars_dtype(dtype) && ruby_dtype.nil?
4694
- if dtype == Array && !dtype.is_a?(Array) && value.is_a?(::Array)
4695
- dtype = Array.new(nil, value.size)
4696
- end
4697
-
4698
- constructor = polars_type_to_constructor(dtype)
4699
- rbseries = constructor.call(name, values, strict)
4700
-
4701
- base_type = dtype.is_a?(DataType) ? dtype.class : dtype
4702
- if [Date, Datetime, Duration, Time, Categorical, Boolean, Enum, Decimal].include?(base_type)
4703
- if rbseries.dtype != dtype
4704
- rbseries = rbseries.cast(dtype, true)
4705
- end
4706
- end
4707
- rbseries
4708
- elsif dtype == Struct
4709
- struct_schema = dtype.is_a?(Struct) ? dtype.to_schema : nil
4710
- empty = {}
4711
- DataFrame.sequence_to_rbdf(
4712
- values.map { |v| v.nil? ? empty : v },
4713
- schema: struct_schema,
4714
- orient: "row",
4715
- ).to_struct(name)
4716
- else
4717
- if ruby_dtype.nil?
4718
- if value.nil?
4719
- # generic default dtype
4720
- ruby_dtype = Float
4721
- else
4722
- ruby_dtype = value.class
4723
- end
4724
- end
4725
-
4726
- # temporal branch
4727
- if rb_temporal_types.include?(ruby_dtype)
4728
- if dtype.nil?
4729
- dtype = Utils.rb_type_to_dtype(ruby_dtype)
4730
- elsif rb_temporal_types.include?(dtype)
4731
- dtype = Utils.rb_type_to_dtype(dtype)
4732
- end
4733
- # TODO
4734
- time_unit = nil
4735
-
4736
- rb_series = RbSeries.new_from_any_values(name, values, strict)
4737
- if time_unit.nil?
4738
- s = Utils.wrap_s(rb_series)
4739
- else
4740
- s = Utils.wrap_s(rb_series).dt.cast_time_unit(time_unit)
4741
- end
4742
- s._s
4743
- elsif defined?(Numo::NArray) && value.is_a?(Numo::NArray) && value.shape.length == 1
4744
- raise Todo
4745
- elsif ruby_dtype == ::Array
4746
- if dtype.is_a?(Object)
4747
- return RbSeries.new_object(name, values, strict)
4748
- end
4749
- if dtype
4750
- srs = sequence_from_anyvalue_or_object(name, values)
4751
- if dtype != srs.dtype
4752
- srs = srs.cast(dtype, strict: false)
4753
- end
4754
- return srs
4755
- end
4756
- sequence_from_anyvalue_or_object(name, values)
4757
- elsif ruby_dtype == Series
4758
- RbSeries.new_series_list(name, values.map(&:_s), strict)
4759
- elsif ruby_dtype == RbSeries
4760
- RbSeries.new_series_list(name, values, strict)
4761
- else
4762
- constructor =
4763
- if value.is_a?(::String)
4764
- if value.encoding == Encoding::UTF_8
4765
- RbSeries.method(:new_str)
4766
- else
4767
- RbSeries.method(:new_binary)
4768
- end
4769
- elsif value.is_a?(Integer) && values.any? { |v| v.is_a?(Float) }
4770
- # TODO improve performance
4771
- RbSeries.method(:new_opt_f64)
4772
- else
4773
- rb_type_to_constructor(value.class)
4774
- end
4775
-
4776
- construct_series_with_fallbacks(constructor, name, values, dtype, strict: strict)
4777
- end
4778
- end
4779
- end
4780
-
4781
- def construct_series_with_fallbacks(constructor, name, values, dtype, strict:)
4782
- begin
4783
- constructor.call(name, values, strict)
4784
- rescue
4785
- if dtype.nil?
4786
- RbSeries.new_from_any_values(name, values, strict)
4787
- else
4788
- RbSeries.new_from_any_values_and_dtype(name, values, dtype, strict)
4789
- end
4790
- end
4791
- end
4792
-
4793
- def sequence_from_anyvalue_or_object(name, values)
4794
- RbSeries.new_from_any_values(name, values, true)
4795
- rescue
4796
- RbSeries.new_object(name, values, false)
4797
- end
4798
-
4799
- POLARS_TYPE_TO_CONSTRUCTOR = {
4800
- Float32 => RbSeries.method(:new_opt_f32),
4801
- Float64 => RbSeries.method(:new_opt_f64),
4802
- Int8 => RbSeries.method(:new_opt_i8),
4803
- Int16 => RbSeries.method(:new_opt_i16),
4804
- Int32 => RbSeries.method(:new_opt_i32),
4805
- Int64 => RbSeries.method(:new_opt_i64),
4806
- UInt8 => RbSeries.method(:new_opt_u8),
4807
- UInt16 => RbSeries.method(:new_opt_u16),
4808
- UInt32 => RbSeries.method(:new_opt_u32),
4809
- UInt64 => RbSeries.method(:new_opt_u64),
4810
- Decimal => RbSeries.method(:new_decimal),
4811
- Date => RbSeries.method(:new_from_any_values),
4812
- Datetime => RbSeries.method(:new_from_any_values),
4813
- Duration => RbSeries.method(:new_from_any_values),
4814
- Time => RbSeries.method(:new_from_any_values),
4815
- Boolean => RbSeries.method(:new_opt_bool),
4816
- Utf8 => RbSeries.method(:new_str),
4817
- Object => RbSeries.method(:new_object),
4818
- Categorical => RbSeries.method(:new_str),
4819
- Enum => RbSeries.method(:new_str),
4820
- Binary => RbSeries.method(:new_binary),
4821
- Null => RbSeries.method(:new_null)
4822
- }
4823
-
4824
- SYM_TYPE_TO_CONSTRUCTOR = {
4825
- f32: RbSeries.method(:new_opt_f32),
4826
- f64: RbSeries.method(:new_opt_f64),
4827
- i8: RbSeries.method(:new_opt_i8),
4828
- i16: RbSeries.method(:new_opt_i16),
4829
- i32: RbSeries.method(:new_opt_i32),
4830
- i64: RbSeries.method(:new_opt_i64),
4831
- u8: RbSeries.method(:new_opt_u8),
4832
- u16: RbSeries.method(:new_opt_u16),
4833
- u32: RbSeries.method(:new_opt_u32),
4834
- u64: RbSeries.method(:new_opt_u64),
4835
- bool: RbSeries.method(:new_opt_bool),
4836
- str: RbSeries.method(:new_str)
4837
- }
4838
-
4839
- def polars_type_to_constructor(dtype)
4840
- if dtype.is_a?(Array)
4841
- lambda do |name, values, strict|
4842
- RbSeries.new_array(dtype.width, dtype.inner, name, values, strict)
4843
- end
4844
- elsif dtype.is_a?(Class) && dtype < DataType
4845
- POLARS_TYPE_TO_CONSTRUCTOR.fetch(dtype)
4846
- elsif dtype.is_a?(DataType)
4847
- POLARS_TYPE_TO_CONSTRUCTOR.fetch(dtype.class)
4848
- else
4849
- SYM_TYPE_TO_CONSTRUCTOR.fetch(dtype.to_sym)
4850
- end
4851
- rescue KeyError
4852
- raise ArgumentError, "Cannot construct RbSeries for type #{dtype}."
4853
- end
4854
-
4855
- RB_TYPE_TO_CONSTRUCTOR = {
4856
- Float => RbSeries.method(:new_opt_f64),
4857
- Integer => RbSeries.method(:new_opt_i64),
4858
- TrueClass => RbSeries.method(:new_opt_bool),
4859
- FalseClass => RbSeries.method(:new_opt_bool),
4860
- BigDecimal => RbSeries.method(:new_decimal),
4861
- NilClass => RbSeries.method(:new_null)
4862
- }
4863
-
4864
- def rb_type_to_constructor(dtype)
4865
- RB_TYPE_TO_CONSTRUCTOR.fetch(dtype)
4866
- rescue KeyError
4867
- RbSeries.method(:new_object)
4868
- end
4869
-
4870
- def _get_first_non_none(values)
4871
- values.find { |v| !v.nil? }
4872
- end
4873
6621
  end
4874
6622
  end