rover-df 0.1.1 → 0.2.4
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 +4 -4
- data/CHANGELOG.md +30 -0
- data/LICENSE.txt +1 -1
- data/README.md +63 -8
- data/lib/rover.rb +7 -3
- data/lib/rover/data_frame.rb +115 -14
- data/lib/rover/group.rb +18 -17
- data/lib/rover/vector.rb +40 -10
- data/lib/rover/version.rb +1 -1
- metadata +10 -94
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a96f5fa610232beb50eb2d22cd87b52627dfda44139e618fb0fa5d82f4d90fa
|
4
|
+
data.tar.gz: 899ae175705f7195a994c0bfd19fd021334404d07440f05153c08be5fa08c11b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc61f769ce5bac5fcda65dcc25fb940f7bf9f81ac168029748b5ccf8bfb896008f0836f9523ca3785e22782dff3f4d8dccc19ae823f944391c47df41fd88b3ec
|
7
|
+
data.tar.gz: 5a0c7e5e77233ef8bf7b4df23d711ec22a2e85165715ca330344a0b6cd5bef99e571256496e9c6f6037bf0fc0c771b4e951d91f0a85c17211127649d6e246878
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
## 0.2.4 (2021-06-03)
|
2
|
+
|
3
|
+
- Added grouping for `std` and `var`
|
4
|
+
- Fixed `==` for data frames
|
5
|
+
- Fixed error with `first` and `last` for data frames
|
6
|
+
- Fixed error with `last` when vector size is smaller than `n`
|
7
|
+
|
8
|
+
## 0.2.3 (2021-02-08)
|
9
|
+
|
10
|
+
- Added `select`, `reject`, and `map!` methods to vectors
|
11
|
+
|
12
|
+
## 0.2.2 (2021-01-01)
|
13
|
+
|
14
|
+
- Added line, pie, area, and bar charts
|
15
|
+
- Added `|` and `^` for vectors
|
16
|
+
- Fixed typecasting with `map`
|
17
|
+
|
18
|
+
## 0.2.1 (2020-11-23)
|
19
|
+
|
20
|
+
- Added `plot` method to data frames
|
21
|
+
- Improved error message when too few headers
|
22
|
+
|
23
|
+
## 0.2.0 (2020-08-17)
|
24
|
+
|
25
|
+
- Added `numeric?` and `zip` methods to vectors
|
26
|
+
- Changed group calculations to return a data frame instead of a hash
|
27
|
+
- Changed `each_row` to return enumerator
|
28
|
+
- Improved inspect
|
29
|
+
- Fixed `any?`, `all?`, and `uniq` for boolean vectors
|
30
|
+
|
1
31
|
## 0.1.1 (2020-06-10)
|
2
32
|
|
3
33
|
- Added methods and options for types
|
data/LICENSE.txt
CHANGED
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
|
-
[
|
7
|
+
:evergreen_tree: Uses [Vega](https://github.com/ankane/vega) for visualization
|
8
|
+
|
9
|
+
[](https://github.com/ankane/rover/actions)
|
8
10
|
|
9
11
|
## Installation
|
10
12
|
|
@@ -121,30 +123,53 @@ df[1..3]
|
|
121
123
|
df[[1, 4, 5]]
|
122
124
|
```
|
123
125
|
|
126
|
+
Iterate over rows
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
df.each_row { |row| ... }
|
130
|
+
```
|
131
|
+
|
132
|
+
Iterate over a column
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
df[:a].each { |item| ... }
|
136
|
+
# or
|
137
|
+
df[:a].each_with_index { |item, index| ... }
|
138
|
+
```
|
139
|
+
|
124
140
|
## Filtering
|
125
141
|
|
126
142
|
Filter on a condition
|
127
143
|
|
128
144
|
```ruby
|
145
|
+
df[df[:a] == 100]
|
146
|
+
df[df[:a] != 100]
|
129
147
|
df[df[:a] > 100]
|
148
|
+
df[df[:a] >= 100]
|
149
|
+
df[df[:a] < 100]
|
150
|
+
df[df[:a] <= 100]
|
130
151
|
```
|
131
152
|
|
132
|
-
|
153
|
+
In
|
133
154
|
|
134
155
|
```ruby
|
135
|
-
df[df[:a]
|
156
|
+
df[df[:a].in?([1, 2, 3])]
|
157
|
+
df[df[:a].in?(1..3)]
|
158
|
+
df[df[:a].in?(["a", "b", "c"])]
|
136
159
|
```
|
137
160
|
|
138
|
-
|
161
|
+
Not in
|
139
162
|
|
140
163
|
```ruby
|
141
|
-
df[df[:a]
|
164
|
+
df[!df[:a].in?([1, 2, 3])]
|
142
165
|
```
|
143
166
|
|
144
|
-
|
167
|
+
And, or, and exclusive or
|
145
168
|
|
146
169
|
```ruby
|
147
|
-
df[df[:a]
|
170
|
+
df[(df[:a] > 100) & (df[:b] == "one")] # and
|
171
|
+
df[(df[:a] > 100) | (df[:b] == "one")] # or
|
172
|
+
df[(df[:a] > 100) ^ (df[:b] == "one")] # xor
|
148
173
|
```
|
149
174
|
|
150
175
|
## Operations
|
@@ -170,6 +195,8 @@ df[:a].median
|
|
170
195
|
df[:a].percentile(90)
|
171
196
|
df[:a].min
|
172
197
|
df[:a].max
|
198
|
+
df[:a].std
|
199
|
+
df[:a].var
|
173
200
|
```
|
174
201
|
|
175
202
|
Count occurrences
|
@@ -204,6 +231,26 @@ Multiple groups
|
|
204
231
|
df.group([:a, :b]).count
|
205
232
|
```
|
206
233
|
|
234
|
+
## Visualization
|
235
|
+
|
236
|
+
Add [Vega](https://github.com/ankane/vega) to your application’s Gemfile:
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
gem 'vega'
|
240
|
+
```
|
241
|
+
|
242
|
+
And use:
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
df.plot(:a, :b)
|
246
|
+
```
|
247
|
+
|
248
|
+
Specify the chart type (`line`, `pie`, `column`, `bar`, `area`, or `scatter`)
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
df.plot(:a, :b, type: "pie")
|
252
|
+
```
|
253
|
+
|
207
254
|
## Updating Data
|
208
255
|
|
209
256
|
Add a new column
|
@@ -228,6 +275,14 @@ df[:a][0..2] = 1
|
|
228
275
|
df[:a][0..2] = [1, 2, 3]
|
229
276
|
```
|
230
277
|
|
278
|
+
Update all elements
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
df[:a] = df[:a].map { |v| v.gsub("a", "b") }
|
282
|
+
# or
|
283
|
+
df[:a].map! { |v| v.gsub("a", "b") }
|
284
|
+
```
|
285
|
+
|
231
286
|
Update elements matching a condition
|
232
287
|
|
233
288
|
```ruby
|
@@ -340,7 +395,7 @@ df.to_csv
|
|
340
395
|
|
341
396
|
## Types
|
342
397
|
|
343
|
-
|
398
|
+
You can specify column types when creating a data frame
|
344
399
|
|
345
400
|
```ruby
|
346
401
|
Rover::DataFrame.new(data, types: {"a" => :int, "b" => :float})
|
data/lib/rover.rb
CHANGED
@@ -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|
|
data/lib/rover/data_frame.rb
CHANGED
@@ -72,6 +72,7 @@ module Rover
|
|
72
72
|
# multiple columns
|
73
73
|
df = DataFrame.new
|
74
74
|
where.each do |k|
|
75
|
+
check_column(k, true)
|
75
76
|
df[k] = @vectors[k]
|
76
77
|
end
|
77
78
|
df
|
@@ -81,8 +82,9 @@ module Rover
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
84
|
-
# return each row as a hash
|
85
85
|
def each_row
|
86
|
+
return enum_for(:each_row) unless block_given?
|
87
|
+
|
86
88
|
size.times do |i|
|
87
89
|
yield @vectors.map { |k, v| [k, v[i]] }.to_h
|
88
90
|
end
|
@@ -161,7 +163,7 @@ module Rover
|
|
161
163
|
last(n)
|
162
164
|
end
|
163
165
|
|
164
|
-
def first(n =
|
166
|
+
def first(n = 1)
|
165
167
|
new_vectors = {}
|
166
168
|
@vectors.each do |k, v|
|
167
169
|
new_vectors[k] = v.first(n)
|
@@ -169,7 +171,7 @@ module Rover
|
|
169
171
|
DataFrame.new(new_vectors)
|
170
172
|
end
|
171
173
|
|
172
|
-
def last(n =
|
174
|
+
def last(n = 1)
|
173
175
|
new_vectors = {}
|
174
176
|
@vectors.each do |k, v|
|
175
177
|
new_vectors[k] = v.last(n)
|
@@ -236,7 +238,12 @@ module Rover
|
|
236
238
|
# for IRuby
|
237
239
|
def to_html
|
238
240
|
require "iruby"
|
239
|
-
|
241
|
+
if size > 7
|
242
|
+
# pass 8 rows so maxrows is applied
|
243
|
+
IRuby::HTML.table((self[0..4] + self[-4..-1]).to_h, maxrows: 7)
|
244
|
+
else
|
245
|
+
IRuby::HTML.table(to_h)
|
246
|
+
end
|
240
247
|
end
|
241
248
|
|
242
249
|
# TODO handle long text better
|
@@ -247,18 +254,19 @@ module Rover
|
|
247
254
|
line_start = 0
|
248
255
|
spaces = 2
|
249
256
|
|
257
|
+
summarize = size >= 30
|
258
|
+
|
250
259
|
@vectors.each do |k, v|
|
251
|
-
v = v.first(5).to_a
|
260
|
+
v = summarize ? v.first(5).to_a + ["..."] + v.last(5).to_a : v.to_a
|
252
261
|
width = ([k] + v).map(&:to_s).map(&:size).max
|
253
262
|
width = 3 if width < 3
|
254
263
|
|
255
264
|
if lines.empty? || lines[-2].map { |l| l.size + spaces }.sum + width > 120
|
256
265
|
line_start = lines.size
|
257
266
|
lines << []
|
258
|
-
|
267
|
+
v.size.times do |i|
|
259
268
|
lines << []
|
260
269
|
end
|
261
|
-
lines << [] if size > 5
|
262
270
|
lines << []
|
263
271
|
end
|
264
272
|
|
@@ -266,7 +274,6 @@ module Rover
|
|
266
274
|
v.each_with_index do |v2, i|
|
267
275
|
lines[line_start + 1 + i] << "%#{width}s" % v2.to_s
|
268
276
|
end
|
269
|
-
lines[line_start + 6] << "%#{width}s" % "..." if size > 5
|
270
277
|
end
|
271
278
|
|
272
279
|
lines.pop
|
@@ -290,11 +297,11 @@ module Rover
|
|
290
297
|
dup.sort_by!(&block)
|
291
298
|
end
|
292
299
|
|
293
|
-
def group(columns)
|
294
|
-
Group.new(self, columns)
|
300
|
+
def group(*columns)
|
301
|
+
Group.new(self, columns.flatten)
|
295
302
|
end
|
296
303
|
|
297
|
-
[:max, :min, :median, :mean, :percentile, :sum].each do |name|
|
304
|
+
[:max, :min, :median, :mean, :percentile, :sum, :std, :var].each do |name|
|
298
305
|
define_method(name) do |column, *args|
|
299
306
|
check_column(column)
|
300
307
|
self[column].send(name, *args)
|
@@ -353,7 +360,89 @@ module Rover
|
|
353
360
|
def ==(other)
|
354
361
|
size == other.size &&
|
355
362
|
keys == other.keys &&
|
356
|
-
keys.all? { |k| self[k] == other[k] }
|
363
|
+
keys.all? { |k| self[k].to_numo == other[k].to_numo }
|
364
|
+
end
|
365
|
+
|
366
|
+
def plot(x = nil, y = nil, type: nil)
|
367
|
+
require "vega"
|
368
|
+
|
369
|
+
raise ArgumentError, "Must specify columns" if keys.size != 2 && (!x || !y)
|
370
|
+
x ||= keys[0]
|
371
|
+
y ||= keys[1]
|
372
|
+
type ||= begin
|
373
|
+
if self[x].numeric? && self[y].numeric?
|
374
|
+
"scatter"
|
375
|
+
elsif types[x] == :object && self[y].numeric?
|
376
|
+
"column"
|
377
|
+
else
|
378
|
+
raise "Cannot determine type. Use the type option."
|
379
|
+
end
|
380
|
+
end
|
381
|
+
data = self[[x, y]]
|
382
|
+
|
383
|
+
case type
|
384
|
+
when "line", "area"
|
385
|
+
x_type =
|
386
|
+
if data[x].numeric?
|
387
|
+
"quantitative"
|
388
|
+
elsif data[x].all? { |v| v.is_a?(Date) || v.is_a?(Time) }
|
389
|
+
"temporal"
|
390
|
+
else
|
391
|
+
"nominal"
|
392
|
+
end
|
393
|
+
|
394
|
+
scale = x_type == "temporal" ? {type: "utc"} : {}
|
395
|
+
|
396
|
+
Vega.lite
|
397
|
+
.data(data)
|
398
|
+
.mark(type: type, tooltip: true, interpolate: "cardinal", point: {size: 60})
|
399
|
+
.encoding(
|
400
|
+
x: {field: x, type: x_type, scale: scale},
|
401
|
+
y: {field: y, type: "quantitative"}
|
402
|
+
)
|
403
|
+
.config(axis: {labelFontSize: 12})
|
404
|
+
when "pie"
|
405
|
+
Vega.lite
|
406
|
+
.data(data)
|
407
|
+
.mark(type: "arc", tooltip: true)
|
408
|
+
.encoding(
|
409
|
+
color: {field: x, type: "nominal", sort: "none", axis: {title: nil}, legend: {labelFontSize: 12}},
|
410
|
+
theta: {field: y, type: "quantitative"}
|
411
|
+
)
|
412
|
+
.view(stroke: nil)
|
413
|
+
when "column"
|
414
|
+
Vega.lite
|
415
|
+
.data(data)
|
416
|
+
.mark(type: "bar", tooltip: true)
|
417
|
+
.encoding(
|
418
|
+
# TODO determine label angle
|
419
|
+
x: {field: x, type: "nominal", sort: "none", axis: {labelAngle: 0}},
|
420
|
+
y: {field: y, type: "quantitative"}
|
421
|
+
)
|
422
|
+
.config(axis: {labelFontSize: 12})
|
423
|
+
when "bar"
|
424
|
+
Vega.lite
|
425
|
+
.data(data)
|
426
|
+
.mark(type: "bar", tooltip: true)
|
427
|
+
.encoding(
|
428
|
+
# TODO determine label angle
|
429
|
+
y: {field: x, type: "nominal", sort: "none", axis: {labelAngle: 0}},
|
430
|
+
x: {field: y, type: "quantitative"}
|
431
|
+
)
|
432
|
+
.config(axis: {labelFontSize: 12})
|
433
|
+
when "scatter"
|
434
|
+
Vega.lite
|
435
|
+
.data(data)
|
436
|
+
.mark(type: "circle", tooltip: true)
|
437
|
+
.encoding(
|
438
|
+
x: {field: x, type: "quantitative", scale: {zero: false}},
|
439
|
+
y: {field: y, type: "quantitative", scale: {zero: false}},
|
440
|
+
size: {value: 60}
|
441
|
+
)
|
442
|
+
.config(axis: {labelFontSize: 12})
|
443
|
+
else
|
444
|
+
raise ArgumentError, "Invalid type: #{type}"
|
445
|
+
end
|
357
446
|
end
|
358
447
|
|
359
448
|
private
|
@@ -418,8 +507,20 @@ module Rover
|
|
418
507
|
raise ArgumentError, "Missing keys: #{missing_keys.join(", ")}" if missing_keys.any?
|
419
508
|
end
|
420
509
|
|
421
|
-
|
422
|
-
|
510
|
+
# TODO in 0.3.0
|
511
|
+
# always use did_you_mean
|
512
|
+
def check_column(key, did_you_mean = false)
|
513
|
+
unless include?(key)
|
514
|
+
if did_you_mean
|
515
|
+
if RUBY_VERSION.to_f >= 2.6
|
516
|
+
raise KeyError.new("Missing column: #{key}", receiver: self, key: key)
|
517
|
+
else
|
518
|
+
raise KeyError.new("Missing column: #{key}")
|
519
|
+
end
|
520
|
+
else
|
521
|
+
raise ArgumentError, "Missing column: #{key}"
|
522
|
+
end
|
523
|
+
end
|
423
524
|
end
|
424
525
|
|
425
526
|
def to_vector(v, size: nil, type: nil)
|
data/lib/rover/group.rb
CHANGED
@@ -2,16 +2,23 @@ module Rover
|
|
2
2
|
class Group
|
3
3
|
def initialize(df, columns)
|
4
4
|
@df = df
|
5
|
-
@columns =
|
5
|
+
@columns = columns
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
def group(*columns)
|
9
|
+
Group.new(@df, @columns + columns.flatten)
|
10
|
+
end
|
11
|
+
|
12
|
+
[:count, :max, :min, :mean, :median, :percentile, :sum, :std, :var].each do |name|
|
9
13
|
define_method(name) do |*args|
|
10
|
-
|
14
|
+
n = [name, args.first].compact.join("_")
|
15
|
+
|
16
|
+
rows = []
|
11
17
|
grouped_dfs.each do |k, df|
|
12
|
-
|
18
|
+
rows << k.merge(n => df.send(name, *args))
|
13
19
|
end
|
14
|
-
|
20
|
+
|
21
|
+
DataFrame.new(rows)
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
@@ -26,21 +33,15 @@ module Rover
|
|
26
33
|
raise ArgumentError, "Missing keys: #{missing_keys.join(", ")}" if missing_keys.any?
|
27
34
|
|
28
35
|
groups = Hash.new { |hash, key| hash[key] = [] }
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
else
|
34
|
-
i = 0
|
35
|
-
@df.each_row do |row|
|
36
|
-
groups[@columns.map { |c| row[c] }] << i
|
37
|
-
i += 1
|
38
|
-
end
|
36
|
+
i = 0
|
37
|
+
@df.each_row do |row|
|
38
|
+
groups[row.slice(*@columns)] << i
|
39
|
+
i += 1
|
39
40
|
end
|
40
41
|
|
41
42
|
result = {}
|
42
|
-
groups.each do |k
|
43
|
-
result[k] = @df[
|
43
|
+
groups.keys.each do |k|
|
44
|
+
result[k] = @df[groups[k]]
|
44
45
|
end
|
45
46
|
result
|
46
47
|
end
|
data/lib/rover/vector.rb
CHANGED
@@ -44,6 +44,10 @@ module Rover
|
|
44
44
|
a
|
45
45
|
end
|
46
46
|
|
47
|
+
def numeric?
|
48
|
+
![:object, :bool].include?(type)
|
49
|
+
end
|
50
|
+
|
47
51
|
def size
|
48
52
|
@data.size
|
49
53
|
end
|
@@ -51,7 +55,7 @@ module Rover
|
|
51
55
|
alias_method :count, :size
|
52
56
|
|
53
57
|
def uniq
|
54
|
-
Vector.new(
|
58
|
+
Vector.new(to_a.uniq)
|
55
59
|
end
|
56
60
|
|
57
61
|
def missing
|
@@ -87,11 +91,11 @@ module Rover
|
|
87
91
|
@data[k] = v
|
88
92
|
end
|
89
93
|
|
90
|
-
%w(+ - * / % ** &).each do |op|
|
94
|
+
%w(+ - * / % ** & | ^).each do |op|
|
91
95
|
define_method(op) do |other|
|
92
96
|
other = other.to_numo if other.is_a?(Vector)
|
93
97
|
# TODO better logic
|
94
|
-
if @data.is_a?(Numo::RObject)
|
98
|
+
if @data.is_a?(Numo::RObject) && !other.is_a?(Numo::RObject)
|
95
99
|
map { |v| v.send(op, other) }
|
96
100
|
else
|
97
101
|
Vector.new(@data.send(op, other))
|
@@ -157,9 +161,22 @@ module Rover
|
|
157
161
|
end
|
158
162
|
|
159
163
|
def map(&block)
|
160
|
-
|
161
|
-
|
162
|
-
Vector.new(
|
164
|
+
# convert to Ruby first to cast properly
|
165
|
+
# https://github.com/ruby-numo/numo-narray/issues/181
|
166
|
+
Vector.new(@data.to_a.map(&block))
|
167
|
+
end
|
168
|
+
|
169
|
+
def map!(&block)
|
170
|
+
@data = cast_data(@data.to_a.map(&block))
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
def select(&block)
|
175
|
+
Vector.new(@data.to_a.select(&block))
|
176
|
+
end
|
177
|
+
|
178
|
+
def reject(&block)
|
179
|
+
Vector.new(@data.to_a.reject(&block))
|
163
180
|
end
|
164
181
|
|
165
182
|
def tally
|
@@ -226,11 +243,15 @@ module Rover
|
|
226
243
|
end
|
227
244
|
|
228
245
|
def all?(&block)
|
229
|
-
|
246
|
+
to_a.all?(&block)
|
230
247
|
end
|
231
248
|
|
232
249
|
def any?(&block)
|
233
|
-
|
250
|
+
to_a.any?(&block)
|
251
|
+
end
|
252
|
+
|
253
|
+
def zip(other, &block)
|
254
|
+
to_a.zip(other.to_a, &block)
|
234
255
|
end
|
235
256
|
|
236
257
|
def first(n = 1)
|
@@ -242,7 +263,11 @@ module Rover
|
|
242
263
|
end
|
243
264
|
|
244
265
|
def last(n = 1)
|
245
|
-
|
266
|
+
if n >= size
|
267
|
+
Vector.new(@data)
|
268
|
+
else
|
269
|
+
Vector.new(@data[-n..-1])
|
270
|
+
end
|
246
271
|
end
|
247
272
|
|
248
273
|
def take(n)
|
@@ -298,7 +323,12 @@ module Rover
|
|
298
323
|
# for IRuby
|
299
324
|
def to_html
|
300
325
|
require "iruby"
|
301
|
-
|
326
|
+
if size > 7
|
327
|
+
# pass 8 rows so maxrows is applied
|
328
|
+
IRuby::HTML.table(first(4).to_a + last(4).to_a, maxrows: 7)
|
329
|
+
else
|
330
|
+
IRuby::HTML.table(to_a)
|
331
|
+
end
|
302
332
|
end
|
303
333
|
|
304
334
|
private
|
data/lib/rover/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.4
|
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:
|
11
|
+
date: 2021-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: numo-narray
|
@@ -16,100 +16,16 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.9.1.
|
19
|
+
version: 0.9.1.9
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.9.1.
|
27
|
-
|
28
|
-
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: minitest
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '5'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '5'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: activerecord
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '5'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '5'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: sqlite3
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: iruby
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
description:
|
112
|
-
email: andrew@chartkick.com
|
26
|
+
version: 0.9.1.9
|
27
|
+
description:
|
28
|
+
email: andrew@ankane.org
|
113
29
|
executables: []
|
114
30
|
extensions: []
|
115
31
|
extra_rdoc_files: []
|
@@ -127,7 +43,7 @@ homepage: https://github.com/ankane/rover
|
|
127
43
|
licenses:
|
128
44
|
- MIT
|
129
45
|
metadata: {}
|
130
|
-
post_install_message:
|
46
|
+
post_install_message:
|
131
47
|
rdoc_options: []
|
132
48
|
require_paths:
|
133
49
|
- lib
|
@@ -142,8 +58,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
58
|
- !ruby/object:Gem::Version
|
143
59
|
version: '0'
|
144
60
|
requirements: []
|
145
|
-
rubygems_version: 3.
|
146
|
-
signing_key:
|
61
|
+
rubygems_version: 3.2.3
|
62
|
+
signing_key:
|
147
63
|
specification_version: 4
|
148
64
|
summary: Simple, powerful data frames for Ruby
|
149
65
|
test_files: []
|