daru 0.1.3.1 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -1
- data/.rspec_formatter.rb +33 -0
- data/.rubocop.yml +26 -2
- data/History.md +38 -0
- data/README.md +22 -13
- data/Rakefile +50 -2
- data/benchmarks/csv_reading.rb +22 -0
- data/daru.gemspec +9 -2
- data/lib/daru.rb +36 -4
- data/lib/daru/accessors/array_wrapper.rb +6 -1
- data/lib/daru/accessors/dataframe_by_row.rb +10 -2
- data/lib/daru/accessors/gsl_wrapper.rb +1 -3
- data/lib/daru/accessors/nmatrix_wrapper.rb +9 -0
- data/lib/daru/category.rb +935 -0
- data/lib/daru/core/group_by.rb +29 -38
- data/lib/daru/core/merge.rb +186 -145
- data/lib/daru/core/query.rb +22 -11
- data/lib/daru/dataframe.rb +976 -885
- data/lib/daru/date_time/index.rb +166 -166
- data/lib/daru/date_time/offsets.rb +66 -77
- data/lib/daru/formatters/table.rb +54 -0
- data/lib/daru/helpers/array.rb +40 -0
- data/lib/daru/index.rb +476 -73
- data/lib/daru/io/io.rb +66 -45
- data/lib/daru/io/sql_data_source.rb +33 -62
- data/lib/daru/iruby/helpers.rb +38 -0
- data/lib/daru/iruby/templates/dataframe.html.erb +52 -0
- data/lib/daru/iruby/templates/dataframe_mi.html.erb +58 -0
- data/lib/daru/iruby/templates/multi_index.html.erb +12 -0
- data/lib/daru/iruby/templates/vector.html.erb +27 -0
- data/lib/daru/iruby/templates/vector_mi.html.erb +36 -0
- data/lib/daru/maths/arithmetic/dataframe.rb +16 -18
- data/lib/daru/maths/arithmetic/vector.rb +4 -6
- data/lib/daru/maths/statistics/dataframe.rb +8 -15
- data/lib/daru/maths/statistics/vector.rb +120 -98
- data/lib/daru/monkeys.rb +12 -40
- data/lib/daru/plotting/gruff.rb +3 -0
- data/lib/daru/plotting/gruff/category.rb +49 -0
- data/lib/daru/plotting/gruff/dataframe.rb +91 -0
- data/lib/daru/plotting/gruff/vector.rb +57 -0
- data/lib/daru/plotting/nyaplot.rb +3 -0
- data/lib/daru/plotting/nyaplot/category.rb +34 -0
- data/lib/daru/plotting/nyaplot/dataframe.rb +187 -0
- data/lib/daru/plotting/nyaplot/vector.rb +46 -0
- data/lib/daru/vector.rb +694 -421
- data/lib/daru/version.rb +1 -1
- data/profile/_base.rb +23 -0
- data/profile/df_to_a.rb +10 -0
- data/profile/filter.rb +13 -0
- data/profile/joining.rb +13 -0
- data/profile/sorting.rb +12 -0
- data/profile/vector_each_with_index.rb +9 -0
- data/spec/accessors/wrappers_spec.rb +2 -4
- data/spec/categorical_spec.rb +1734 -0
- data/spec/core/group_by_spec.rb +52 -2
- data/spec/core/merge_spec.rb +63 -2
- data/spec/core/query_spec.rb +236 -80
- data/spec/dataframe_spec.rb +1373 -79
- data/spec/date_time/data_spec.rb +3 -5
- data/spec/date_time/index_spec.rb +154 -17
- data/spec/date_time/offsets_spec.rb +3 -4
- data/spec/fixtures/empties.dat +2 -0
- data/spec/fixtures/strings.dat +2 -0
- data/spec/formatters/table_formatter_spec.rb +99 -0
- data/spec/helpers_spec.rb +8 -0
- data/spec/index/categorical_index_spec.rb +168 -0
- data/spec/index/index_spec.rb +283 -0
- data/spec/index/multi_index_spec.rb +570 -0
- data/spec/io/io_spec.rb +31 -4
- data/spec/io/sql_data_source_spec.rb +0 -1
- data/spec/iruby/dataframe_spec.rb +172 -0
- data/spec/iruby/helpers_spec.rb +49 -0
- data/spec/iruby/multi_index_spec.rb +37 -0
- data/spec/iruby/vector_spec.rb +107 -0
- data/spec/math/arithmetic/dataframe_spec.rb +71 -13
- data/spec/math/arithmetic/vector_spec.rb +8 -10
- data/spec/math/statistics/dataframe_spec.rb +3 -5
- data/spec/math/statistics/vector_spec.rb +45 -55
- data/spec/monkeys_spec.rb +32 -9
- data/spec/plotting/dataframe_spec.rb +386 -0
- data/spec/plotting/vector_spec.rb +230 -0
- data/spec/shared/vector_display_spec.rb +215 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/vector_spec.rb +905 -138
- metadata +143 -11
- data/.rubocop_todo.yml +0 -44
- data/lib/daru/plotting/dataframe.rb +0 -104
- data/lib/daru/plotting/vector.rb +0 -38
- data/spec/daru_spec.rb +0 -58
- data/spec/index_spec.rb +0 -375
data/spec/io/io_spec.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
1
|
describe Daru::IO do
|
4
2
|
describe Daru::DataFrame do
|
5
3
|
context ".from_csv" do
|
@@ -29,7 +27,7 @@ describe Daru::IO do
|
|
29
27
|
expect(y_ds).to be_within(0.001).of(y_expected)
|
30
28
|
end
|
31
29
|
end
|
32
|
-
|
30
|
+
|
33
31
|
it "follows the order of columns given in CSV" do
|
34
32
|
df = Daru::DataFrame.from_csv 'spec/fixtures/sales-funnel.csv'
|
35
33
|
expect(df.vectors.to_a).to eq(%W[Account Name Rep Manager Product Quantity Price Status])
|
@@ -145,8 +143,23 @@ describe Daru::IO do
|
|
145
143
|
end
|
146
144
|
|
147
145
|
context "#write_sql" do
|
146
|
+
let(:df) { Daru::DataFrame.new({
|
147
|
+
'a' => [1,2,3,4,5],
|
148
|
+
'b' => [11,22,33,44,55],
|
149
|
+
'c' => ['a', 'g', 4, 5,'addadf'],
|
150
|
+
'd' => [nil, 23, 4,'a','ff']})
|
151
|
+
}
|
152
|
+
|
153
|
+
let(:dbh) { double }
|
154
|
+
let(:prepared_query) { double }
|
155
|
+
|
148
156
|
it "writes the DataFrame to an SQL database" do
|
149
|
-
|
157
|
+
expect(dbh).to receive(:prepare)
|
158
|
+
.with('INSERT INTO tbl (a,b,c,d) VALUES (?,?,?,?)')
|
159
|
+
.and_return(prepared_query)
|
160
|
+
df.each_row { |r| expect(prepared_query).to receive(:execute).with(*r.to_a).ordered }
|
161
|
+
|
162
|
+
df.write_sql dbh, 'tbl'
|
150
163
|
end
|
151
164
|
end
|
152
165
|
|
@@ -201,6 +214,20 @@ describe Daru::IO do
|
|
201
214
|
|
202
215
|
expect(df.vectors.to_a).to eq([:v1,:v2,:v3,:v4,:v5,:v6])
|
203
216
|
end
|
217
|
+
|
218
|
+
xit "understands empty fields" do
|
219
|
+
pending 'See FIXME note in io.rb'
|
220
|
+
|
221
|
+
df = Daru::DataFrame.from_plaintext 'spec/fixtures/empties.dat', [:v1,:v2,:v3]
|
222
|
+
|
223
|
+
expect(df.row[1].to_a).to eq [4, nil, 6]
|
224
|
+
end
|
225
|
+
|
226
|
+
it "understands non-numeric fields" do
|
227
|
+
df = Daru::DataFrame.from_plaintext 'spec/fixtures/strings.dat', [:v1,:v2,:v3]
|
228
|
+
|
229
|
+
expect(df[:v1].to_a).to eq ['test', 'foo']
|
230
|
+
end
|
204
231
|
end
|
205
232
|
|
206
233
|
context "JSON" do
|
@@ -0,0 +1,172 @@
|
|
1
|
+
describe Daru::DataFrame, '#to_html' do
|
2
|
+
let(:doc) { Nokogiri::HTML(df.to_html) }
|
3
|
+
subject(:table) { doc.at('table') }
|
4
|
+
let(:header) { table.at('tr:first-child > th:first-child') }
|
5
|
+
let(:name) { 'test' }
|
6
|
+
|
7
|
+
let(:splitted_row) { row.inner_html.scan(/<t[dh].+?<\/t[dh]>/) }
|
8
|
+
|
9
|
+
context 'simple' do
|
10
|
+
let(:df) { Daru::DataFrame.new({a: [1,2,3], b: [3,4,5], c: [6,7,8]}, name: name)}
|
11
|
+
|
12
|
+
describe 'header' do
|
13
|
+
subject { header }
|
14
|
+
|
15
|
+
it { is_expected.not_to be_nil }
|
16
|
+
its(['colspan']) { is_expected.to eq (df.ncols + 1).to_s }
|
17
|
+
its(:text) { is_expected.to eq "Daru::DataFrame: test (3x3)" }
|
18
|
+
|
19
|
+
context 'without name' do
|
20
|
+
let(:name) { nil }
|
21
|
+
|
22
|
+
its(:text) { is_expected.to eq "Daru::DataFrame(3x3)" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'column headers' do
|
27
|
+
subject(:columns) { table.search('tr:nth-child(2) th').map(&:text) }
|
28
|
+
its(:size) { is_expected.to eq df.ncols + 1 }
|
29
|
+
it { is_expected.to eq ['', 'a', 'b', 'c'] }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with multi-index columns' do
|
33
|
+
before { df.vectors = Daru::MultiIndex.from_tuples [[:a, :foo], [:a, :baz], [:b, :foo]] }
|
34
|
+
|
35
|
+
subject { splitted_row }
|
36
|
+
describe 'first row' do
|
37
|
+
let(:row) { table.search('tr:nth-child(2)') }
|
38
|
+
|
39
|
+
it { is_expected.to eq [
|
40
|
+
'<th rowspan="2"></th>',
|
41
|
+
'<th colspan="2">a</th>',
|
42
|
+
'<th colspan="1">b</th>'
|
43
|
+
] }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'next row' do
|
47
|
+
let(:row) { table.search('tr:nth-child(3)') }
|
48
|
+
|
49
|
+
it { is_expected.to eq [
|
50
|
+
'<th colspan="1">foo</th>',
|
51
|
+
'<th colspan="1">baz</th>',
|
52
|
+
'<th colspan="1">foo</th>'
|
53
|
+
] }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'index' do
|
58
|
+
subject(:indexes) { table.search('tr > td:first-child').map(&:text) }
|
59
|
+
its(:count) { is_expected.to eq df.nrows }
|
60
|
+
it { is_expected.to eq df.index.to_a.map(&:to_s) }
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'values' do
|
64
|
+
subject(:values) {
|
65
|
+
table.search('tr')[2..-1]
|
66
|
+
.map { |tr| tr.search('td')[1..-1].map(&:text) }
|
67
|
+
}
|
68
|
+
its(:count) { is_expected.to eq df.nrows }
|
69
|
+
it { is_expected.to eq df.map_rows{|r| r.map(&:to_s)} }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'large dataframe' do
|
74
|
+
let(:df) { Daru::DataFrame.new({a: [1,2,3]*100, b: [3,4,5]*100, c: [6,7,8]*100}, name: 'test') }
|
75
|
+
|
76
|
+
describe 'header' do
|
77
|
+
subject { header }
|
78
|
+
|
79
|
+
its(:text) { is_expected.to eq "Daru::DataFrame: test (300x3)" }
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'has only 30 rows (+ 2 header rows, + 2 finishing rows)' do
|
83
|
+
expect(table.search('tr').size).to eq 34
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '"skipped" row' do
|
87
|
+
subject(:row) { table.search('tr:nth-child(33) td').map(&:text) }
|
88
|
+
its(:count) { is_expected.to eq df.ncols + 1 }
|
89
|
+
it { is_expected.to all eq '...' }
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'last row' do
|
93
|
+
subject(:row) { table.search('tr:nth-child(34) td').map(&:text) }
|
94
|
+
its(:count) { is_expected.to eq df.ncols + 1 }
|
95
|
+
it { is_expected.to eq ['299', *df.row[-1].map(&:to_s)] }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with multi-index' do
|
100
|
+
let(:df) {
|
101
|
+
Daru::DataFrame.new(
|
102
|
+
{
|
103
|
+
a: [1,2,3,4,5,6,7],
|
104
|
+
b: %w[a b c d e f g]
|
105
|
+
}, index: Daru::MultiIndex.from_tuples([
|
106
|
+
%w[foo one],
|
107
|
+
%w[foo two],
|
108
|
+
%w[foo three],
|
109
|
+
%w[bar one],
|
110
|
+
%w[bar two],
|
111
|
+
%w[bar three],
|
112
|
+
%w[baz one],
|
113
|
+
]),
|
114
|
+
name: 'test'
|
115
|
+
)
|
116
|
+
}
|
117
|
+
|
118
|
+
describe 'header' do
|
119
|
+
subject { header }
|
120
|
+
|
121
|
+
it { is_expected.not_to be_nil }
|
122
|
+
its(['colspan']) { is_expected.to eq (df.ncols + df.index.width).to_s }
|
123
|
+
its(:text) { is_expected.to eq "Daru::DataFrame: test (7x2)" }
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'column headers' do
|
127
|
+
let(:row) { table.search('tr:nth-child(2)') }
|
128
|
+
subject { splitted_row }
|
129
|
+
|
130
|
+
it { is_expected.to eq [
|
131
|
+
'<th colspan="2"></th>',
|
132
|
+
'<th>a</th>',
|
133
|
+
'<th>b</th>'
|
134
|
+
]}
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with multi-index columns' do
|
138
|
+
before { df.vectors = Daru::MultiIndex.from_tuples [[:a, :foo], [:a, :baz]] }
|
139
|
+
|
140
|
+
subject { splitted_row }
|
141
|
+
describe 'first row' do
|
142
|
+
let(:row) { table.search('tr:nth-child(2)') }
|
143
|
+
|
144
|
+
it { is_expected.to eq [
|
145
|
+
'<th colspan="2" rowspan="2"></th>',
|
146
|
+
'<th colspan="2">a</th>',
|
147
|
+
] }
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'next row' do
|
151
|
+
let(:row) { table.search('tr:nth-child(3)') }
|
152
|
+
|
153
|
+
it { is_expected.to eq [
|
154
|
+
'<th colspan="1">foo</th>',
|
155
|
+
'<th colspan="1">baz</th>',
|
156
|
+
] }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe 'first row' do
|
161
|
+
let(:row) { table.search('tr:nth-child(3)') }
|
162
|
+
subject { splitted_row }
|
163
|
+
|
164
|
+
it { is_expected.to eq [
|
165
|
+
'<th rowspan="3">foo</th>',
|
166
|
+
'<th rowspan="1">one</th>',
|
167
|
+
'<td>1</td>',
|
168
|
+
'<td>a</td>'
|
169
|
+
]}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
describe Daru::IRuby::Helpers do
|
2
|
+
context 'MultiIndex' do
|
3
|
+
let(:index) {
|
4
|
+
Daru::MultiIndex.from_tuples [
|
5
|
+
[:a,:one,:bar],
|
6
|
+
[:a,:one,:baz],
|
7
|
+
[:a,:two,:bar],
|
8
|
+
[:a,:two,:baz],
|
9
|
+
[:b,:one,:bar],
|
10
|
+
[:b,:two,:bar],
|
11
|
+
[:b,:two,:baz],
|
12
|
+
[:b,:one,:foo],
|
13
|
+
[:c,:one,:bar],
|
14
|
+
[:c,:one,:baz],
|
15
|
+
[:c,:two,:foo],
|
16
|
+
[:c,:two,:bar]
|
17
|
+
]
|
18
|
+
}
|
19
|
+
|
20
|
+
context '#tuples_with_rowspans' do
|
21
|
+
subject { described_class.tuples_with_rowspans(index) }
|
22
|
+
|
23
|
+
it { is_expected.to eq [
|
24
|
+
[[:a,4],[:one,2],[:bar,1]],
|
25
|
+
[ [:baz,1]],
|
26
|
+
[ [:two,2],[:bar,1]],
|
27
|
+
[ [:baz,1]],
|
28
|
+
[[:b,4],[:one,1],[:bar,1]],
|
29
|
+
[ [:two,2],[:bar,1]],
|
30
|
+
[ [:baz,1]],
|
31
|
+
[ [:one,1],[:foo,1]],
|
32
|
+
[[:c,4],[:one,2],[:bar,1]],
|
33
|
+
[ [:baz,1]],
|
34
|
+
[ [:two,2],[:foo,1]],
|
35
|
+
[ [:bar,1]]
|
36
|
+
]}
|
37
|
+
end
|
38
|
+
|
39
|
+
context '#tuples_with_colspans' do
|
40
|
+
subject { described_class.tuples_with_colspans(index) }
|
41
|
+
|
42
|
+
it { is_expected.to eq [
|
43
|
+
[[:a, 4], [:b, 4], [:c, 4]],
|
44
|
+
[[:one, 2], [:two, 2], [:one, 1], [:two, 2], [:one, 1], [:one, 2], [:two, 2]],
|
45
|
+
[[:bar, 1], [:baz, 1], [:bar, 1], [:baz, 1], [:bar, 1], [:bar, 1], [:baz, 1], [:foo, 1], [:bar, 1], [:baz, 1], [:foo, 1], [:bar, 1]]
|
46
|
+
]}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
describe Daru::MultiIndex, '#to_html' do
|
2
|
+
let(:index) {
|
3
|
+
Daru::MultiIndex.from_tuples [
|
4
|
+
[:a,:one,:bar],
|
5
|
+
[:a,:one,:baz],
|
6
|
+
[:a,:two,:bar],
|
7
|
+
[:a,:two,:baz],
|
8
|
+
[:b,:one,:bar],
|
9
|
+
[:b,:two,:bar],
|
10
|
+
[:b,:two,:baz],
|
11
|
+
[:b,:one,:foo],
|
12
|
+
[:c,:one,:bar],
|
13
|
+
[:c,:one,:baz],
|
14
|
+
[:c,:two,:foo],
|
15
|
+
[:c,:two,:bar]
|
16
|
+
]
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:table) { Nokogiri::HTML(index.to_html) }
|
20
|
+
|
21
|
+
describe 'first row' do
|
22
|
+
subject { table.at('tr:first-child > th') }
|
23
|
+
its(['colspan']) { is_expected.to eq '3' }
|
24
|
+
its(:text) { is_expected.to eq 'Daru::MultiIndex(12x3)' }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'next row' do
|
28
|
+
let(:row) { table.at('tr:nth-child(2)') }
|
29
|
+
subject { row.inner_html.scan(/<th.+?<\/th>/) }
|
30
|
+
|
31
|
+
it { is_expected.to eq [
|
32
|
+
'<th rowspan="4">a</th>',
|
33
|
+
'<th rowspan="2">one</th>',
|
34
|
+
'<th rowspan="1">bar</th>'
|
35
|
+
]}
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
describe Daru::Vector, '#to_html' do
|
2
|
+
[nil, :category].each do |type|
|
3
|
+
let(:doc) { Nokogiri::HTML(vector.to_html) }
|
4
|
+
subject(:table) { doc.at('table') }
|
5
|
+
let(:header) { table.at('tr:first-child > th:first-child') }
|
6
|
+
|
7
|
+
context 'simple' do
|
8
|
+
let(:vector) { Daru::Vector.new [1,nil,3],
|
9
|
+
index: [:a, :b, :c], name: 'test', type: type }
|
10
|
+
it { is_expected.not_to be_nil }
|
11
|
+
|
12
|
+
describe 'header' do
|
13
|
+
subject { header }
|
14
|
+
it { is_expected.not_to be_nil }
|
15
|
+
its(['colspan']) { is_expected.to eq '2' }
|
16
|
+
its(:text) { is_expected.to eq "Daru::Vector(3)"\
|
17
|
+
"#{":category" if type == :category}" }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'name' do
|
21
|
+
subject(:name) { table.at('tr:nth-child(2) > th:nth-child(2)') }
|
22
|
+
it { is_expected.not_to be_nil }
|
23
|
+
its(:text) { is_expected.to eq 'test' }
|
24
|
+
|
25
|
+
context 'withought name' do
|
26
|
+
let(:vector) { Daru::Vector.new [1,nil,3], index: [:a, :b, :c], type: type }
|
27
|
+
|
28
|
+
it { is_expected.to be_nil }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'index' do
|
33
|
+
subject(:indexes) { table.search('tr > td:first-child').map(&:text) }
|
34
|
+
its(:count) { is_expected.to eq vector.size }
|
35
|
+
it { is_expected.to eq vector.index.to_a.map(&:to_s) }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'values' do
|
39
|
+
subject(:indexes) { table.search('tr > td:last-child').map(&:text) }
|
40
|
+
its(:count) { is_expected.to eq vector.size }
|
41
|
+
it { is_expected.to eq vector.to_a.map(&:to_s) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'large vector' do
|
46
|
+
subject(:vector) { Daru::Vector.new [1,2,3] * 100, name: 'test', type: type }
|
47
|
+
it 'has only 30 rows (+ 2 header rows, + 2 finishing rows)' do
|
48
|
+
expect(table.search('tr').size).to eq 34
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '"skipped" row' do
|
52
|
+
subject(:row) { table.search('tr:nth-child(33) td').map(&:text) }
|
53
|
+
its(:count) { is_expected.to eq 2 }
|
54
|
+
it { is_expected.to eq ['...', '...'] }
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'last row' do
|
58
|
+
subject(:row) { table.search('tr:nth-child(34) td').map(&:text) }
|
59
|
+
its(:count) { is_expected.to eq 2 }
|
60
|
+
it { is_expected.to eq ['299', '3'] }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'multi-index' do
|
65
|
+
subject(:vector) {
|
66
|
+
Daru::Vector.new(
|
67
|
+
[1,2,3,4,5,6,7],
|
68
|
+
name: 'test',
|
69
|
+
type: type,
|
70
|
+
index: Daru::MultiIndex.from_tuples([
|
71
|
+
%w[foo one],
|
72
|
+
%w[foo two],
|
73
|
+
%w[foo three],
|
74
|
+
%w[bar one],
|
75
|
+
%w[bar two],
|
76
|
+
%w[bar three],
|
77
|
+
%w[baz one],
|
78
|
+
]),
|
79
|
+
)
|
80
|
+
}
|
81
|
+
|
82
|
+
describe 'header' do
|
83
|
+
subject { header }
|
84
|
+
it { is_expected.not_to be_nil }
|
85
|
+
its(['colspan']) { is_expected.to eq '3' }
|
86
|
+
its(:text) { is_expected.to eq "Daru::Vector(7)"\
|
87
|
+
"#{":category" if type == :category}" }
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'name row' do
|
91
|
+
subject(:row) { table.at('tr:nth-child(2)').search('th') }
|
92
|
+
its(:count) { should == 2 }
|
93
|
+
it { expect(row.first['colspan']).to eq '2' }
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'first data row' do
|
97
|
+
let(:row) { table.at('tr:nth-child(3)') }
|
98
|
+
subject { row.inner_html.scan(/<t[dh].+?<\/t[dh]>/) }
|
99
|
+
it { is_expected.to eq [
|
100
|
+
'<th rowspan="3">foo</th>',
|
101
|
+
'<th rowspan="1">one</th>',
|
102
|
+
'<td>1</td>'
|
103
|
+
]}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -1,25 +1,23 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
1
|
describe Daru::DataFrame do
|
4
2
|
before(:each) do
|
5
|
-
@df = Daru::DataFrame.new({a: [1,2,3,4,5], b: ['a','e','i','o','u'],
|
3
|
+
@df = Daru::DataFrame.new({a: [1,2,3,4,5], b: ['a','e','i','o','u'],
|
6
4
|
c: [10,20,30,40,50]})
|
7
5
|
@left = Daru::DataFrame.new({a: [1,nil,nil,4], b: [10,nil,nil,40], c: [5,6,7,8]},
|
8
6
|
index: [0,4,5,3])
|
9
|
-
@right = Daru::DataFrame.new({a: [1,2,3,4,5], b: [10,20,30,40,50]},
|
7
|
+
@right = Daru::DataFrame.new({a: [1,2,3,4,5], b: [10,20,30,40,50]},
|
10
8
|
index: [0,1,2,3,6])
|
11
9
|
end
|
12
10
|
|
13
11
|
context "#+" do
|
14
12
|
it "adds a number to all numeric vectors" do
|
15
|
-
expect(@df + 2).to eq(Daru::DataFrame.new({a: [3,4,5,6,7], b: ['a','e','i','o','u'],
|
13
|
+
expect(@df + 2).to eq(Daru::DataFrame.new({a: [3,4,5,6,7], b: ['a','e','i','o','u'],
|
16
14
|
c: [12,22,32,42,52] }))
|
17
15
|
end
|
18
16
|
|
19
17
|
it "adds two dataframes to produce a third" do
|
20
18
|
expect(@left + @right).to eq(Daru::DataFrame.new({
|
21
19
|
a: [2,nil,nil,8,nil,nil],
|
22
|
-
b: [20,nil,nil,80,nil,nil],
|
20
|
+
b: [20,nil,nil,80,nil,nil],
|
23
21
|
c: [nil,nil,nil,nil,nil,nil]
|
24
22
|
}, index: [0,1,2,3,4,5,6]))
|
25
23
|
end
|
@@ -28,36 +26,85 @@ describe Daru::DataFrame do
|
|
28
26
|
context "#-" do
|
29
27
|
it "subtracts a number from all numeric vectors" do
|
30
28
|
expect(@df - 2).to eq(Daru::DataFrame.new({
|
31
|
-
a: [-1,0,1,2,3],
|
32
|
-
b: ['a','e','i','o','u'],
|
29
|
+
a: [-1,0,1,2,3],
|
30
|
+
b: ['a','e','i','o','u'],
|
33
31
|
c: [8,18,28,38,48]}))
|
34
32
|
end
|
35
33
|
|
36
34
|
it "subtracts a data frame from another" do
|
37
|
-
|
35
|
+
expect(@left - @right).to eq(Daru::DataFrame.new({
|
36
|
+
a: [0,nil,nil,0,nil,nil],
|
37
|
+
b: [0,nil,nil,0,nil,nil],
|
38
|
+
c: [nil,nil,nil,nil,nil,nil]
|
39
|
+
}, index: [0,1,2,3,4,5,6]))
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
context "#*" do
|
42
|
-
it "multiplies
|
44
|
+
it "multiplies all numeric vectors by number" do
|
45
|
+
expect(@df * 2).to eq(Daru::DataFrame.new({a: [2,4,6,8,10], b: ['a','e','i','o','u'],
|
46
|
+
c: [20,40,60,80,100] }))
|
47
|
+
end
|
48
|
+
|
49
|
+
it "multipies two dataframes to produce a third" do
|
50
|
+
expect(@left * @right).to eq(Daru::DataFrame.new({
|
51
|
+
a: [1,nil,nil,16,nil,nil],
|
52
|
+
b: [100,nil,nil,1600,nil,nil],
|
53
|
+
c: [nil,nil,nil,nil,nil,nil]
|
54
|
+
}, index: [0,1,2,3,4,5,6]))
|
43
55
|
end
|
44
56
|
end
|
45
57
|
|
46
58
|
context "#/" do
|
59
|
+
it "divides all numeric vectors by number" do
|
60
|
+
expect(@df / 2.0).to eq(Daru::DataFrame.new({a: [0.5, 1, 1.5, 2, 2.5], b: ['a','e','i','o','u'],
|
61
|
+
c: [5,10,15,20,25] }))
|
62
|
+
end
|
47
63
|
|
64
|
+
it "multipies two dataframes to produce a third" do
|
65
|
+
# NB: this and other tests of two DF interactions are not EXTREMELY
|
66
|
+
# useful, but to know that nothing unexpected emerges here
|
67
|
+
expect(@left / @right).to eq(Daru::DataFrame.new({
|
68
|
+
a: [1,nil,nil,1,nil,nil],
|
69
|
+
b: [1,nil,nil,1,nil,nil],
|
70
|
+
c: [nil,nil,nil,nil,nil,nil]
|
71
|
+
}, index: [0,1,2,3,4,5,6]))
|
72
|
+
end
|
48
73
|
end
|
49
74
|
|
50
75
|
context "#%" do
|
76
|
+
it "divides all numeric vectors by number and returns reminder" do
|
77
|
+
expect(@df % 3).to eq(Daru::DataFrame.new({a: [1, 2, 0, 1, 2], b: ['a','e','i','o','u'],
|
78
|
+
c: [1, 2, 0, 1, 2] }))
|
79
|
+
end
|
51
80
|
|
81
|
+
it "returns reminder of per-item division" do
|
82
|
+
expect(@left % @right).to eq(Daru::DataFrame.new({
|
83
|
+
a: [0,nil,nil,0,nil,nil],
|
84
|
+
b: [0,nil,nil,0,nil,nil],
|
85
|
+
c: [nil,nil,nil,nil,nil,nil]
|
86
|
+
}, index: [0,1,2,3,4,5,6]))
|
87
|
+
end
|
52
88
|
end
|
53
89
|
|
54
90
|
context "#**" do
|
91
|
+
it "calculates result of each numeric value pow" do
|
92
|
+
expect(@df ** 2).to eq(Daru::DataFrame.new({a: [1, 4, 9, 16, 25], b: ['a','e','i','o','u'],
|
93
|
+
c: [100, 400, 900, 1600, 2500] }))
|
94
|
+
end
|
55
95
|
|
96
|
+
it "returns per-item pow" do
|
97
|
+
expect(@left ** @right).to eq(Daru::DataFrame.new({
|
98
|
+
a: [1,nil,nil,4**4,nil,nil],
|
99
|
+
b: [10**10,nil,nil,40**40,nil,nil],
|
100
|
+
c: [nil,nil,nil,nil,nil,nil]
|
101
|
+
}, index: [0,1,2,3,4,5,6]))
|
102
|
+
end
|
56
103
|
end
|
57
104
|
|
58
105
|
context "#sqrt" do
|
59
106
|
it "calculates sqrt" do
|
60
|
-
expect_correct_df_in_delta(@df.sqrt,
|
107
|
+
expect_correct_df_in_delta(@df.sqrt,
|
61
108
|
Daru::DataFrame.new({
|
62
109
|
a: [1.0,1.41421356,1.73205080,2.0,2.23606797],
|
63
110
|
c: [3.16227766, 4.47213595 ,5.47722557 ,6.32455532, 7.07106781]
|
@@ -84,7 +131,18 @@ describe Daru::DataFrame do
|
|
84
131
|
|
85
132
|
context "#exp" do
|
86
133
|
it "calculates exponential" do
|
87
|
-
|
134
|
+
e = Math::E
|
135
|
+
df = Daru::DataFrame.new({
|
136
|
+
a: [1,2,3],
|
137
|
+
b: [4,5,6],
|
138
|
+
c: %w(a b c)
|
139
|
+
})
|
140
|
+
ans = Daru::DataFrame.new({
|
141
|
+
a: [e, e**2, e**3],
|
142
|
+
b: [e**4, e**5, e**6],
|
143
|
+
})
|
144
|
+
|
145
|
+
expect_correct_df_in_delta(df.exp, ans, 0.0001)
|
88
146
|
end
|
89
147
|
end
|
90
|
-
end
|
148
|
+
end
|