daru 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +20 -7
  3. data/CONTRIBUTING.md +1 -1
  4. data/History.md +48 -1
  5. data/README.md +3 -3
  6. data/benchmarks/statistics.rb +6 -6
  7. data/benchmarks/where_clause.rb +1 -1
  8. data/benchmarks/where_vs_filter.rb +1 -1
  9. data/daru.gemspec +3 -2
  10. data/lib/daru.rb +14 -6
  11. data/lib/daru/accessors/gsl_wrapper.rb +1 -1
  12. data/lib/daru/accessors/nmatrix_wrapper.rb +2 -0
  13. data/lib/daru/category.rb +1 -1
  14. data/lib/daru/core/group_by.rb +32 -15
  15. data/lib/daru/core/query.rb +4 -4
  16. data/lib/daru/dataframe.rb +196 -48
  17. data/lib/daru/date_time/index.rb +7 -5
  18. data/lib/daru/formatters/table.rb +1 -0
  19. data/lib/daru/index/index.rb +121 -33
  20. data/lib/daru/index/multi_index.rb +83 -3
  21. data/lib/daru/io/csv/converters.rb +18 -0
  22. data/lib/daru/io/io.rb +80 -11
  23. data/lib/daru/io/sql_data_source.rb +10 -0
  24. data/lib/daru/iruby/templates/dataframe.html.erb +3 -50
  25. data/lib/daru/iruby/templates/dataframe_mi.html.erb +3 -56
  26. data/lib/daru/iruby/templates/dataframe_mi_tbody.html.erb +35 -0
  27. data/lib/daru/iruby/templates/dataframe_mi_thead.html.erb +21 -0
  28. data/lib/daru/iruby/templates/dataframe_tbody.html.erb +28 -0
  29. data/lib/daru/iruby/templates/dataframe_thead.html.erb +21 -0
  30. data/lib/daru/iruby/templates/vector.html.erb +3 -25
  31. data/lib/daru/iruby/templates/vector_mi.html.erb +3 -34
  32. data/lib/daru/iruby/templates/vector_mi_tbody.html.erb +26 -0
  33. data/lib/daru/iruby/templates/vector_mi_thead.html.erb +8 -0
  34. data/lib/daru/iruby/templates/vector_tbody.html.erb +17 -0
  35. data/lib/daru/iruby/templates/vector_thead.html.erb +8 -0
  36. data/lib/daru/maths/statistics/dataframe.rb +9 -11
  37. data/lib/daru/maths/statistics/vector.rb +139 -32
  38. data/lib/daru/plotting/gruff/dataframe.rb +13 -15
  39. data/lib/daru/plotting/nyaplot/category.rb +1 -1
  40. data/lib/daru/plotting/nyaplot/dataframe.rb +4 -4
  41. data/lib/daru/plotting/nyaplot/vector.rb +1 -2
  42. data/lib/daru/vector.rb +169 -80
  43. data/lib/daru/version.rb +1 -1
  44. data/spec/category_spec.rb +19 -19
  45. data/spec/core/group_by_spec.rb +47 -0
  46. data/spec/core/query_spec.rb +55 -50
  47. data/spec/daru_spec.rb +22 -0
  48. data/spec/dataframe_spec.rb +118 -6
  49. data/spec/date_time/index_spec.rb +34 -16
  50. data/spec/extensions/rserve_spec.rb +1 -1
  51. data/spec/fixtures/boolean_converter_test.csv +5 -0
  52. data/spec/fixtures/eciresults.html +394 -0
  53. data/spec/fixtures/empty_rows_test.csv +17 -0
  54. data/spec/fixtures/macau.html +3691 -0
  55. data/spec/fixtures/macd_data.csv +150 -0
  56. data/spec/fixtures/moneycontrol.html +6812 -0
  57. data/spec/fixtures/url_test.txt~ +0 -0
  58. data/spec/fixtures/valid_markup.html +62 -0
  59. data/spec/fixtures/wiki_climate.html +1243 -0
  60. data/spec/fixtures/wiki_table_info.html +631 -0
  61. data/spec/formatters/table_formatter_spec.rb +29 -0
  62. data/spec/index/categorical_index_spec.rb +33 -33
  63. data/spec/index/index_spec.rb +134 -41
  64. data/spec/index/multi_index_spec.rb +115 -31
  65. data/spec/io/io_spec.rb +201 -0
  66. data/spec/io/sql_data_source_spec.rb +31 -41
  67. data/spec/iruby/dataframe_spec.rb +17 -19
  68. data/spec/iruby/vector_spec.rb +26 -28
  69. data/spec/maths/statistics/vector_spec.rb +136 -14
  70. data/spec/plotting/gruff/category_spec.rb +3 -3
  71. data/spec/plotting/gruff/dataframe_spec.rb +14 -4
  72. data/spec/plotting/gruff/vector_spec.rb +9 -9
  73. data/spec/plotting/nyaplot/category_spec.rb +5 -9
  74. data/spec/plotting/nyaplot/dataframe_spec.rb +72 -47
  75. data/spec/plotting/nyaplot/vector_spec.rb +5 -11
  76. data/spec/shared/vector_display_spec.rb +12 -14
  77. data/spec/spec_helper.rb +21 -0
  78. data/spec/support/matchers.rb +5 -0
  79. data/spec/vector_spec.rb +222 -72
  80. metadata +68 -23
  81. data/spec/fixtures/stock_data.csv +0 -500
