rover-df 0.2.0 → 0.2.1

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: 2fb7c518e0c1d61e601012d0beff064fe04b6cfcfb852fd97d28b999f1173445
4
- data.tar.gz: b1a3f177d05095799dc2f02082d921d87774375e3f91db468539540c0c5d9482
3
+ metadata.gz: 1c750c49e4cb313565a3b52a273c4820ae406471a1007ddb8e83742f3f2640f1
4
+ data.tar.gz: 2a7469abd672a87c9b4c874469baf07f42b22067ac2281c424eeb7b60841bbfe
5
5
  SHA512:
6
- metadata.gz: 5a98bce5cdb1cd8ed2442dd54cdcc0bcb93f39ff0daa4c4386a5805b285bd898a10278aad2522947bc944e4f995c833ebbe96f08b29421e048fd850cb2cf7903
7
- data.tar.gz: a64bdc8da3a2202f0b4583d02eb162e07d8ae387bacf4f434ab8b6377a8752da0919c24506616df0bb90667dc1eab9f7b4acd6076ef932d1fb69f57c395e6e00
6
+ metadata.gz: 24e7874a67e498cadb8c2b4773f00c5cf53ab76e8231b7c762b8f403c2d4783809beb44ba3b37cb50b801032c3a3a9c140b18e1a10967eb331c517b5dd5251aa
7
+ data.tar.gz: b62f4bfd7591e9c4869ab13e4e6efeba5c4e121c92470bc81d517ec85045a2fdc080a7a6ca3f61a15e7c98335543fcb11893d00d374cb5a3cf1294e12ed65130
@@ -1,3 +1,8 @@
1
+ ## 0.2.1 (2020-11-23)
2
+
3
+ - Added `plot` method to data frames
4
+ - Improved error message when too few headers
5
+
1
6
  ## 0.2.0 (2020-08-17)
2
7
 
3
8
  - Added `numeric?` and `zip` methods to vectors
data/README.md CHANGED
@@ -4,7 +4,9 @@ Simple, powerful data frames for Ruby
4
4
 
