daru 0.1.3.1 → 0.1.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.
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