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.
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