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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -1
  4. data/.rspec_formatter.rb +33 -0
  5. data/.rubocop.yml +26 -2
  6. data/History.md +38 -0
  7. data/README.md +22 -13
  8. data/Rakefile +50 -2
  9. data/benchmarks/csv_reading.rb +22 -0
  10. data/daru.gemspec +9 -2
  11. data/lib/daru.rb +36 -4
  12. data/lib/daru/accessors/array_wrapper.rb +6 -1
  13. data/lib/daru/accessors/dataframe_by_row.rb +10 -2
  14. data/lib/daru/accessors/gsl_wrapper.rb +1 -3
  15. data/lib/daru/accessors/nmatrix_wrapper.rb +9 -0
  16. data/lib/daru/category.rb +935 -0
  17. data/lib/daru/core/group_by.rb +29 -38
  18. data/lib/daru/core/merge.rb +186 -145
  19. data/lib/daru/core/query.rb +22 -11
  20. data/lib/daru/dataframe.rb +976 -885
  21. data/lib/daru/date_time/index.rb +166 -166
  22. data/lib/daru/date_time/offsets.rb +66 -77
  23. data/lib/daru/formatters/table.rb +54 -0
  24. data/lib/daru/helpers/array.rb +40 -0
  25. data/lib/daru/index.rb +476 -73
  26. data/lib/daru/io/io.rb +66 -45
  27. data/lib/daru/io/sql_data_source.rb +33 -62
  28. data/lib/daru/iruby/helpers.rb +38 -0
  29. data/lib/daru/iruby/templates/dataframe.html.erb +52 -0
  30. data/lib/daru/iruby/templates/dataframe_mi.html.erb +58 -0
  31. data/lib/daru/iruby/templates/multi_index.html.erb +12 -0
  32. data/lib/daru/iruby/templates/vector.html.erb +27 -0
  33. data/lib/daru/iruby/templates/vector_mi.html.erb +36 -0
  34. data/lib/daru/maths/arithmetic/dataframe.rb +16 -18
  35. data/lib/daru/maths/arithmetic/vector.rb +4 -6
  36. data/lib/daru/maths/statistics/dataframe.rb +8 -15
  37. data/lib/daru/maths/statistics/vector.rb +120 -98
  38. data/lib/daru/monkeys.rb +12 -40
  39. data/lib/daru/plotting/gruff.rb +3 -0
  40. data/lib/daru/plotting/gruff/category.rb +49 -0
  41. data/lib/daru/plotting/gruff/dataframe.rb +91 -0
  42. data/lib/daru/plotting/gruff/vector.rb +57 -0
  43. data/lib/daru/plotting/nyaplot.rb +3 -0
  44. data/lib/daru/plotting/nyaplot/category.rb +34 -0
  45. data/lib/daru/plotting/nyaplot/dataframe.rb +187 -0
  46. data/lib/daru/plotting/nyaplot/vector.rb +46 -0
  47. data/lib/daru/vector.rb +694 -421
  48. data/lib/daru/version.rb +1 -1
  49. data/profile/_base.rb +23 -0
  50. data/profile/df_to_a.rb +10 -0
  51. data/profile/filter.rb +13 -0
  52. data/profile/joining.rb +13 -0
  53. data/profile/sorting.rb +12 -0
  54. data/profile/vector_each_with_index.rb +9 -0
  55. data/spec/accessors/wrappers_spec.rb +2 -4
  56. data/spec/categorical_spec.rb +1734 -0
  57. data/spec/core/group_by_spec.rb +52 -2
  58. data/spec/core/merge_spec.rb +63 -2
  59. data/spec/core/query_spec.rb +236 -80
  60. data/spec/dataframe_spec.rb +1373 -79
  61. data/spec/date_time/data_spec.rb +3 -5
  62. data/spec/date_time/index_spec.rb +154 -17
  63. data/spec/date_time/offsets_spec.rb +3 -4
  64. data/spec/fixtures/empties.dat +2 -0
  65. data/spec/fixtures/strings.dat +2 -0
  66. data/spec/formatters/table_formatter_spec.rb +99 -0
  67. data/spec/helpers_spec.rb +8 -0
  68. data/spec/index/categorical_index_spec.rb +168 -0
  69. data/spec/index/index_spec.rb +283 -0
  70. data/spec/index/multi_index_spec.rb +570 -0
  71. data/spec/io/io_spec.rb +31 -4
  72. data/spec/io/sql_data_source_spec.rb +0 -1
  73. data/spec/iruby/dataframe_spec.rb +172 -0
  74. data/spec/iruby/helpers_spec.rb +49 -0
  75. data/spec/iruby/multi_index_spec.rb +37 -0
  76. data/spec/iruby/vector_spec.rb +107 -0
  77. data/spec/math/arithmetic/dataframe_spec.rb +71 -13
  78. data/spec/math/arithmetic/vector_spec.rb +8 -10
  79. data/spec/math/statistics/dataframe_spec.rb +3 -5
  80. data/spec/math/statistics/vector_spec.rb +45 -55
  81. data/spec/monkeys_spec.rb +32 -9
  82. data/spec/plotting/dataframe_spec.rb +386 -0
  83. data/spec/plotting/vector_spec.rb +230 -0
  84. data/spec/shared/vector_display_spec.rb +215 -0
  85. data/spec/spec_helper.rb +23 -0
  86. data/spec/vector_spec.rb +905 -138
  87. metadata +143 -11
  88. data/.rubocop_todo.yml +0 -44
  89. data/lib/daru/plotting/dataframe.rb +0 -104
  90. data/lib/daru/plotting/vector.rb +0 -38
  91. data/spec/daru_spec.rb +0 -58
  92. data/spec/index_spec.rb +0 -375
@@ -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
- # TODO: write these tests
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
@@ -1,4 +1,3 @@
1
- require 'spec_helper'
2
1
  require 'daru/io/sql_data_source'
3
2
  require 'sqlite3'
4
3
  require 'dbi'
@@ -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 a number with a DataFrame" do
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
- @df.exp
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