goldmine 1.2.1 → 2.0.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +34 -46
- data/lib/goldmine.rb +1 -0
- data/lib/goldmine/array_miner.rb +2 -5
- data/lib/goldmine/hash_miner.rb +7 -63
- data/lib/goldmine/hash_rollup.rb +65 -0
- data/lib/goldmine/version.rb +1 -1
- data/test/test_goldmine.rb +69 -54
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98cf471fea798a03ff6b2d00fd66f46a8e7314bc
|
4
|
+
data.tar.gz: 9f3504f492b1fe77c6e6a6be0c25ca8c15320a1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d8eb6c77e8a16834ad6c045040abb56d77fbd0b4fff6c5921cb96b17875de0152deaf874b85269836f7e18f6c194783a865d9dc4fb75c2eb65ed977e62a09c6
|
7
|
+
data.tar.gz: 869e2679c6f914fba82726834056420f00f7aee3597d514623b15d233b826936d29600729609e2e3ff6ad07d042f84cab0a5e8195f5b4a4b1e004c0fcc2f863c
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
|
2
2
|
[](https://codeclimate.com/github/hopsoft/goldmine)
|
3
3
|
[](https://gemnasium.com/hopsoft/goldmine)
|
4
4
|
[](https://travis-ci.org/hopsoft/goldmine)
|
@@ -14,14 +14,14 @@ Think of __Goldmine__ as `Enumerable#group_by` on steroids.
|
|
14
14
|
|
15
15
|
- Data mining
|
16
16
|
- Data transformation
|
17
|
+
- Data blending
|
18
|
+
- Data visualization prep
|
17
19
|
- CSV report generation
|
18
|
-
- Prep for data visualization
|
19
|
-
- Fact table creation
|
20
20
|
|
21
21
|
---
|
22
22
|
|
23
23
|
The [demo project](http://hopsoft.github.io/goldmine/) demonstrates some of Goldmine's uses.
|
24
|
-
`TODO: update the demo project`
|
24
|
+
`TODO: update the demo project to use the latest features`
|
25
25
|
|
26
26
|
---
|
27
27
|
|
@@ -143,64 +143,52 @@ end
|
|
143
143
|
}
|
144
144
|
```
|
145
145
|
|
146
|
-
## Rollups
|
146
|
+
## Rollups, Tabular, & CSV
|
147
147
|
|
148
|
-
|
148
|
+
Rollups provide a clean way to aggregate pivoted data.
|
149
|
+
|
150
|
+
_NOTE: Rollups can also be chained._
|
149
151
|
|
150
152
|
```ruby
|
151
153
|
list = [1,2,3,4,5,6,7,8,9]
|
152
154
|
list = Goldmine::ArrayMiner.new(list)
|
153
|
-
pivoted = list
|
154
|
-
|
155
|
+
pivoted = list
|
156
|
+
.pivot(:less_than_5) { |i| i < 5 }
|
157
|
+
.pivot(:even) { |i| i % 2 == 0 }
|
155
158
|
# result:
|
156
159
|
{
|
157
|
-
{ :less_than_5 => true, :even => false} =>
|
158
|
-
{ :less_than_5 => true, :even => true} => 2,
|
159
|
-
{ :less_than_5 => false, :even => false} =>
|
160
|
-
{ :less_than_5 => false, :even => true} =>
|
160
|
+
{ :less_than_5 => true, :even => false } => [1, 3],
|
161
|
+
{ :less_than_5 => true, :even => true } => [2, 4],
|
162
|
+
{ :less_than_5 => false, :even => false} => [5, 7, 9],
|
163
|
+
{ :less_than_5 => false, :even => true } => [6, 8]
|
161
164
|
}
|
162
|
-
```
|
163
|
-
|
164
|
-
## Tabular data
|
165
165
|
|
166
|
-
|
166
|
+
rollup = pivoted.rollup(:count) { |matched| matched.size }
|
167
|
+
# result:
|
168
|
+
{
|
169
|
+
{:less_than_5=>true, :even=>false}=>{:count=>2},
|
170
|
+
{:less_than_5=>true, :even=>true}=>{:count=>2},
|
171
|
+
{:less_than_5=>false, :even=>false}=>{:count=>3},
|
172
|
+
{:less_than_5=>false, :even=>true}=>{:count=>2}
|
173
|
+
}
|
167
174
|
|
168
|
-
|
169
|
-
list = [1,2,3,4,5,6,7,8,9]
|
170
|
-
list = Goldmine::ArrayMiner.new(list)
|
171
|
-
pivoted = list.pivot(:less_than_5) { |i| i < 5 }.pivot(:even) { |i| i % 2 == 0 }
|
172
|
-
pivoted.to_tabular
|
175
|
+
rollup.to_tabular
|
173
176
|
# result:
|
174
177
|
[
|
175
|
-
["less_than_5", "even", "
|
176
|
-
[true, false,
|
177
|
-
[true, true,
|
178
|
-
[false, false,
|
179
|
-
[false, true,
|
178
|
+
["less_than_5", "even", "count"],
|
179
|
+
[true, false, 2],
|
180
|
+
[true, true, 2],
|
181
|
+
[false, false, 3],
|
182
|
+
[false, true, 2]
|
180
183
|
]
|
181
|
-
```
|
182
184
|
|
183
|
-
|
184
|
-
|
185
|
-
CSV
|
186
|
-
They simplify the complexity of working with tabular data.
|
187
|
-
|
188
|
-
```ruby
|
189
|
-
list = [1,2,3,4,5,6,7,8,9]
|
190
|
-
list = Goldmine::ArrayMiner.new(list)
|
191
|
-
pivoted = list.pivot(:less_than_5) { |i| i < 5 }.pivot(:even) { |i| i % 2 == 0 }
|
192
|
-
csv = pivoted.to_csv
|
193
|
-
|
194
|
-
csv.headers # => ["less_than_5", "even", "percent", "count"]
|
195
|
-
|
196
|
-
csv.each do |row|
|
197
|
-
puts row["less_than_5"]
|
198
|
-
puts row["even"]
|
199
|
-
end
|
185
|
+
rollup.to_csv_table
|
186
|
+
# result:
|
187
|
+
#<CSV::Table mode:col_or_row row_count:5>
|
200
188
|
|
201
|
-
|
189
|
+
rollup.to_csv_table.to_csv
|
202
190
|
# result:
|
203
|
-
"less_than_5,even,
|
191
|
+
"less_than_5,even,count\ntrue,false,2\ntrue,true,2\nfalse,false,3\nfalse,true,2\n"
|
204
192
|
```
|
205
193
|
|
206
194
|
## Summary
|
data/lib/goldmine.rb
CHANGED
data/lib/goldmine/array_miner.rb
CHANGED
@@ -2,10 +2,7 @@ require "delegate"
|
|
2
2
|
|
3
3
|
module Goldmine
|
4
4
|
class ArrayMiner < SimpleDelegator
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(array=[], source_data: [])
|
8
|
-
@source_data = source_data
|
5
|
+
def initialize(array=[])
|
9
6
|
super array
|
10
7
|
end
|
11
8
|
|
@@ -48,7 +45,7 @@ module Goldmine
|
|
48
45
|
# @yield [Object] Yields once for each item in the Array
|
49
46
|
# @return [Hash] The pivoted Hash of data.
|
50
47
|
def pivot(name=nil, &block)
|
51
|
-
reduce(HashMiner.new
|
48
|
+
reduce(HashMiner.new) do |memo, item|
|
52
49
|
value = yield(item)
|
53
50
|
|
54
51
|
if value.is_a?(Array)
|
data/lib/goldmine/hash_miner.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
require "delegate"
|
2
|
-
require "csv"
|
3
2
|
|
4
3
|
module Goldmine
|
5
4
|
class HashMiner < SimpleDelegator
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(hash={}, source_data: [])
|
9
|
-
@source_data = source_data
|
10
|
-
super hash
|
5
|
+
def initialize(hash={})
|
6
|
+
super @hash = hash
|
11
7
|
end
|
12
8
|
|
13
9
|
attr_accessor :goldmine
|
@@ -35,7 +31,7 @@ module Goldmine
|
|
35
31
|
def pivot(name=nil, &block)
|
36
32
|
return self unless goldmine
|
37
33
|
|
38
|
-
reduce(HashMiner.new
|
34
|
+
reduce(HashMiner.new) do |memo, item|
|
39
35
|
key = item.first
|
40
36
|
value = Goldmine.miner(item.last)
|
41
37
|
value.pivot(name, &block).each do |k, v|
|
@@ -52,45 +48,12 @@ module Goldmine
|
|
52
48
|
end
|
53
49
|
end
|
54
50
|
|
55
|
-
# Returns a
|
51
|
+
# Returns a HashRollup with summarized data.
|
56
52
|
#
|
57
|
-
# @yield [Object] Yields once for each pivoted
|
53
|
+
# @yield [Object] Yields once for each pivoted grouping of values.
|
58
54
|
# @return [Hash] The rollup Hash of data.
|
59
|
-
def rollup
|
60
|
-
|
61
|
-
memo[pair.first] = yield(pair.last)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Returns a tabular representation of the pivot.
|
66
|
-
# Useful for building CSVs & data visualizations.
|
67
|
-
#
|
68
|
-
# @param percent_column_name [String] The name of the percent column (percent of total)
|
69
|
-
# @param count_column_name [String] The name of the count column (number of objects)
|
70
|
-
# @return [Array] The tabular representation of the data.
|
71
|
-
def to_tabular(percent_column_name: "percent", count_column_name: "count")
|
72
|
-
[].tap do |rows|
|
73
|
-
rows << tabular_header_from_key(first.first) + [percent_column_name, count_column_name]
|
74
|
-
rolled = rollup { |row| row.size }
|
75
|
-
rolled.each do |key, value|
|
76
|
-
tabular_row_from_key(key).tap do |row|
|
77
|
-
rows << row + [calculate_percentage(value, source_data.size), value]
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Returns an in memory CSV table representation of the pivot.
|
84
|
-
# Useful for working with data & building data visualizations.
|
85
|
-
#
|
86
|
-
# @param percent_column_name [String] The name of the percent column (percent of total)
|
87
|
-
# @param count_column_name [String] The name of the count column (number of objects)
|
88
|
-
# @return [CSV::Table] The CSV representation of the data.
|
89
|
-
def to_csv(percent_column_name: "percent", count_column_name: "count")
|
90
|
-
tabular = to_tabular(percent_column_name: percent_column_name, count_column_name: count_column_name)
|
91
|
-
header = tabular.shift
|
92
|
-
rows = tabular.map { |row| CSV::Row.new(header, row) }
|
93
|
-
CSV::Table.new rows
|
55
|
+
def rollup(name, &block)
|
56
|
+
HashRollup.new(@hash).rollup(name, &block)
|
94
57
|
end
|
95
58
|
|
96
59
|
# Assigns a key/value pair to the Hash.
|
@@ -113,24 +76,5 @@ module Goldmine
|
|
113
76
|
goldmine_key ||= key
|
114
77
|
end
|
115
78
|
|
116
|
-
private
|
117
|
-
|
118
|
-
def calculate_percentage(count, total)
|
119
|
-
return 0.0 unless total > 0
|
120
|
-
sprintf("%.2f", count / total.to_f).to_f
|
121
|
-
end
|
122
|
-
|
123
|
-
def tabular_header_from_key(key)
|
124
|
-
return key.keys.map(&:to_s) if key.is_a?(Hash)
|
125
|
-
key = [key] unless key.is_a?(Array)
|
126
|
-
(0..key.size-1).map { |i| "column#{i}" }
|
127
|
-
end
|
128
|
-
|
129
|
-
def tabular_row_from_key(key)
|
130
|
-
return key.dup if key.is_a?(Array)
|
131
|
-
return [key] unless key.is_a?(Hash)
|
132
|
-
key.values.dup
|
133
|
-
end
|
134
|
-
|
135
79
|
end
|
136
80
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "delegate"
|
2
|
+
require "csv"
|
3
|
+
|
4
|
+
module Goldmine
|
5
|
+
class HashRollup < SimpleDelegator
|
6
|
+
def initialize(pivoted)
|
7
|
+
@pivoted = pivoted
|
8
|
+
super @rolled = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def rollup(name)
|
12
|
+
pivoted.each do |key, value|
|
13
|
+
rolled[key] ||= {}
|
14
|
+
rolled[key][name] = yield(value)
|
15
|
+
end
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_tabular
|
20
|
+
[].tap do |rows|
|
21
|
+
rows << tabular_header
|
22
|
+
rows.concat tabular_rows
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_csv_table
|
27
|
+
header = tabular_header
|
28
|
+
rows = tabular_rows.map { |row| CSV::Row.new(header, row) }
|
29
|
+
CSV::Table.new rows
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :pivoted, :rolled
|
35
|
+
|
36
|
+
def tabular_header
|
37
|
+
return [] if empty?
|
38
|
+
to_tabular_header keys.first, values.first
|
39
|
+
end
|
40
|
+
|
41
|
+
def tabular_rows
|
42
|
+
map do |pair|
|
43
|
+
to_tabular_row pair.first, pair.last
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_tabular_row(key, value)
|
48
|
+
row = key.values.dup if key.is_a?(Hash)
|
49
|
+
row ||= as_array(key).dup
|
50
|
+
row.concat value.values
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_tabular_header(key, value)
|
54
|
+
header = key.keys.map(&:to_s) if key.is_a?(Hash)
|
55
|
+
header ||= (1..as_array(key).size).map { |i| "column#{i}" }
|
56
|
+
header.concat value.keys.map(&:to_s)
|
57
|
+
end
|
58
|
+
|
59
|
+
def as_array(value)
|
60
|
+
return value if value.is_a?(Array)
|
61
|
+
[value]
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
data/lib/goldmine/version.rb
CHANGED
data/test/test_goldmine.rb
CHANGED
@@ -34,38 +34,54 @@ class TestGoldmine < PryTest::Test
|
|
34
34
|
list = [1,2,3,4,5,6,7,8,9]
|
35
35
|
list = Goldmine::ArrayMiner.new(list)
|
36
36
|
data = list.pivot { |i| i < 5 }
|
37
|
-
rolled = data.rollup { |
|
37
|
+
rolled = data.rollup(:count) { |items| items.size }
|
38
38
|
|
39
39
|
expected = {
|
40
|
-
true => 4,
|
41
|
-
false => 5
|
40
|
+
true => { count: 4 },
|
41
|
+
false => { count: 5 }
|
42
42
|
}
|
43
43
|
|
44
44
|
assert rolled == expected
|
45
45
|
end
|
46
46
|
|
47
|
-
test "
|
47
|
+
test "pivot with chained rollup" do
|
48
48
|
list = [1,2,3,4,5,6,7,8,9]
|
49
49
|
list = Goldmine::ArrayMiner.new(list)
|
50
50
|
data = list.pivot { |i| i < 5 }
|
51
|
+
rolled = data
|
52
|
+
.rollup(:count) { |items| items.size }
|
53
|
+
.rollup(:div_by_3) { |items| items.keep_if { |i| i % 3 == 0 }.size }
|
54
|
+
|
55
|
+
expected = {
|
56
|
+
true => {:count=>4, :div_by_3=>1},
|
57
|
+
false => {:count=>5, :div_by_3=>2}
|
58
|
+
}
|
59
|
+
|
60
|
+
assert rolled == expected
|
61
|
+
end
|
62
|
+
|
63
|
+
test "simple pivot rollup to_tabular" do
|
64
|
+
list = [1,2,3,4,5,6,7,8,9]
|
65
|
+
list = Goldmine::ArrayMiner.new(list)
|
66
|
+
rolled = list.pivot { |i| i < 5 }.rollup(:count, &:size)
|
51
67
|
|
52
68
|
expected = [
|
53
|
-
["
|
54
|
-
[true,
|
55
|
-
[false,
|
69
|
+
["column1", "count"],
|
70
|
+
[true, 4],
|
71
|
+
[false, 5]
|
56
72
|
]
|
57
73
|
|
58
|
-
assert
|
74
|
+
assert rolled.to_tabular == expected
|
59
75
|
end
|
60
76
|
|
61
|
-
test "simple pivot
|
77
|
+
test "simple pivot rollup to_csv_table" do
|
62
78
|
list = [1,2,3,4,5,6,7,8,9]
|
63
79
|
list = Goldmine::ArrayMiner.new(list)
|
64
|
-
|
65
|
-
csv =
|
80
|
+
rolled = list.pivot { |i| i < 5 }.rollup(:count, &:size)
|
81
|
+
csv = rolled.to_csv_table
|
66
82
|
|
67
|
-
assert csv.headers == ["
|
68
|
-
assert csv.to_a == [["
|
83
|
+
assert csv.headers == ["column1", "count"]
|
84
|
+
assert csv.to_a == [["column1", "count"], [true, 4], [false, 5]]
|
69
85
|
end
|
70
86
|
|
71
87
|
test "named pivot" do
|
@@ -85,28 +101,28 @@ class TestGoldmine < PryTest::Test
|
|
85
101
|
list = [1,2,3,4,5,6,7,8,9]
|
86
102
|
list = Goldmine::ArrayMiner.new(list)
|
87
103
|
data = list.pivot("less than 5") { |i| i < 5 }
|
88
|
-
rolled = data.rollup { |row| row.size }
|
104
|
+
rolled = data.rollup(:count) { |row| row.size }
|
89
105
|
|
90
106
|
expected = {
|
91
|
-
{ "less than 5" => true } => 4,
|
92
|
-
{ "less than 5" => false } => 5
|
107
|
+
{ "less than 5" => true } => { count: 4 },
|
108
|
+
{ "less than 5" => false } => { count: 5 }
|
93
109
|
}
|
94
110
|
|
95
111
|
assert rolled == expected
|
96
112
|
end
|
97
113
|
|
98
|
-
test "named pivot to_tabular" do
|
114
|
+
test "named pivot rollup to_tabular" do
|
99
115
|
list = [1,2,3,4,5,6,7,8,9]
|
100
116
|
list = Goldmine::ArrayMiner.new(list)
|
101
|
-
|
117
|
+
rolled = list.pivot("less than 5") { |i| i < 5 }.rollup(:count, &:size)
|
102
118
|
|
103
119
|
expected = [
|
104
|
-
["less than 5", "
|
105
|
-
[true,
|
106
|
-
[false,
|
120
|
+
["less than 5", "count"],
|
121
|
+
[true, 4],
|
122
|
+
[false, 5]
|
107
123
|
]
|
108
124
|
|
109
|
-
assert
|
125
|
+
assert rolled.to_tabular == expected
|
110
126
|
end
|
111
127
|
|
112
128
|
test "pivot of list values" do
|
@@ -182,32 +198,32 @@ class TestGoldmine < PryTest::Test
|
|
182
198
|
list = [1,2,3,4,5,6,7,8,9]
|
183
199
|
list = Goldmine::ArrayMiner.new(list)
|
184
200
|
data = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }
|
185
|
-
rolled = data.rollup { |row| row.size }
|
201
|
+
rolled = data.rollup(:count) { |row| row.size }
|
186
202
|
|
187
203
|
expected = {
|
188
|
-
[true, false] => 2,
|
189
|
-
[true, true] => 2,
|
190
|
-
[false, false] => 3,
|
191
|
-
[false, true] => 2
|
204
|
+
[true, false] => { count: 2 },
|
205
|
+
[true, true] => { count: 2 },
|
206
|
+
[false, false] => { count: 3 },
|
207
|
+
[false, true] => { count: 2 }
|
192
208
|
}
|
193
209
|
|
194
210
|
assert rolled == expected
|
195
211
|
end
|
196
212
|
|
197
|
-
test "chained pivots to_tabular" do
|
213
|
+
test "chained pivots rollup to_tabular" do
|
198
214
|
list = [1,2,3,4,5,6,7,8,9]
|
199
215
|
list = Goldmine::ArrayMiner.new(list)
|
200
|
-
|
216
|
+
rolled = list.pivot { |i| i < 5 }.pivot { |i| i % 2 == 0 }.rollup(:count, &:size)
|
201
217
|
|
202
218
|
expected = [
|
203
|
-
["
|
204
|
-
[true, false,
|
205
|
-
[true, true,
|
206
|
-
[false, false,
|
207
|
-
[false, true,
|
219
|
+
["column1", "column2", "count"],
|
220
|
+
[true, false, 2],
|
221
|
+
[true, true, 2],
|
222
|
+
[false, false, 3],
|
223
|
+
[false, true, 2]
|
208
224
|
]
|
209
225
|
|
210
|
-
assert
|
226
|
+
assert rolled.to_tabular == expected
|
211
227
|
end
|
212
228
|
|
213
229
|
test "deep chained pivots" do
|
@@ -274,49 +290,48 @@ class TestGoldmine < PryTest::Test
|
|
274
290
|
list = [1,2,3,4,5,6,7,8,9]
|
275
291
|
list = Goldmine::ArrayMiner.new(list)
|
276
292
|
data = list.pivot("less than 5") { |i| i < 5 }.pivot("divisible by 2") { |i| i % 2 == 0 }
|
277
|
-
rolled = data.rollup { |row| row.size }
|
293
|
+
rolled = data.rollup(:count) { |row| row.size }
|
278
294
|
|
279
295
|
expected = {
|
280
|
-
{ "less than 5" => true, "divisible by 2" => false } => 2,
|
281
|
-
{ "less than 5" => true, "divisible by 2" => true } => 2,
|
282
|
-
{ "less than 5" => false, "divisible by 2" => false } => 3,
|
283
|
-
{ "less than 5" => false, "divisible by 2" => true } => 2
|
296
|
+
{ "less than 5" => true, "divisible by 2" => false } => { count: 2 },
|
297
|
+
{ "less than 5" => true, "divisible by 2" => true } => { count: 2 },
|
298
|
+
{ "less than 5" => false, "divisible by 2" => false } => { count: 3 },
|
299
|
+
{ "less than 5" => false, "divisible by 2" => true } => { count: 2 }
|
284
300
|
}
|
285
301
|
|
286
302
|
assert rolled == expected
|
287
303
|
end
|
288
304
|
|
289
|
-
test "named chained pivots to tabular" do
|
305
|
+
test "named chained pivots rollup to tabular" do
|
290
306
|
list = [1,2,3,4,5,6,7,8,9]
|
291
307
|
list = Goldmine::ArrayMiner.new(list)
|
292
|
-
|
308
|
+
rolled = list.pivot("less than 5") { |i| i < 5 }.pivot("divisible by 2") { |i| i % 2 == 0 }.rollup(:count, &:size)
|
293
309
|
|
294
310
|
expected = [
|
295
|
-
["less than 5", "divisible by 2", "
|
296
|
-
[true, false,
|
297
|
-
[true, true,
|
298
|
-
[false, false,
|
299
|
-
[false, true,
|
311
|
+
["less than 5", "divisible by 2", "count"],
|
312
|
+
[true, false, 2],
|
313
|
+
[true, true, 2],
|
314
|
+
[false, false, 3],
|
315
|
+
[false, true, 2]
|
300
316
|
]
|
301
317
|
|
302
|
-
assert
|
318
|
+
assert rolled.to_tabular == expected
|
303
319
|
end
|
304
320
|
|
305
|
-
test "named chained pivots
|
321
|
+
test "named chained pivots rollup to_csv_table" do
|
306
322
|
list = [1,2,3,4,5,6,7,8,9]
|
307
323
|
list = Goldmine::ArrayMiner.new(list)
|
308
|
-
|
309
|
-
csv =
|
324
|
+
rolled = list.pivot("less than 5") { |i| i < 5 }.pivot("divisible by 2") { |i| i % 2 == 0 }.rollup(:count, &:size)
|
325
|
+
csv = rolled.to_csv_table
|
310
326
|
|
311
|
-
assert csv.to_a ==
|
327
|
+
assert csv.to_a == rolled.to_tabular
|
312
328
|
|
313
|
-
expected = ["less than 5", "divisible by 2", "
|
329
|
+
expected = ["less than 5", "divisible by 2", "count"]
|
314
330
|
assert csv.headers == expected
|
315
331
|
|
316
332
|
row = csv.first
|
317
333
|
assert row["less than 5"] == true
|
318
334
|
assert row["divisible by 2"] == false
|
319
|
-
assert row["percent"] == 0.22
|
320
335
|
assert row ["count"] == 2
|
321
336
|
end
|
322
337
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: goldmine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Hopkins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -67,6 +67,7 @@ files:
|
|
67
67
|
- lib/goldmine.rb
|
68
68
|
- lib/goldmine/array_miner.rb
|
69
69
|
- lib/goldmine/hash_miner.rb
|
70
|
+
- lib/goldmine/hash_rollup.rb
|
70
71
|
- lib/goldmine/version.rb
|
71
72
|
- license.md
|
72
73
|
- test/test_goldmine.rb
|