@@ -105,4 +105,33 @@ describe Daru::Formatters::Table do
105
105
  }.unindent}
106
106
  end
107
107
  end
108
+
109
+ context 'no row and column headers' do
110
+ let(:headers) { nil }
111
+ let(:row_headers) { nil }
112
+ it { is_expected.to eq %Q{
113
+ | 1 2 3
114
+ | 4 5 6
115
+ | 7 8 9
116
+ }.unindent }
117
+ end
118
+
119
+ context 'row headers only' do
120
+ let(:headers) { nil }
121
+ it { is_expected.to eq %Q{
122
+ | row1 1 2 3
123
+ | row2 4 5 6
124
+ | row3 7 8 9
125
+ }.unindent }
126
+ end
127
+
128
+ context 'column headers only' do
129
+ let(:row_headers) { nil }
130
+ it { is_expected.to eq %Q{
131
+ | col1 col2 col3
132
+ | 1 2 3
133
+ | 4 5 6
134
+ | 7 8 9
135
+ }.unindent }
136
+ end
108
137
  end
@@ -7,13 +7,13 @@ describe Daru::CategoricalIndex do
7
7
 
8
8
  context "single category" do
9
9
  subject { idx.pos :a }
10
-
10
+
11
11
  it { is_expected.to eq [0, 2, 3] }
12
12
  end
13
-
13
+
14
14
  context "multiple categories" do
15
15
  subject { idx.pos :a, :c }
16
-
16
+
17
17
  it { is_expected.to eq [0, 2, 3, 4] }
18
18
  end
19
19
 
@@ -56,23 +56,23 @@ describe Daru::CategoricalIndex do
56
56
  end
57
57
  end
58
58
  end
59
-
59
+
60
60
  context "#subset" do
61
61
  let(:idx) { described_class.new [:a, 1, :a, 1, :c] }
62
-
62
+
63
63
  context "single index" do
64
64
  context "multiple instances" do
65
65
  subject { idx.subset :a }
66
-
66
+
67
67
  it { is_expected.to be_a described_class }
68
68
  its(:size) { is_expected.to eq 2 }
69
69
  its(:to_a) { is_expected.to eq [:a, :a] }
70
70
  end
71
71
  end
72
-
72
+
73
73
  context "multiple indexes" do
74
74
  subject { idx.subset :a, 1 }
75
-
75
+
76
76
  it { is_expected.to be_a described_class }
77
77
  its(:size) { is_expected.to eq 4 }
78
78
  its(:to_a) { is_expected.to eq [:a, 1, :a, 1] }
@@ -80,79 +80,79 @@ describe Daru::CategoricalIndex do
80
80
 
81
81
  context "multiple positional indexes" do
