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

Sign up to get free protection for your applications and to get access to all the features.
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