polars-df 0.3.0-x86_64-darwin → 0.3.1-x86_64-darwin

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98b1c8e9c64af2bfb3909d9fab6ea22b41012fe4042338c1dfff2024fa7bb67b
4
- data.tar.gz: e664796bc914c409e467c6d7f9a366744b4f2ca722cb2642b427553c4cf29d8e
3
+ metadata.gz: 8db31e27e3e68bb1714ec1feafddf9874fde4f3d7bb8f399ade18b0b7e48e98d
4
+ data.tar.gz: bd9704f2bee8c19dfe1e479abe5097100edccd9b22b051c9010fb0485e795e09
5
5
  SHA512:
6
- metadata.gz: 4dbb0dd9ffc24e9267be79d4d717c653e4d3be53b485cb42459bf3c59f6146d06c79d53a80355d25b0c9fa553ec2d297e9316a9633ddefaef919ec0b9bda6ff3
7
- data.tar.gz: 8e5094459614bd726f53e52d808399c344b4acaca09e0ee7e035c1bb7dd0cc2db77813849f4d7db9d055ccac3152d62ef43f9aca9f2f12c2284be68d0d786c45
6
+ metadata.gz: 3cf8e1aee531ee78d36b20ae2387fa37c3ce00204b88eae6df86c71daf1becf689faca9991287dcd4ecd247f81dbfbfc6bb9c5836faf0ff9008ba28bf9d58343
7
+ data.tar.gz: 502e8596310e9cb5ae9b71e7da44067f5253e5eb7940a1da085f4f1bc2b190ae9c39a50e9ba8b5c2ded72e2fbfec1c4e82bb109a06cf4d1096c01201a8064c77
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.3.1 (2023-02-21)
2
+
3
+ - Added `to_numo` method to `Series` and `DataFrame`
4
+ - Added `plot` method to `DataFrame`
5
+ - Fixed `is_datelike` method for `Datetime` and `Duration`
6
+
1
7
  ## 0.3.0 (2023-02-15)
2
8
 
3
9
  - Updated Polars to 0.27.1
