daru 0.1.5 → 0.1.6
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/.rubocop.yml +20 -7
- data/CONTRIBUTING.md +1 -1
- data/History.md +48 -1
- data/README.md +3 -3
- data/benchmarks/statistics.rb +6 -6
- data/benchmarks/where_clause.rb +1 -1
- data/benchmarks/where_vs_filter.rb +1 -1
- data/daru.gemspec +3 -2
- data/lib/daru.rb +14 -6
- data/lib/daru/accessors/gsl_wrapper.rb +1 -1
- data/lib/daru/accessors/nmatrix_wrapper.rb +2 -0
- data/lib/daru/category.rb +1 -1
- data/lib/daru/core/group_by.rb +32 -15
- data/lib/daru/core/query.rb +4 -4
- data/lib/daru/dataframe.rb +196 -48
- data/lib/daru/date_time/index.rb +7 -5
- data/lib/daru/formatters/table.rb +1 -0
- data/lib/daru/index/index.rb +121 -33
- data/lib/daru/index/multi_index.rb +83 -3
- data/lib/daru/io/csv/converters.rb +18 -0
- data/lib/daru/io/io.rb +80 -11
- data/lib/daru/io/sql_data_source.rb +10 -0
- data/lib/daru/iruby/templates/dataframe.html.erb +3 -50
- data/lib/daru/iruby/templates/dataframe_mi.html.erb +3 -56
- data/lib/daru/iruby/templates/dataframe_mi_tbody.html.erb +35 -0
- data/lib/daru/iruby/templates/dataframe_mi_thead.html.erb +21 -0
- data/lib/daru/iruby/templates/dataframe_tbody.html.erb +28 -0
- data/lib/daru/iruby/templates/dataframe_thead.html.erb +21 -0
- data/lib/daru/iruby/templates/vector.html.erb +3 -25
- data/lib/daru/iruby/templates/vector_mi.html.erb +3 -34
- data/lib/daru/iruby/templates/vector_mi_tbody.html.erb +26 -0
- data/lib/daru/iruby/templates/vector_mi_thead.html.erb +8 -0
- data/lib/daru/iruby/templates/vector_tbody.html.erb +17 -0
- data/lib/daru/iruby/templates/vector_thead.html.erb +8 -0
- data/lib/daru/maths/statistics/dataframe.rb +9 -11
- data/lib/daru/maths/statistics/vector.rb +139 -32
- data/lib/daru/plotting/gruff/dataframe.rb +13 -15
- data/lib/daru/plotting/nyaplot/category.rb +1 -1
- data/lib/daru/plotting/nyaplot/dataframe.rb +4 -4
- data/lib/daru/plotting/nyaplot/vector.rb +1 -2
- data/lib/daru/vector.rb +169 -80
- data/lib/daru/version.rb +1 -1
- data/spec/category_spec.rb +19 -19
- data/spec/core/group_by_spec.rb +47 -0
- data/spec/core/query_spec.rb +55 -50
- data/spec/daru_spec.rb +22 -0
- data/spec/dataframe_spec.rb +118 -6
- data/spec/date_time/index_spec.rb +34 -16
- data/spec/extensions/rserve_spec.rb +1 -1
- data/spec/fixtures/boolean_converter_test.csv +5 -0
- data/spec/fixtures/eciresults.html +394 -0
- data/spec/fixtures/empty_rows_test.csv +17 -0
- data/spec/fixtures/macau.html +3691 -0
- data/spec/fixtures/macd_data.csv +150 -0
- data/spec/fixtures/moneycontrol.html +6812 -0
- data/spec/fixtures/url_test.txt~ +0 -0
- data/spec/fixtures/valid_markup.html +62 -0
- data/spec/fixtures/wiki_climate.html +1243 -0
- data/spec/fixtures/wiki_table_info.html +631 -0
- data/spec/formatters/table_formatter_spec.rb +29 -0
- data/spec/index/categorical_index_spec.rb +33 -33
- data/spec/index/index_spec.rb +134 -41
- data/spec/index/multi_index_spec.rb +115 -31
- data/spec/io/io_spec.rb +201 -0
- data/spec/io/sql_data_source_spec.rb +31 -41
- data/spec/iruby/dataframe_spec.rb +17 -19
- data/spec/iruby/vector_spec.rb +26 -28
- data/spec/maths/statistics/vector_spec.rb +136 -14
- data/spec/plotting/gruff/category_spec.rb +3 -3
- data/spec/plotting/gruff/dataframe_spec.rb +14 -4
- data/spec/plotting/gruff/vector_spec.rb +9 -9
- data/spec/plotting/nyaplot/category_spec.rb +5 -9
- data/spec/plotting/nyaplot/dataframe_spec.rb +72 -47
- data/spec/plotting/nyaplot/vector_spec.rb +5 -11
- data/spec/shared/vector_display_spec.rb +12 -14
- data/spec/spec_helper.rb +21 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/vector_spec.rb +222 -72
- metadata +68 -23
- data/spec/fixtures/stock_data.csv +0 -500
@@ -5,62 +5,52 @@ require 'active_record'
|
|
5
5
|
|
6
6
|
RSpec.describe Daru::IO::SqlDataSource do
|
7
7
|
include_context 'with accounts table in sqlite3 database'
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
let(:query) do
|
10
|
+
'select * from accounts'
|
10
11
|
end
|
11
12
|
|
12
|
-
let(:
|
13
|
+
let(:source) do
|
13
14
|
ActiveRecord::Base.establish_connection("sqlite3:#{db_name}")
|
14
15
|
ActiveRecord::Base.connection
|
15
16
|
end
|
16
17
|
|
17
|
-
let(:query) do
|
18
|
-
'select * from accounts'
|
19
|
-
end
|
20
|
-
|
21
18
|
describe '.make_dataframe' do
|
22
|
-
|
23
|
-
it 'returns a dataframe' do
|
24
|
-
result = Daru::IO::SqlDataSource.make_dataframe(dbi_handle, query)
|
25
|
-
expect(result).to be_a(Daru::DataFrame)
|
26
|
-
expect(result.nrows).to eq(2)
|
27
|
-
expect(result.row[0][:id]).to eq(1)
|
28
|
-
expect(result.row[0][:name]).to eq('Homer')
|
29
|
-
end
|
19
|
+
subject(:df) { Daru::IO::SqlDataSource.make_dataframe(source, query) }
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
21
|
+
context 'with DBI::DatabaseHandle' do
|
22
|
+
let(:source) { DBI.connect("DBI:SQLite3:#{db_name}") }
|
23
|
+
it { is_expected.to be_a(Daru::DataFrame) }
|
24
|
+
it { expect(df.row[0]).to have_attributes(id: 1, age: 20) }
|
25
|
+
its(:nrows) { is_expected.to eq 2 }
|
38
26
|
end
|
39
27
|
|
40
28
|
context 'with ActiveRecord::Connection' do
|
41
|
-
it
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
expect(result.row[0][:id]).to eq(1)
|
46
|
-
expect(result.row[0][:name]).to eq('Homer')
|
47
|
-
end
|
29
|
+
it { is_expected.to be_a(Daru::DataFrame) }
|
30
|
+
it { expect(df.row[0]).to have_attributes(id: 1, age: 20) }
|
31
|
+
its(:nrows) { is_expected.to eq 2 }
|
32
|
+
end
|
48
33
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
34
|
+
context 'with path to sqlite3 file' do
|
35
|
+
let(:source) { db_name }
|
36
|
+
it { is_expected.to be_a(Daru::DataFrame) }
|
37
|
+
it { expect(df.row[0]).to have_attributes(id: 1, age: 20) }
|
38
|
+
its(:nrows) { is_expected.to eq 2 }
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with an object not a string as a query' do
|
42
|
+
let(:query) { Object.new }
|
43
|
+
it { expect { df }.to raise_error(ArgumentError) }
|
56
44
|
end
|
57
45
|
|
58
46
|
context 'with an object not a database connection' do
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
47
|
+
let(:source) { Object.new }
|
48
|
+
it { expect { df }.to raise_error(ArgumentError) }
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with path to unsupported db file' do
|
52
|
+
let(:source) { 'spec/fixtures/bank2.dat' }
|
53
|
+
it { expect { df }.to raise_error(ArgumentError) }
|
64
54
|
end
|
65
55
|
end
|
66
56
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
describe Daru::DataFrame, '#to_html' do
|
2
2
|
let(:doc) { Nokogiri::HTML(df.to_html) }
|
3
3
|
subject(:table) { doc.at('table') }
|
4
|
-
let(:header) {
|
4
|
+
let(:header) { doc.at('b')}
|
5
5
|
let(:name) { 'test' }
|
6
6
|
|
7
7
|
let(:splitted_row) { row.inner_html.scan(/<t[dh].+?<\/t[dh]>/) }
|
@@ -13,18 +13,17 @@ describe Daru::DataFrame, '#to_html' do
|
|
13
13
|
subject { header }
|
14
14
|
|
15
15
|
it { is_expected.not_to be_nil }
|
16
|
-
its(
|
17
|
-
its(:text) { is_expected.to eq "Daru::DataFrame: test (3x3)" }
|
16
|
+
its(:text) { is_expected.to eq " Daru::DataFrame: test (3x3) " }
|
18
17
|
|
19
18
|
context 'without name' do
|
20
19
|
let(:name) { nil }
|
21
20
|
|
22
|
-
its(:text) { is_expected.to eq "Daru::DataFrame(3x3)" }
|
21
|
+
its(:text) { is_expected.to eq " Daru::DataFrame(3x3) " }
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
describe 'column headers' do
|
27
|
-
subject(:columns) { table.search('tr:nth-child(
|
26
|
+
subject(:columns) { table.search('tr:nth-child(1) th').map(&:text) }
|
28
27
|
its(:size) { is_expected.to eq df.ncols + 1 }
|
29
28
|
it { is_expected.to eq ['', 'a', 'b', 'c'] }
|
30
29
|
end
|
@@ -34,7 +33,7 @@ describe Daru::DataFrame, '#to_html' do
|
|
34
33
|
|
35
34
|
subject { splitted_row }
|
36
35
|
describe 'first row' do
|
37
|
-
let(:row) { table.search('tr:nth-child(
|
36
|
+
let(:row) { table.search('thead > tr:nth-child(1)') }
|
38
37
|
|
39
38
|
it { is_expected.to eq [
|
40
39
|
'<th rowspan="2"></th>',
|
@@ -44,7 +43,7 @@ describe Daru::DataFrame, '#to_html' do
|
|
44
43
|
end
|
45
44
|
|
46
45
|
describe 'next row' do
|
47
|
-
let(:row) { table.search('tr:nth-child(
|
46
|
+
let(:row) { table.search('thead > tr:nth-child(2)') }
|
48
47
|
|
49
48
|
it { is_expected.to eq [
|
50
49
|
'<th colspan="1">foo</th>',
|
@@ -62,7 +61,7 @@ describe Daru::DataFrame, '#to_html' do
|
|
62
61
|
|
63
62
|
describe 'values' do
|
64
63
|
subject(:values) {
|
65
|
-
table.search('tr')[
|
64
|
+
table.search('tr')[1..-1]
|
66
65
|
.map { |tr| tr.search('td')[1..-1].map(&:text) }
|
67
66
|
}
|
68
67
|
its(:count) { is_expected.to eq df.nrows }
|
@@ -76,21 +75,21 @@ describe Daru::DataFrame, '#to_html' do
|
|
76
75
|
describe 'header' do
|
77
76
|
subject { header }
|
78
77
|
|
79
|
-
its(:text) { is_expected.to eq "Daru::DataFrame: test (300x3)" }
|
78
|
+
its(:text) { is_expected.to eq " Daru::DataFrame: test (300x3) " }
|
80
79
|
end
|
81
80
|
|
82
|
-
it 'has only 30 rows (+
|
83
|
-
expect(table.search('tr').size).to eq
|
81
|
+
it 'has only 30 rows (+ 1 header rows, + 2 finishing rows)' do
|
82
|
+
expect(table.search('tr').size).to eq 33
|
84
83
|
end
|
85
84
|
|
86
85
|
describe '"skipped" row' do
|
87
|
-
subject(:row) { table.search('tr:nth-child(
|
86
|
+
subject(:row) { table.search('tr:nth-child(31) td').map(&:text) }
|
88
87
|
its(:count) { is_expected.to eq df.ncols + 1 }
|
89
88
|
it { is_expected.to all eq '...' }
|
90
89
|
end
|
91
90
|
|
92
91
|
describe 'last row' do
|
93
|
-
subject(:row) { table.search('tr:nth-child(
|
92
|
+
subject(:row) { table.search('tr:nth-child(32) td').map(&:text) }
|
94
93
|
its(:count) { is_expected.to eq df.ncols + 1 }
|
95
94
|
it { is_expected.to eq ['299', *df.row[-1].map(&:to_s)] }
|
96
95
|
end
|
@@ -119,12 +118,11 @@ describe Daru::DataFrame, '#to_html' do
|
|
119
118
|
subject { header }
|
120
119
|
|
121
120
|
it { is_expected.not_to be_nil }
|
122
|
-
its(
|
123
|
-
its(:text) { is_expected.to eq "Daru::DataFrame: test (7x2)" }
|
121
|
+
its(:text) { is_expected.to eq " Daru::DataFrame: test (7x2) " }
|
124
122
|
end
|
125
123
|
|
126
124
|
describe 'column headers' do
|
127
|
-
let(:row) { table.search('tr:nth-child(
|
125
|
+
let(:row) { table.search('thead > tr:nth-child(1)') }
|
128
126
|
subject { splitted_row }
|
129
127
|
|
130
128
|
it { is_expected.to eq [
|
@@ -139,7 +137,7 @@ describe Daru::DataFrame, '#to_html' do
|
|
139
137
|
|
140
138
|
subject { splitted_row }
|
141
139
|
describe 'first row' do
|
142
|
-
let(:row) { table.search('tr:nth-child(
|
140
|
+
let(:row) { table.search('thead > tr:nth-child(1)') }
|
143
141
|
|
144
142
|
it { is_expected.to eq [
|
145
143
|
'<th colspan="2" rowspan="2"></th>',
|
@@ -148,7 +146,7 @@ describe Daru::DataFrame, '#to_html' do
|
|
148
146
|
end
|
149
147
|
|
150
148
|
describe 'next row' do
|
151
|
-
let(:row) { table.search('tr:nth-child(
|
149
|
+
let(:row) { table.search('thead > tr:nth-child(2)') }
|
152
150
|
|
153
151
|
it { is_expected.to eq [
|
154
152
|
'<th colspan="1">foo</th>',
|
@@ -158,7 +156,7 @@ describe Daru::DataFrame, '#to_html' do
|
|
158
156
|
end
|
159
157
|
|
160
158
|
describe 'first row' do
|
161
|
-
let(:row) { table.search('tr:nth-child(
|
159
|
+
let(:row) { table.search('tbody > tr:nth-child(1)') }
|
162
160
|
subject { splitted_row }
|
163
161
|
|
164
162
|
it { is_expected.to eq [
|
data/spec/iruby/vector_spec.rb
CHANGED
@@ -2,65 +2,64 @@ describe Daru::Vector, '#to_html' do
|
|
2
2
|
[nil, :category].each do |type|
|
3
3
|
let(:doc) { Nokogiri::HTML(vector.to_html) }
|
4
4
|
subject(:table) { doc.at('table') }
|
5
|
-
let(:header) {
|
6
|
-
|
5
|
+
let(:header) { doc.at('b') }
|
6
|
+
|
7
7
|
context 'simple' do
|
8
8
|
let(:vector) { Daru::Vector.new [1,nil,3],
|
9
9
|
index: [:a, :b, :c], name: 'test', type: type }
|
10
10
|
it { is_expected.not_to be_nil }
|
11
|
-
|
11
|
+
|
12
12
|
describe 'header' do
|
13
13
|
subject { header }
|
14
14
|
it { is_expected.not_to be_nil }
|
15
|
-
its(
|
16
|
-
|
17
|
-
"#{":category" if type == :category}" }
|
15
|
+
its(:text) { is_expected.to eq " Daru::Vector(3)"\
|
16
|
+
"#{":category" if type == :category} " }
|
18
17
|
end
|
19
|
-
|
18
|
+
|
20
19
|
describe 'name' do
|
21
|
-
subject(:name) { table.at('tr:nth-child(
|
20
|
+
subject(:name) { table.at('tr:nth-child(1) > th:nth-child(2)') }
|
22
21
|
it { is_expected.not_to be_nil }
|
23
22
|
its(:text) { is_expected.to eq 'test' }
|
24
|
-
|
23
|
+
|
25
24
|
context 'withought name' do
|
26
25
|
let(:vector) { Daru::Vector.new [1,nil,3], index: [:a, :b, :c], type: type }
|
27
|
-
|
26
|
+
|
28
27
|
it { is_expected.to be_nil }
|
29
28
|
end
|
30
29
|
end
|
31
|
-
|
30
|
+
|
32
31
|
describe 'index' do
|
33
32
|
subject(:indexes) { table.search('tr > td:first-child').map(&:text) }
|
34
33
|
its(:count) { is_expected.to eq vector.size }
|
35
34
|
it { is_expected.to eq vector.index.to_a.map(&:to_s) }
|
36
35
|
end
|
37
|
-
|
36
|
+
|
38
37
|
describe 'values' do
|
39
38
|
subject(:indexes) { table.search('tr > td:last-child').map(&:text) }
|
40
39
|
its(:count) { is_expected.to eq vector.size }
|
41
40
|
it { is_expected.to eq vector.to_a.map(&:to_s) }
|
42
41
|
end
|
43
42
|
end
|
44
|
-
|
43
|
+
|
45
44
|
context 'large vector' do
|
46
45
|
subject(:vector) { Daru::Vector.new [1,2,3] * 100, name: 'test', type: type }
|
47
|
-
it 'has only 30 rows (+
|
48
|
-
expect(table.search('tr').size).to eq
|
46
|
+
it 'has only 30 rows (+ 1 header rows, + 2 finishing rows)' do
|
47
|
+
expect(table.search('tr').size).to eq 33
|
49
48
|
end
|
50
|
-
|
49
|
+
|
51
50
|
describe '"skipped" row' do
|
52
|
-
subject(:row) { table.search('tr:nth-child(
|
51
|
+
subject(:row) { table.search('tr:nth-child(31) td').map(&:text) }
|
53
52
|
its(:count) { is_expected.to eq 2 }
|
54
53
|
it { is_expected.to eq ['...', '...'] }
|
55
54
|
end
|
56
|
-
|
55
|
+
|
57
56
|
describe 'last row' do
|
58
|
-
subject(:row) { table.search('tr:nth-child(
|
57
|
+
subject(:row) { table.search('tr:nth-child(32) td').map(&:text) }
|
59
58
|
its(:count) { is_expected.to eq 2 }
|
60
59
|
it { is_expected.to eq ['299', '3'] }
|
61
60
|
end
|
62
61
|
end
|
63
|
-
|
62
|
+
|
64
63
|
context 'multi-index' do
|
65
64
|
subject(:vector) {
|
66
65
|
Daru::Vector.new(
|
@@ -78,23 +77,22 @@ describe Daru::Vector, '#to_html' do
|
|
78
77
|
]),
|
79
78
|
)
|
80
79
|
}
|
81
|
-
|
80
|
+
|
82
81
|
describe 'header' do
|
83
82
|
subject { header }
|
84
83
|
it { is_expected.not_to be_nil }
|
85
|
-
its(
|
86
|
-
|
87
|
-
"#{":category" if type == :category}" }
|
84
|
+
its(:text) { is_expected.to eq " Daru::Vector(7)"\
|
85
|
+
"#{":category" if type == :category} " }
|
88
86
|
end
|
89
|
-
|
87
|
+
|
90
88
|
describe 'name row' do
|
91
|
-
subject(:row) { table.at('tr:nth-child(
|
89
|
+
subject(:row) { table.at('tr:nth-child(1)').search('th') }
|
92
90
|
its(:count) { should == 2 }
|
93
91
|
it { expect(row.first['colspan']).to eq '2' }
|
94
92
|
end
|
95
|
-
|
93
|
+
|
96
94
|
describe 'first data row' do
|
97
|
-
let(:row) { table.at('tr:
|
95
|
+
let(:row) { table.at('tbody > tr:first-child') }
|
98
96
|
subject { row.inner_html.scan(/<t[dh].+?<\/t[dh]>/) }
|
99
97
|
it { is_expected.to eq [
|
100
98
|
'<th rowspan="3">foo</th>',
|
@@ -12,6 +12,116 @@ describe Daru::Vector do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
let(:dv) { dv = Daru::Vector.new (["Tyrion", "Daenerys", "Jon Starkgaryen"]), index: Daru::Index.new([:t, :d, :j]) }
|
16
|
+
|
17
|
+
context "#max" do
|
18
|
+
it "returns max value" do
|
19
|
+
expect(dv.max).to eq("Tyrion")
|
20
|
+
end
|
21
|
+
it "returns N max values" do
|
22
|
+
expect(dv.max(2)).to eq(["Tyrion","Jon Starkgaryen"])
|
23
|
+
end
|
24
|
+
it "returns max value, sorted by comparitive block input" do
|
25
|
+
expect(dv.max { |a,b| a.size <=> b.size }).to eq("Jon Starkgaryen")
|
26
|
+
end
|
27
|
+
it "returns max value, sorted by object block input" do
|
28
|
+
expect(dv.max { |x| x.size }).to eq("Jon Starkgaryen")
|
29
|
+
end
|
30
|
+
it "returns N max values, sorted by comparitive block input" do
|
31
|
+
expect(dv.max(2) {|a,b| a.size <=> b.size}).to eq(["Jon Starkgaryen","Daenerys"])
|
32
|
+
end
|
33
|
+
it "returns N max values, sorted by object block input" do
|
34
|
+
expect(dv.max(2) {|x| x.size }).to eq(["Jon Starkgaryen","Daenerys"])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "#index_of_max" do
|
39
|
+
it "returns index_of_max value" do
|
40
|
+
expect(dv.index_of_max).to eq(:t)
|
41
|
+
end
|
42
|
+
it "returns N index_of_max values" do
|
43
|
+
expect(dv.index_of_max(2)).to eq([:t, :j])
|
44
|
+
end
|
45
|
+
it "returns index_of_max value, sorted by comparitive block input" do
|
46
|
+
expect(dv.index_of_max { |a,b| a.size <=> b.size }).to eq(:j)
|
47
|
+
end
|
48
|
+
it "returns index_of_max value, sorted by object block input" do
|
49
|
+
expect(dv.index_of_max { |x| x.size }).to eq(:j)
|
50
|
+
end
|
51
|
+
it "returns N index_of_max values, sorted by comparitive block input" do
|
52
|
+
expect(dv.index_of_max(2) {|a,b| a.size <=> b.size}).to eq([:j, :d])
|
53
|
+
end
|
54
|
+
it "returns N index_of_max values, sorted by object block input" do
|
55
|
+
expect(dv.index_of_max(2) {|x| x.size }).to eq([:j, :d])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "#min" do
|
60
|
+
it "returns min value" do
|
61
|
+
expect(dv.min).to eq("Daenerys")
|
62
|
+
end
|
63
|
+
it "returns N min values" do
|
64
|
+
expect(dv.min(2)).to eq(["Daenerys","Jon Starkgaryen"])
|
65
|
+
end
|
66
|
+
it "returns min value, sorted by comparitive block input" do
|
67
|
+
expect(dv.min { |a,b| a.size <=> b.size }).to eq("Tyrion")
|
68
|
+
end
|
69
|
+
it "returns min value, sorted by object block input" do
|
70
|
+
expect(dv.min { |x| x.size }).to eq("Tyrion")
|
71
|
+
end
|
72
|
+
it "returns N min values, sorted by comparitive block input" do
|
73
|
+
expect(dv.min(2) {|a,b| a.size <=> b.size}).to eq(["Tyrion","Daenerys"])
|
74
|
+
end
|
75
|
+
it "returns N min values, sorted by object block input" do
|
76
|
+
expect(dv.min(2) {|x| x.size }).to eq(["Tyrion","Daenerys"])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "#index_of_min" do
|
81
|
+
it "returns index of min value" do
|
82
|
+
expect(dv.index_of_min).to eq(:d)
|
83
|
+
end
|
84
|
+
it "returns N index of min values" do
|
85
|
+
expect(dv.index_of_min(2)).to eq([:d, :j])
|
86
|
+
end
|
87
|
+
it "returns index of min value, sorted by comparitive block input" do
|
88
|
+
expect(dv.index_of_min { |a,b| a.size <=> b.size }).to eq(:t)
|
89
|
+
end
|
90
|
+
it "returns index of min value, sorted by object block input" do
|
91
|
+
expect(dv.index_of_min { |x| x.size }).to eq(:t)
|
92
|
+
end
|
93
|
+
it "returns N index of min values, sorted by comparitive block input" do
|
94
|
+
expect(dv.index_of_min(2) {|a,b| a.size <=> b.size}).to eq([:t, :d])
|
95
|
+
end
|
96
|
+
it "returns N index of min values, sorted by object block input" do
|
97
|
+
expect(dv.index_of_min(2) {|x| x.size }).to eq([:t, :d])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "#max_by" do
|
102
|
+
it "tests alias of max_by to max" do
|
103
|
+
expect(dv.method(:max_by)).to eq(dv.method(:max))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "#min_by" do
|
108
|
+
it "tests alias of min_by to min" do
|
109
|
+
expect(dv.method(:min_by)).to eq(dv.method(:min))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "#index_of_max_by" do
|
114
|
+
it "tests alias of index_of_max_by to index_of_max" do
|
115
|
+
expect(dv.method(:index_of_max_by)).to eq(dv.method(:index_of_max))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "#index_of_min_by" do
|
120
|
+
it "tests alias of index_of_min_by to index_of_min" do
|
121
|
+
expect(dv.method(:index_of_min_by)).to eq(dv.method(:index_of_min))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
15
125
|
context "#sum_of_squares" do
|
16
126
|
it "calcs sum of squares, omits nil values" do
|
17
127
|
v = Daru::Vector.new [1,2,3,4,5,6], dtype: dtype
|
@@ -583,26 +693,38 @@ describe Daru::Vector do
|
|
583
693
|
end
|
584
694
|
end
|
585
695
|
|
586
|
-
|
587
|
-
|
588
|
-
# MACD uses a lot more data than the other ones, so we need a bigger vector
|
589
|
-
data = Daru::Vector.new(
|
590
|
-
File.readlines("spec/fixtures/stock_data.csv").map(&:to_f))
|
696
|
+
RSpec.shared_examples 'correct macd' do |*args|
|
697
|
+
let(:source) { Daru::DataFrame.from_csv('spec/fixtures/macd_data.csv') }
|
591
698
|
|
592
|
-
|
699
|
+
# skip initial records during compare as ema is sensitive to
|
700
|
+
# period used.
|
701
|
+
# http://ta-lib.org/d_api/ta_setunstableperiod.html
|
702
|
+
let(:stability_offset) { 90 }
|
703
|
+
let(:delta) { 0.001 }
|
704
|
+
let(:desc) { args.empty? ? '12_26_9' : args.join('_') }
|
593
705
|
|
594
|
-
|
595
|
-
expect(macd[-1]).to be_within(1e-6).of(3.12e-4)
|
596
|
-
expect(macd[-10]).to be_within(1e-4).of(-1.07e-2)
|
597
|
-
expect(macd[-20]).to be_within(1e-5).of(-5.65e-3)
|
706
|
+
subject { source['price'].macd(*args) }
|
598
707
|
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
708
|
+
%w[ macd macdsig macdhist ].each_with_index do |field, i|
|
709
|
+
it do
|
710
|
+
act = subject[i][stability_offset..-1]
|
711
|
+
exp = source["#{field}_#{desc}"][stability_offset..-1]
|
712
|
+
expect(act).to be_all_within(delta).of(exp)
|
713
|
+
end
|
603
714
|
end
|
604
715
|
end
|
605
716
|
|
717
|
+
describe '#macd' do
|
718
|
+
context 'by default' do
|
719
|
+
it_should_behave_like 'correct macd'
|
720
|
+
end
|
721
|
+
|
722
|
+
context 'custom values for fast, slow, signal' do
|
723
|
+
it_should_behave_like 'correct macd', 6, 13, 4
|
724
|
+
end
|
725
|
+
|
726
|
+
end
|
727
|
+
|
606
728
|
context "#cumsum" do
|
607
729
|
it "calculates cumulative sum" do
|
608
730
|
vector = Daru::Vector.new([1,2,3,4,5,6,7,8,9,10])
|