82
82
  subject { idx.subset 0, 2 }
83
-
83
+
84
84
  it { is_expected.to be_a described_class }
85
85
  its(:size) { is_expected.to eq 2 }
86
86
  its(:to_a) { is_expected.to eq [:a, :a] }
87
87
  end
88
88
  end
89
-
89
+
90
90
  context "#at" do
91
91
  let(:idx) { described_class.new [:a, :a, :a, 1, :c] }
92
-
92
+
93
93
  context "single position" do
94
94
  it { expect(idx.at 1).to eq :a }
95
95
  end
96
-
96
+
97
97
  context "multiple positions" do
98
98
  subject { idx.at 0, 2, 3 }
99
-
99
+
100
100
  it { is_expected.to be_a described_class }
101
101
  its(:size) { is_expected.to eq 3 }
102
102
  its(:to_a) { is_expected.to eq [:a, :a, 1] }
103
103
  end
104
-
104
+
105
105
  context "range" do
106
106
  subject { idx.at 2..3 }
107
-
107
+
108
108
  it { is_expected.to be_a described_class }
109
109
  its(:size) { is_expected.to eq 2 }
110
- its(:to_a) { is_expected.to eq [:a, 1] }
110
+ its(:to_a) { is_expected.to eq [:a, 1] }
111
111
  end
112
-
112
+
113
113
  context "range with negative integers" do
114
114
  subject { idx.at 2..-2 }
115
-
115
+
116
116
  it { is_expected.to be_a described_class }
117
117
  its(:size) { is_expected.to eq 2 }
118
- its(:to_a) { is_expected.to eq [:a, 1] }
119
- end
120
-
118
+ its(:to_a) { is_expected.to eq [:a, 1] }
119
+ end
120
+
121
121
  context "rangle with single element" do
122
122
  subject { idx.at 2..2 }
123
-
123
+
124
124
  it { is_expected.to be_a described_class }
125
125
  its(:size) { is_expected.to eq 1 }
126
- its(:to_a) { is_expected.to eq [:a] }
126
+ its(:to_a) { is_expected.to eq [:a] }
127
127
  end
128
-
128
+
129
129
  context "invalid position" do
130
130
  it { expect { idx.at 5 }.to raise_error IndexError }
131
131
  end
132
-
132
+
133
133
  context "invalid positions" do
134
134
  it { expect { idx.at 2, 5 }.to raise_error IndexError }
135
- end
135
+ end
136
136
  end
137
-
137
+
138
138
  context "#add" do
139
139
  let(:idx) { described_class.new [:a, 1, :a, 1] }
140
-
140
+
141
141
  context "single index" do
142
142
  subject { idx.add :c }
143
-
143
+
144
144
  its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
145
145
  its(:categories) { is_expected.to eq [:a, 1, :c] }
146
146
  end
147
-
147
+
148
148
  context "multiple indexes" do
149
149
  subject { idx.add :c, :d }
150
-
150
+
151
151
  its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c, :d] }
152
152
  its(:categories) { is_expected.to eq [:a, 1, :c, :d] }
153
153
  end
154
154
  end
155
-
155
+
156
156
  context "#valid?" do
157
157
  let(:idx) { described_class.new [:a, 1, :a, 1] }
158
158
 
@@ -161,7 +161,7 @@ describe Daru::CategoricalIndex do
161
161
  it { expect(idx.valid? 2).to eq true }
162
162
  it { expect(idx.valid? 4).to eq false }
163
163
  end
164
-
164
+
165
165
  context "multiple indexes" do
166
166
  it { expect(idx.valid? :a, 1).to eq true }
167
167
  it { expect(idx.valid? :a, 1, 5).to eq false }
@@ -28,6 +28,25 @@ describe Daru::Index do
28
28
  expect(i.to_a).to eq([DateTime.new(2012,2,4), DateTime.new(2012,2,5), DateTime.new(2012,2,6)])
29
29
  expect(i.frequency).to eq('D')
30
30
  end