5
5
  :mountain: Designed for data exploration and machine learning, and powered by [Numo](https://github.com/ruby-numo/numo-narray)
6
6
 
7
- [![Build Status](https://travis-ci.org/ankane/rover.svg?branch=master)](https://travis-ci.org/ankane/rover)
7
+ :evergreen_tree: Uses [Vega](https://github.com/ankane/vega) for visualization
8
+
9
+ [![Build Status](https://github.com/ankane/rover/workflows/build/badge.svg?branch=master)](https://github.com/ankane/rover/actions)
8
10
 
9
11
  ## Installation
10
12
 
@@ -198,6 +200,20 @@ Multiple groups
198
200
  df.group([:a, :b]).count
199
201
  ```
200
202
 
203
+ ## Visualization [master]
204
+
205
+ Add [Vega](https://github.com/ankane/vega) to your application’s Gemfile:
206
+
207
+ ```ruby
208
+ gem 'vega'
209
+ ```
210
+
211
+ And use:
212
+
213
+ ```ruby
214
+ df.plot(:a, :b)
215
+ ```
216
+
201
217
  ## Updating Data
202
218
 
203
219
  Add a new column
@@ -11,12 +11,12 @@ module Rover
11
11
  class << self
12
12
  def read_csv(path, types: nil, **options)
13
13
  require "csv"
14
- csv_to_df(CSV.read(path, **csv_options(options)), types: types)
14
+ csv_to_df(CSV.read(path, **csv_options(options)), types: types, headers: options[:headers])
15
15
  end
16
16
 
17
17
  def parse_csv(str, types: nil, **options)
18
18
  require "csv"
19
- csv_to_df(CSV.parse(str, **csv_options(options)), types: types)
19
+ csv_to_df(CSV.parse(str, **csv_options(options)), types: types, headers: options[:headers])
20
20
  end
21
21
 
22
22
  private
@@ -28,7 +28,11 @@ module Rover
28
28
  options
29
29
  end
30
30
 
31
- def csv_to_df(table, types: nil)
31
+ def csv_to_df(table, types: nil, headers: nil)
32
+ if headers && headers.size < table.headers.size
33
+ raise ArgumentError, "Expected #{table.headers.size} headers, got #{headers.size}"
34
+ end
35
+
32
36
  table.by_col!
33
37
  data = {}
34
38
  table.each do |k, v|
@@ -237,7 +237,12 @@ module Rover
237
237
  # for IRuby
238
238
  def to_html
239
239
  require "iruby"
240
- IRuby::HTML.table(to_h)
240
+ if size > 7
241
+ # pass 8 rows so maxrows is applied
242
+ IRuby::HTML.table((self[0..4] + self[-4..-1]).to_h, maxrows: 7)
243
+ else
244
+ IRuby::HTML.table(to_h)
245
+ end
241
246
  end
242
247
 
243
248
  # TODO handle long text better
@@ -291,8 +296,8 @@ module Rover
291
296
  dup.sort_by!(&block)
292
297
  end
293
298
 
294
- def group(columns)
295
- Group.new(self, columns)
299
+ def group(*columns)
300
+ Group.new(self, columns.flatten)
296
301
  end
297
302
 
298
303
  [:max, :min, :median, :mean, :percentile, :sum].each do |name|
@@ -357,6 +362,49 @@ module Rover
357
362
  keys.all? { |k| self[k] == other[k] }
358
363
  end
359
364
 
365
+ def plot(x = nil, y = nil, type: nil)
366
+ require "vega"
367
+
368
+ raise ArgumentError, "Must specify columns" if keys.size != 2 && (!x || !y)
369
+ x ||= keys[0]
370
+ y ||= keys[1]
371
+ type ||= begin
372
+ if self[x].numeric? && self[y].numeric?
373
+ "scatter"
374
+ elsif types[x] == :object && self[y].numeric?
375
+ "column"
376
+ else
377
+ raise "Cannot determine type"
378
+ end
379
+ end
380
+ data = self[[x, y]]
381
+
382
+ case type
383
+ when "scatter"
384
+ Vega.lite
385
+ .data(data)
386
+ .mark(type: "circle", tooltip: true)
387
+ .encoding(
388
+ x: {field: x, type: "quantitative", scale: {zero: false}},
389
+ y: {field: y, type: "quantitative", scale: {zero: false}},
390
+ size: {value: 60}
391
+ )
392
+ .config(axis: {title: nil, labelFontSize: 12})
393
+ when "column"
394
+ Vega.lite
395
+ .data(data)
396
+ .mark(type: "bar", tooltip: true)
397
+ .encoding(
398
+ # TODO determine label angle
399
+ x: {field: x, type: "nominal", sort: "none", axis: {labelAngle: 0}},
400
+ y: {field: y, type: "quantitative"}
401
+ )
402
+ .config(axis: {title: nil, labelFontSize: 12})
403
+ else
404
+ raise ArgumentError, "Invalid type: #{type}"
405
+ end
406
+ end
407
+
360
408
  private
361
409
 
362
410
  def check_key(key)
@@ -2,7 +2,11 @@ module Rover
2
2
  class Group
3
3
  def initialize(df, columns)
4
4
  @df = df
5
- @columns = Array(columns)
5
+ @columns = columns
6
+ end
7
+
8
+ def group(*columns)
9
+ Group.new(@df, @columns + columns.flatten)
6
10
  end
7
11
 
8
12
  [:count, :max, :min, :mean, :median, :percentile, :sum].each do |name|
@@ -95,7 +95,7 @@ module Rover
95
95
  define_method(op) do |other|
96
96
  other = other.to_numo if other.is_a?(Vector)
97
97
  # TODO better logic
98
- if @data.is_a?(Numo::RObject)
98
+ if @data.is_a?(Numo::RObject) && !other.is_a?(Numo::RObject)
99
99
  map { |v| v.send(op, other) }
100
100
  else
101
101
  Vector.new(@data.send(op, other))
@@ -1,3 +1,3 @@
1
1
  module Rover
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rover-df
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-17 00:00:00.000000000 Z
11
+ date: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -108,7 +108,7 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description:
111
+ description:
112
112
  email: andrew@chartkick.com
113
113
  executables: []
114
114
  extensions: []
@@ -127,7 +127,7 @@ homepage: https://github.com/ankane/rover
127
127
  licenses:
128
128
  - MIT
129
129
  metadata: {}
130
- post_install_message:
130
+ post_install_message:
131
131
  rdoc_options: []
132
132
  require_paths:
133
133
  - lib
@@ -142,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  - !ruby/object:Gem::Version
143
143
  version: '0'
144
144
  requirements: []
145
- rubygems_version: 3.1.2
146
- signing_key:
145
+ rubygems_version: 3.1.4
146
+ signing_key:
147
147
  specification_version: 4
148
148
  summary: Simple, powerful data frames for Ruby
149
149
  test_files: []