data/Cargo.lock CHANGED
@@ -1430,7 +1430,7 @@ dependencies = [
1430
1430
 
1431
1431
  [[package]]
1432
1432
  name = "polars"
1433
- version = "0.3.0"
1433
+ version = "0.3.1"
1434
1434
  dependencies = [
1435
1435
  "ahash",
1436
1436
  "jemallocator",
@@ -1630,33 +1630,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1630
1630
  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1631
1631
  DEALINGS IN THE SOFTWARE.
1632
1632
 
1633
- ================================================================================
1634
- array-init-cursor LICENSE-MIT
1635
- ================================================================================
1636
-
1637
- MIT License
1638
-
1639
- Copyright (c) 2021 The Planus Project Developers
1640
-
1641
- Permission is hereby granted, free of charge, to any person obtaining a copy
1642
- of this software and associated documentation files (the "Software"), to deal
1643
- in the Software without restriction, including without limitation the rights
1644
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1645
- copies of the Software, and to permit persons to whom the Software is
1646
- furnished to do so, subject to the following conditions:
1647
-
1648
- The above copyright notice and this permission notice shall be included in all
1649
- copies or substantial portions of the Software.
1650
-
1651
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1652
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1653
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1654
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1655
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1656
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1657
- SOFTWARE.
1658
-
1659
-
1660
1633
  ================================================================================
1661
1634
  array-init-cursor LICENSE-APACHE
1662
1635
  ================================================================================
@@ -1839,6 +1812,33 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1839
1812
  END OF TERMS AND CONDITIONS
1840
1813
 
1841
1814
 
1815
+ ================================================================================
1816
+ array-init-cursor LICENSE-MIT
1817
+ ================================================================================
1818
+
1819
+ MIT License
1820
+
1821
+ Copyright (c) 2021 The Planus Project Developers
1822
+
1823
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1824
+ of this software and associated documentation files (the "Software"), to deal
1825
+ in the Software without restriction, including without limitation the rights
1826
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1827
+ copies of the Software, and to permit persons to whom the Software is
1828
+ furnished to do so, subject to the following conditions:
1829
+
1830
+ The above copyright notice and this permission notice shall be included in all
1831
+ copies or substantial portions of the Software.
1832
+
1833
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1834
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1835
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1836
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1837
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1838
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1839
+ SOFTWARE.
1840
+
1841
+
1842
1842
  ================================================================================
1843
1843
  arrow-format LICENSE
1844
1844
  ================================================================================
@@ -27534,33 +27534,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
27534
27534
  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27535
27535
  DEALINGS IN THE SOFTWARE.
27536
27536
 
27537
- ================================================================================
27538
- planus LICENSE-MIT
27539
- ================================================================================
27540
-
27541
- MIT License
27542
-
27543
- Copyright (c) 2021 The Planus Project Developers
27544
-
27545
- Permission is hereby granted, free of charge, to any person obtaining a copy
27546
- of this software and associated documentation files (the "Software"), to deal
27547
- in the Software without restriction, including without limitation the rights
27548
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27549
- copies of the Software, and to permit persons to whom the Software is
27550
- furnished to do so, subject to the following conditions:
27551
-
27552
- The above copyright notice and this permission notice shall be included in all
27553
- copies or substantial portions of the Software.
27554
-
27555
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27556
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27557
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27558
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27559
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27560
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27561
- SOFTWARE.
27562
-
27563
-
27564
27537
  ================================================================================
27565
27538
  planus LICENSE-APACHE
27566
27539
  ================================================================================
@@ -27743,6 +27716,33 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
27743
27716
  END OF TERMS AND CONDITIONS
27744
27717
 
27745
27718
 
27719
+ ================================================================================
27720
+ planus LICENSE-MIT
27721
+ ================================================================================
27722
+
27723
+ MIT License
27724
+
27725
+ Copyright (c) 2021 The Planus Project Developers
27726
+
27727
+ Permission is hereby granted, free of charge, to any person obtaining a copy
27728
+ of this software and associated documentation files (the "Software"), to deal
27729
+ in the Software without restriction, including without limitation the rights
27730
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27731
+ copies of the Software, and to permit persons to whom the Software is
27732
+ furnished to do so, subject to the following conditions:
27733
+
27734
+ The above copyright notice and this permission notice shall be included in all
27735
+ copies or substantial portions of the Software.
27736
+
27737
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27738
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27739
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27740
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27741
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27742
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27743
+ SOFTWARE.
27744
+
27745
+
27746
27746
  ================================================================================
27747
27747
  polars LICENSE
27748
27748
  ================================================================================
data/README.md CHANGED
@@ -282,10 +282,10 @@ df.to_dummies
282
282
 
283
283
  ## Conversion
284
284
 
285
- Array of rows
285
+ Array of hashes
286
286
 
287
287
  ```ruby
288
- df.rows
288
+ df.rows(named: true)
289
289
  ```
290
290
 
291
291
  Hash of series
@@ -308,6 +308,12 @@ Parquet
308
308
  df.write_parquet("file.parquet")
309
309
  ```
310
310
 
311
+ Numo array
312
+
313
+ ```ruby
314
+ df.to_numo
315
+ ```
316
+
311
317
  ## Types
312
318
 
313
319
  You can specify column types when creating a data frame
@@ -343,6 +349,38 @@ Cast a column
343
349
  df["a"].cast(Polars::Int32)
344
350
  ```
345
351
 
352
+ ## Visualization
353
+
354
+ Add [Vega](https://github.com/ankane/vega-ruby) to your application’s Gemfile:
355
+
356
+ ```ruby
357
+ gem "vega"
358
+ ```
359
+
360
+ And use:
361
+
362
+ ```ruby
363
+ df.plot("a", "b")
364
+ ```
365
+
366
+ Specify the chart type (`line`, `pie`, `column`, `bar`, `area`, or `scatter`)
367
+
368
+ ```ruby
369
+ df.plot("a", "b", type: "pie")
370
+ ```
371
+
372
+ Group data
373
+
374
+ ```ruby
375
+ df.groupby("c").plot("a", "b")
376
+ ```
377
+
378
+ Stacked columns or bars
379
+
380
+ ```ruby
381
+ df.groupby("c").plot("a", "b", stacked: true)
382
+ ```
383
+
346
384
  ## History
347
385
 
348
386
  View the [changelog](CHANGELOG.md)
Binary file
Binary file
Binary file
@@ -1,6 +1,8 @@
1
1
  module Polars
2
2
  # Two-dimensional data structure representing data as a table with rows and columns.
3
3
  class DataFrame
4
+ include Plot
5
+
4
6
  # @private
5
7
  attr_accessor :_df
6
8
 
@@ -604,10 +606,10 @@ module Polars
604
606
  return Slice.new(self).apply(item)
605
607
  end
606
608
 
607
- if Utils.is_str_sequence(item, allow_str: false)
609
+ if item.is_a?(Array) && item.all? { |v| Utils.strlike?(v) }
608
610
  # select multiple columns
609
611
  # df[["foo", "bar"]]
610
- return _from_rbdf(_df.select(item))
612
+ return _from_rbdf(_df.select(item.map(&:to_s)))
611
613
  end
612
614
 
613
615
  if Utils.is_int_sequence(item)
@@ -689,7 +691,8 @@ module Polars
689
691
  # @example
690
692
  # df = Polars::DataFrame.new({"foo" => [1, 2, 3], "bar" => [4, 5, 6]})
691
693
  # df.to_hashes
692
- # [{'foo': 1, 'bar': 4}, {'foo': 2, 'bar': 5}, {'foo': 3, 'bar': 6}]
694
+ # # =>
695
+ # # [{"foo"=>1, "bar"=>4}, {"foo"=>2, "bar"=>5}, {"foo"=>3, "bar"=>6}]
693
696
  def to_hashes
694
697
  rbdf = _df
695
698
  names = columns
@@ -699,8 +702,26 @@ module Polars
699
702
  end
700
703
  end
701
704
 
702
- # def to_numo
703
- # end
705
+ # Convert DataFrame to a 2D Numo array.
706
+ #
707
+ # This operation clones data.
708
+ #
709
+ # @return [Numo::NArray]
710
+ #
711
+ # @example
712
+ # df = Polars::DataFrame.new(
713
+ # {"foo" => [1, 2, 3], "bar" => [6, 7, 8], "ham" => ["a", "b", "c"]}
714
+ # )
715
+ # df.to_numo.class
716
+ # # => Numo::RObject
717
+ def to_numo
718
+ out = _df.to_numo
719
+ if out.nil?
720
+ Numo::NArray.vstack(width.times.map { |i| to_series(i).to_numo }).transpose
721
+ else
722
+ out
723
+ end
724
+ end
704
725
 
705
726
  # no to_pandas
706
727
 
@@ -84,6 +84,8 @@ module Polars
84
84
 
85
85
  # Calendar date and time type.
86
86
  class Datetime < TemporalType
87
+ attr_reader :tu
88
+
87
89
  def initialize(time_unit = "us", time_zone = nil)
88
90
  @tu = time_unit || "us"
89
91
  @time_zone = time_zone
@@ -92,6 +94,8 @@ module Polars
92
94
 
93
95
  # Time duration/delta type.
94
96
  class Duration < TemporalType
97
+ attr_reader :tu
98
+
95
99
  def initialize(time_unit = "us")
96
100
  @tu = time_unit
97
101
  end
@@ -571,5 +571,16 @@ module Polars
571
571
  def agg_list
572
572
  agg(Polars.all.list)
573
573
  end
574
+
575
+ # Plot data.
576
+ #
577
+ # @return [Vega::LiteChart]
578
+ def plot(*args, **options)
579
+ raise ArgumentError, "Multiple groups not supported" if by.is_a?(Array) && by.size > 1
580
+ # same message as Ruby
581
+ raise ArgumentError, "unknown keyword: :group" if options.key?(:group)
582
+
583
+ Utils.wrap_df(_df).plot(*args, **options, group: by)
584
+ end
574
585
  end
575
586
  end
@@ -0,0 +1,109 @@
1
+ module Polars
2
+ module Plot
3
+ # Plot data.
4
+ #
5
+ # @return [Vega::LiteChart]
6
+ def plot(x = nil, y = nil, type: nil, group: nil, stacked: nil)
7
+ require "vega"
8
+
9
+ raise ArgumentError, "Must specify columns" if columns.size != 2 && (!x || !y)
10
+ x ||= columns[0]
11
+ y ||= columns[1]
12
+ type ||= begin
13
+ if self[x].numeric? && self[y].numeric?
14
+ "scatter"
15
+ elsif self[x].utf8? && self[y].numeric?
16
+ "column"
17
+ elsif (self[x].dtype == Date || self[x].dtype.is_a?(Datetime)) && self[y].numeric?
18
+ "line"
19
+ else
20
+ raise "Cannot determine type. Use the type option."
21
+ end
22
+ end
23
+ df = self[(group.nil? ? [x, y] : [x, y, group]).map(&:to_s).uniq]
24
+ data = df.rows(named: true)
25
+
26
+ case type
27
+ when "line", "area"
28
+ x_type =
29
+ if df[x].numeric?
30
+ "quantitative"
31
+ elsif df[x].datelike?
32
+ "temporal"
33
+ else
34
+ "nominal"
35
+ end
36
+
37
+ scale = x_type == "temporal" ? {type: "utc"} : {}
38
+ encoding = {
39
+ x: {field: x, type: x_type, scale: scale},
40
+ y: {field: y, type: "quantitative"}
41
+ }
42
+ encoding[:color] = {field: group} if group
43
+
44
+ Vega.lite
45
+ .data(data)
46
+ .mark(type: type, tooltip: true, interpolate: "cardinal", point: {size: 60})
47
+ .encoding(encoding)
48
+ .config(axis: {labelFontSize: 12})
49
+ when "pie"
50
+ raise ArgumentError, "Cannot use group option with pie chart" unless group.nil?
51
+
52
+ Vega.lite
53
+ .data(data)
54
+ .mark(type: "arc", tooltip: true)
55
+ .encoding(
56
+ color: {field: x, type: "nominal", sort: "none", axis: {title: nil}, legend: {labelFontSize: 12}},
57
+ theta: {field: y, type: "quantitative"}
58
+ )
59
+ .view(stroke: nil)
60
+ when "column"
61
+ encoding = {
62
+ x: {field: x, type: "nominal", sort: "none", axis: {labelAngle: 0}},
63
+ y: {field: y, type: "quantitative"}
64
+ }
65
+ if group
66
+ encoding[:color] = {field: group}
67
+ encoding[:xOffset] = {field: group} unless stacked
68
+ end
69
+
70
+ Vega.lite
71
+ .data(data)
72
+ .mark(type: "bar", tooltip: true)
73
+ .encoding(encoding)
74
+ .config(axis: {labelFontSize: 12})
75
+ when "bar"
76
+ encoding = {
77
+ # TODO determine label angle
78
+ y: {field: x, type: "nominal", sort: "none", axis: {labelAngle: 0}},
79
+ x: {field: y, type: "quantitative"}
80
+ }
81
+ if group
82
+ encoding[:color] = {field: group}
83
+ encoding[:yOffset] = {field: group} unless stacked
84
+ end
85
+
86
+ Vega.lite
87
+ .data(data)
88
+ .mark(type: "bar", tooltip: true)
89
+ .encoding(encoding)
90
+ .config(axis: {labelFontSize: 12})
91
+ when "scatter"
92
+ encoding = {
93
+ x: {field: x, type: "quantitative", scale: {zero: false}},
94
+ y: {field: y, type: "quantitative", scale: {zero: false}},
95
+ size: {value: 60}
96
+ }
97
+ encoding[:color] = {field: group} if group
98
+
99
+ Vega.lite
100
+ .data(data)
101
+ .mark(type: "circle", tooltip: true)
102
+ .encoding(encoding)
103
+ .config(axis: {labelFontSize: 12})
104
+ else
105
+ raise ArgumentError, "Invalid type: #{type}"
106
+ end
107
+ end
108
+ end
109
+ end
data/lib/polars/series.rb CHANGED
@@ -1776,8 +1776,9 @@ module Polars
1776
1776
  # s.is_datelike
1777
1777
  # # => true
1778
1778
  def is_datelike
1779
- [Date, Datetime, Duration, Time].include?(dtype)
1779
+ [Date, Time].include?(dtype) || dtype.is_a?(Datetime) || dtype.is_a?(Duration)
1780
1780
  end
1781
+ alias_method :datelike?, :is_datelike
1781
1782
 
1782
1783
  # Check if this Series has floating point numbers.
1783
1784
  #
@@ -1823,8 +1824,45 @@ module Polars
1823
1824
  # def view
1824
1825
  # end
1825
1826
 
1826
- # def to_numo
1827
- # end
1827
+ # Convert this Series to a Numo array. This operation clones data but is completely safe.
1828
+ #
1829
+ # @return [Numo::NArray]
1830
+ #
1831
+ # @example
1832
+ # s = Polars::Series.new("a", [1, 2, 3])
1833
+ # s.to_numo
1834
+ # # =>
1835
+ # # Numo::Int64#shape=[3]
1836
+ # # [1, 2, 3]
1837
+ def to_numo
1838
+ if !has_validity
1839
+ if is_datelike
1840
+ Numo::RObject.cast(to_a)
1841
+ elsif is_numeric
1842
+ # TODO make more efficient
1843
+ {
1844
+ UInt8 => Numo::UInt8,
1845
+ UInt16 => Numo::UInt16,
1846
+ UInt32 => Numo::UInt32,
1847
+ UInt64 => Numo::UInt64,
1848
+ Int8 => Numo::Int8,
1849
+ Int16 => Numo::Int16,
1850
+ Int32 => Numo::Int32,
1851
+ Int64 => Numo::Int64,
1852
+ Float32 => Numo::SFloat,
1853
+ Float64 => Numo::DFloat
1854
+ }.fetch(dtype).cast(to_a)
1855
+ elsif is_boolean
1856
+ Numo::Bit.cast(to_a)
1857
+ else
1858
+ _s.to_numo
1859
+ end
1860
+ elsif is_datelike
1861
+ Numo::RObject.cast(to_a)
1862
+ else
1863
+ _s.to_numo
1864
+ end
1865
+ end
1828
1866
 
1829
1867
  # Set masked values.
1830
1868
  #
@@ -1,4 +1,4 @@
1
1
  module Polars
2
2
  # @private
3
- VERSION = "0.3.0"
3
+ VERSION = "0.3.1"
4
4
  end
data/lib/polars.rb CHANGED
@@ -15,6 +15,7 @@ require_relative "polars/batched_csv_reader"
15
15
  require_relative "polars/cat_expr"
16
16
  require_relative "polars/cat_name_space"
17
17
  require_relative "polars/convert"
18
+ require_relative "polars/plot"
18
19
  require_relative "polars/data_frame"
19
20
  require_relative "polars/data_types"
20
21
  require_relative "polars/date_time_expr"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polars-df
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: x86_64-darwin
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-16 00:00:00.000000000 Z
11
+ date: 2023-02-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: andrew@ankane.org
@@ -49,6 +49,7 @@ files:
49
49
  - lib/polars/list_expr.rb
50
50
  - lib/polars/list_name_space.rb
51
51
  - lib/polars/meta_expr.rb
52
+ - lib/polars/plot.rb
52
53
  - lib/polars/rolling_group_by.rb
53
54
  - lib/polars/series.rb
54
55
  - lib/polars/slice.rb