31
+
32
+ context "create an Index with name" do
33
+ context 'if no name is set' do
34
+ subject { Daru::Index.new [:a, :b, :c] }
35
+ its(:name) { is_expected.to be_nil }
36
+ end
37
+
38
+ context 'correctly return the index name' do
39
+ subject { Daru::Index.new [:a, :b, :c], name: 'index_name' }
40
+ its(:name) { is_expected.to eq 'index_name' }
41
+ end
42
+
43
+ context "set new index name" do
44
+ subject {
45
+ Daru::Index.new([:a, :b, :c], name: 'index_name') }
46
+ before { subject.name = 'new_name'}
47
+ its(:name) { is_expected.to eq 'new_name' }
48
+ end
49
+ end
31
50
  end
32
51
 
33
52
  context "#initialize" do
@@ -70,6 +89,25 @@ describe Daru::Index do
70
89
  end
71
90
  end
72
91
 
92
+ context '#sort' do
93
+ let(:asc) { index.sort }
94
+ let(:desc) { index.sort(ascending: false) }
95
+
96
+ context 'string index' do
97
+ let(:index) { Daru::Index.new ['mic', 'amp', 'guitar', 'speaker'] }
98
+ specify { expect(asc).to eq Daru::Index.new ['amp', 'guitar', 'mic',
99
+ 'speaker'] }
100
+ specify { expect(desc).to eq Daru::Index.new ['speaker', 'mic', 'guitar',
101
+ 'amp'] }
102
+ end
103
+
104
+ context 'number index' do
105
+ let(:index) { Daru::Index.new [100, 99, 101, 1, 2] }
106
+ specify { expect(asc).to eq Daru::Index.new [1, 2, 99, 100, 101] }
107
+ specify { expect(desc).to eq Daru::Index.new [101, 100, 99, 2, 1] }
108
+ end
109
+ end
110
+
73
111
  context "#size" do
74
112
  it "correctly returns the size of the index" do
75
113
  idx = Daru::Index.new ['speaker', 'mic', 'guitar', 'amp']
@@ -77,15 +115,15 @@ describe Daru::Index do
77
115
  expect(idx.size).to eq(4)
78
116
  end
79
117
  end
80
-
118
+
81
119
  context "#valid?" do
82
120
  let(:idx) { Daru::Index.new [:a, :b, :c] }
83
-
121
+
84
122
  context "single index" do
85
123
  it { expect(idx.valid? 2).to eq true }
86
124
  it { expect(idx.valid? :d).to eq false }
87
125
  end
88
-
126
+
89
127
  context "multiple indexes" do
90
128
  it { expect(idx.valid? :a, 1).to eq true }
91
129
  it { expect(idx.valid? :a, 3).to eq false }
@@ -102,6 +140,11 @@ describe Daru::Index do
102
140
  subject { Daru::Index.new ('a'..'z').to_a }
103
141
  its(:inspect) { is_expected.to eq "#<Daru::Index(26): {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ... z}>" }
104
142
  end
143
+
144
+ context 'index with name' do
145
+ subject { Daru::Index.new ['one', 'two', 'three'], name: 'number' }
146
+ its(:inspect) { is_expected.to eq "#<Daru::Index(3): number {one, two, three}>" }
147
+ end
105
148
  end
106
149
 
107
150
  context "#&" do
@@ -142,25 +185,25 @@ describe Daru::Index do
142
185
  end
143
186
 
144
187
  it "works with ranges" do
145
- expect(@id[:two..:five]).to eq(Daru::Index.new([:two, :three, :four, :five]))
188
+ expect(@id[:two..:five]).to eq([1, 2, 3, 4])
146
189
 
147
- expect(@mixed_id['a'..'c']).to eq(Daru::Index.new(['a','b','c']))
190
+ expect(@mixed_id['a'..'c']).to eq([0, 1, 2])
148
191
 
149
- # If both start and end are numbers then refer to numerical indexes
150
- expect(@mixed_id[0..2]).to eq(Daru::Index.new(['a','b','c']))
192
+ # returns nil if first index is invalid
193
+ expect(@mixed_id.slice('d', 5)).to be_nil
151
194
 
152
- # If atleast one is a number then refer to actual indexing
153
- expect(@mixed_id.slice('b',8)).to eq(Daru::Index.new(['b','c',:d,:a,8]))
195
+ # returns positions till the end if first index is present
196
+ expect(@mixed_id.slice('c', 6)).to eq([2, 3, 4, 5, 6, 7])
154
197
  end
155
198
 
156
199
  it "returns multiple keys if specified multiple indices" do
157
- expect(@id[0,1,3,4]).to eq(Daru::Index.new([:one, :two, :four, :five]))
158
- expect(@mixed_id[0,5,3,2]).to eq(Daru::Index.new(['a', 8, :d, 'c']))
200
+ expect(@id[:one, :two, :four, :five]).to eq([0, 1, 3, 4])
201
+ expect(@mixed_id[0,5,3,2]).to eq([nil, 7, 6, nil])
159
202
  end
160
203
 
161
- it "returns correct index position for non-numeric index" do
204
+ it "returns nil for invalid indexes" do
162
205
  expect(@id[:four]).to eq(3)
163
- expect(@id[3]).to eq(3)
206
+ expect(@id[3]).to be_nil
164
207
  end
165
208
 
166
209
  it "returns correct index position for mixed index" do
@@ -171,14 +214,14 @@ describe Daru::Index do
171
214
 
172
215
  context "#pos" do
173
216
  let(:idx) { described_class.new [:a, :b, 1, 2] }
174
-
217
+
175
218
  context "single index" do
176
219
  it { expect(idx.pos :a).to eq 0 }
177
220
  end
178
-
221
+
179
222
  context "multiple indexes" do
180
223
  subject { idx.pos :a, 1 }
181
-
224
+
182
225
  it { is_expected.to be_a Array }
183
226
  its(:size) { is_expected.to eq 2 }
184
227
  it { is_expected.to eq [0, 2] }
@@ -187,10 +230,10 @@ describe Daru::Index do
187
230
  context "single positional index" do
188
231
  it { expect(idx.pos 0).to eq 0 }
189
232
  end
190
-
233
+
191
234
  context "multiple positional index" do
192
235
  subject { idx.pos 0, 3 }
193
-
236
+
194
237
  it { is_expected.to be_a Array }
195
238
  its(:size) { is_expected.to eq 2 }
196
239
  it { is_expected.to eq [0, 3] }
@@ -204,78 +247,78 @@ describe Daru::Index do
204
247
  it { is_expected.to eq [1, 2, 3] }
205
248
  end
206
249
  end
207
-
250
+
208
251
  context "#subset" do
209
252
  let(:idx) { described_class.new [:a, :b, 1, 2] }
210
-
253
+
211
254
  context "multiple indexes" do
212
255
  subject { idx.subset :a, 1 }
213
-
256
+
214
257
  it { is_expected.to be_a described_class }
215
258
  its(:size) { is_expected.to eq 2 }
216
259
  its(:to_a) { is_expected.to eq [:a, 1] }
217
260
  end
218
-
261
+
219
262
  context "multiple positional indexes" do
220
263
  subject { idx.subset 0, 3 }
221
-
264
+
222
265
  it { is_expected.to be_a described_class }
223
266
  its(:size) { is_expected.to eq 2 }
224
267
  its(:to_a) { is_expected.to eq [:a, 2] }
225
268
  end
226
-
269
+
227
270
  context "range" do
228
271
  subject { idx.subset 1..3 }
229
-
272
+
230
273
  it { is_expected.to be_a described_class }
231
274
  its(:size) { is_expected.to eq 3 }
232
275
  its(:to_a) { is_expected.to eq [:b, 1, 2] }
233
276
  end
234
277
  end
235
-
278
+
236
279
  context "#at" do
237
280
  let(:idx) { described_class.new [:a, :b, 1 ] }
238
-
281
+
239
282
  context "single position" do
240
283
  it { expect(idx.at 1).to eq :b }
241
284
  end
242
-
285
+
243
286
  context "multiple positions" do
244
287
  subject { idx.at 1, 2 }
245
-
288
+
246
289
  it { is_expected.to be_a described_class }
247
290
  its(:size) { is_expected.to eq 2 }
248
291
  its(:to_a) { is_expected.to eq [:b, 1] }
249
292
  end
250
-
293
+
251
294
  context "range" do
252
295
  subject { idx.at 1..2 }
253
-
296
+
254
297
  it { is_expected.to be_a described_class }
255
298
  its(:size) { is_expected.to eq 2 }
256
- its(:to_a) { is_expected.to eq [:b, 1] }
299
+ its(:to_a) { is_expected.to eq [:b, 1] }
257
300
  end
258
-
301
+
259
302
  context "range with negative integer" do
260
303
  subject { idx.at 1..-1 }
261
-
304
+
262
305
  it { is_expected.to be_a described_class }
263
306
  its(:size) { is_expected.to eq 2 }
264
- its(:to_a) { is_expected.to eq [:b, 1] }
265
- end
266
-
307
+ its(:to_a) { is_expected.to eq [:b, 1] }
308
+ end
309
+
267
310
  context "rangle with single element" do
268
311
  subject { idx.at 1..1 }
269
-
312
+
270
313
  it { is_expected.to be_a described_class }
271
314
  its(:size) { is_expected.to eq 1 }
272
- its(:to_a) { is_expected.to eq [:b] }
315
+ its(:to_a) { is_expected.to eq [:b] }
273
316
  end
274
-
317
+
275
318
  context "invalid position" do
276
319
  it { expect { idx.at 3 }.to raise_error IndexError }
277
320
  end
278
-
321
+
279
322
  context "invalid positions" do
280
323
  it { expect { idx.at 2, 3 }.to raise_error IndexError }
281
324
  end
@@ -295,4 +338,54 @@ describe Daru::Index do
295
338
  it { expect(idx.select {|w| w[0] == 'g' }).to eq(['guitar']) }
296
339
  end
297
340
  end
341
+
342
+ context "#is_values" do
343
+ let(:klass) { Daru::Vector }
344
+ let(:idx) { described_class.new [:one, 'one', 1, 2, 'two', nil, [1, 2]] }
345
+
346
+ context "no arguments" do
347
+ let(:answer) { [false, false, false, false, false, false, false] }
348
+ it { expect(idx.is_values).to eq klass.new(answer) }
349
+ end
350
+
351
+ context "single arguments" do
352
+ let(:answer) { [false, true, false, false, false, false, false] }
353
+ it { expect(idx.is_values 'one').to eq klass.new(answer) }
354
+ end
355
+
356
+ context "multiple arguments" do
357
+ context "symbol and number as argument" do
358
+ subject { idx.is_values 2, :one }
359
+ let(:answer) { [true, false, false, true, false, false, false] }
360
+ it { is_expected.to be_a Daru::Vector }
361
+ its(:size) { is_expected.to eq 7 }
362
+ it { is_expected.to eq klass.new(answer) }
363
+ end
364
+
365
+ context "string and number as argument" do
366
+ subject { idx.is_values('one', 1)}
367
+ let(:answer) { [false, true, true, false, false, false, false] }
368
+ it { is_expected.to be_a Daru::Vector }
369
+ its(:size) { is_expected.to eq 7 }
370
+ it { is_expected.to eq klass.new(answer) }
371
+ end
372
+
373
+ context "nil is present in arguments" do
374
+ subject { idx.is_values('two', nil)}
375
+ let(:answer) { [false, false, false, false, true, true, false] }
376
+ it { is_expected.to be_a Daru::Vector }
377
+ its(:size) { is_expected.to eq 7 }
378
+ it { is_expected.to eq klass.new(answer) }
379
+ end
380
+
381
+ context "subarray is present in arguments" do
382
+ subject { idx.is_values([1, 2])}
383
+ let(:answer) { [false, false, false, false, false, false, true] }
384
+ it { is_expected.to be_a Daru::Vector }
385
+ its(:size) { is_expected.to eq 7 }
386
+ it { is_expected.to eq klass.new(answer) }
387
+ end
388
+ end
389
+
390
+ end
298
391
  end