daru 0.1.0 → 0.1.1

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.build.sh +6 -6
  3. data/.gitignore +2 -0
  4. data/CONTRIBUTING.md +7 -3
  5. data/History.md +36 -0
  6. data/README.md +21 -13
  7. data/Rakefile +16 -1
  8. data/benchmarks/TradeoffData.csv +65 -0
  9. data/benchmarks/dataframe_creation.rb +39 -0
  10. data/benchmarks/group_by.rb +32 -0
  11. data/benchmarks/row_access.rb +41 -0
  12. data/benchmarks/row_assign.rb +36 -0
  13. data/benchmarks/sorting.rb +44 -0
  14. data/benchmarks/vector_access.rb +31 -0
  15. data/benchmarks/vector_assign.rb +42 -0
  16. data/benchmarks/where_clause.rb +48 -0
  17. data/benchmarks/where_vs_filter.rb +28 -0
  18. data/daru.gemspec +29 -5
  19. data/lib/daru.rb +30 -1
  20. data/lib/daru/accessors/array_wrapper.rb +2 -2
  21. data/lib/daru/accessors/nmatrix_wrapper.rb +6 -6
  22. data/lib/daru/core/group_by.rb +112 -31
  23. data/lib/daru/core/merge.rb +170 -0
  24. data/lib/daru/core/query.rb +95 -0
  25. data/lib/daru/dataframe.rb +335 -223
  26. data/lib/daru/date_time/index.rb +550 -0
  27. data/lib/daru/date_time/offsets.rb +397 -0
  28. data/lib/daru/index.rb +266 -54
  29. data/lib/daru/io/io.rb +1 -2
  30. data/lib/daru/maths/arithmetic/dataframe.rb +2 -2
  31. data/lib/daru/maths/arithmetic/vector.rb +2 -2
  32. data/lib/daru/maths/statistics/dataframe.rb +58 -8
  33. data/lib/daru/maths/statistics/vector.rb +229 -0
  34. data/lib/daru/vector.rb +230 -80
  35. data/lib/daru/version.rb +1 -1
  36. data/spec/core/group_by_spec.rb +16 -16
  37. data/spec/core/merge_spec.rb +52 -0
  38. data/spec/core/query_spec.rb +171 -0
  39. data/spec/dataframe_spec.rb +278 -280
  40. data/spec/date_time/data_spec.rb +199 -0
  41. data/spec/date_time/index_spec.rb +433 -0
  42. data/spec/date_time/offsets_spec.rb +371 -0
  43. data/spec/fixtures/stock_data.csv +500 -0
  44. data/spec/index_spec.rb +317 -11
  45. data/spec/io/io_spec.rb +18 -17
  46. data/spec/math/arithmetic/dataframe_spec.rb +3 -3
  47. data/spec/math/statistics/dataframe_spec.rb +39 -1
  48. data/spec/math/statistics/vector_spec.rb +163 -1
  49. data/spec/monkeys_spec.rb +4 -0
  50. data/spec/spec_helper.rb +3 -0
  51. data/spec/vector_spec.rb +125 -60
  52. metadata +71 -14
  53. data/lib/daru/accessors/dataframe_by_vector.rb +0 -17
  54. data/lib/daru/multi_index.rb +0 -216
  55. data/spec/multi_index_spec.rb +0 -216
@@ -49,7 +49,15 @@ describe Daru::DataFrame do
49
49
  end
50
50
 
51
51
  context "#max" do
52
- # TODO
52
+ it "returns the row that has max" do
53
+ df = Daru::DataFrame.new({
54
+ a: [1,2,3,4,5],
55
+ b: ['aa','aaa','a','','dfffdf'],
56
+ c: [11,22,33,44,55]
57
+ })
58
+ expect(df.max(vector: :b)).to eq(
59
+ Daru::Vector.new([5,'dfffdf',55], index: [:a, :b, :c]))
60
+ end
53
61
  end
54
62
 
55
63
  context "#min" do
@@ -107,4 +115,34 @@ describe Daru::DataFrame do
107
115
  ))
108
116
  end
109
117
  end
118
+
119
+ context "#cumsum" do
120
+ it "calculates cumulative sum of numeric vectors" do
121
+ answer = Daru::DataFrame.new({
122
+ d: [1,3,5,8,11,15,20,26,33],
123
+ e: [2,6,10,16,22,30,40,52,66],
124
+ f: [10,30,50,80,110,150,200,260,330]
125
+ })
126
+ expect(@df.cumsum).to eq(answer)
127
+ end
128
+ end
129
+
130
+ context "#rolling_mean" do
131
+ it "calculates rolling mean" do
132
+ v = Daru::Vector.new([17.28, 17.45, 17.84, 17.74, 17.82, 17.85, 17.36, 17.3, 17.56, 17.49, 17.46, 17.4, 17.03, 17.01,16.86, 16.86, 16.56, 16.36, 16.66, 16.77])
133
+ df = Daru::DataFrame.new({ a: v, b: v, c: v })
134
+ answer = df.rolling_mean
135
+
136
+ expect(answer[:a][-1]) .to be_within(0.001).of(16.897)
137
+ expect(answer[:b][-5]) .to be_within(0.001).of(17.233)
138
+ expect(answer[:c][-10]).to be_within(0.001).of(17.587)
139
+ end
140
+ end
141
+
142
+ context "#standardize" do
143
+ it "standardizes" do
144
+ # TODO: Write this test.
145
+ @df.standardize
146
+ end
147
+ end
110
148
  end
@@ -111,6 +111,16 @@ describe Daru::Vector do
111
111
  end
112
112
  end
113
113
 
114
+ context "#value_counts" do
115
+ it "counts number of unique values in the Vector" do
116
+ vector = Daru::Vector.new(
117
+ ["America","America","America","America","America",
118
+ "India","India", "China", "India", "China"])
119
+ expect(vector.value_counts).to eq(
120
+ Daru::Vector.new([5,3,2], index: ["America", "India", "China"]))
121
+ end
122
+ end
123
+
114
124
  context "#coefficient_of_variation" do
115
125
  it "calculates coefficient_of_variation" do
116
126
  @dv.coefficient_of_variation
@@ -344,4 +354,156 @@ describe Daru::Vector do
344
354
  expect_correct_vector_in_delta(exp, ds[:mean], 1e-13)
345
355
  end
346
356
  end
347
- end
357
+
358
+ before do
359
+ # daily closes of iShares XIU on the TSX
360
+ @shares = Daru::Vector.new([17.28, 17.45, 17.84, 17.74, 17.82, 17.85, 17.36, 17.3, 17.56, 17.49, 17.46, 17.4, 17.03, 17.01,16.86, 16.86, 16.56, 16.36, 16.66, 16.77])
361
+ end
362
+
363
+ context "#acf" do
364
+ it "calculates autocorrelation co-efficients" do
365
+ acf = @shares.acf
366
+
367
+ expect(acf.length).to eq(14)
368
+
369
+ # test the first few autocorrelations
370
+ expect(acf[0]).to be_within(0.0001).of(1.0)
371
+ expect(acf[1]).to be_within(0.001) .of(0.852)
372
+ expect(acf[2]).to be_within(0.001) .of(0.669)
373
+ expect(acf[3]).to be_within(0.001) .of(0.486)
374
+ end
375
+ end
376
+
377
+ context "#diff" do
378
+ it "performs the difference of the series" do
379
+ diff = @shares.diff
380
+
381
+ expect(diff.class).to eq(Daru::Vector)
382
+ expect(diff[@shares.size - 1]).to be_within(0.001).of( 0.11)
383
+ expect(diff[@shares.size - 2]).to be_within(0.001).of( 0.30)
384
+ expect(diff[@shares.size - 3]).to be_within(0.001).of(-0.20)
385
+ end
386
+ end
387
+
388
+ context "#rolling" do
389
+ it "calculates rolling mean" do
390
+ ma10 = @shares.rolling_mean
391
+
392
+ expect(ma10[-1]) .to be_within(0.001).of(16.897)
393
+ expect(ma10[-5]) .to be_within(0.001).of(17.233)
394
+ expect(ma10[-10]).to be_within(0.001).of(17.587)
395
+
396
+ # test with a different lookback period
397
+ ma5 = @shares.rolling :mean, 5
398
+
399
+ expect(ma5[-1]).to be_within(0.001).of(16.642)
400
+ expect(ma5[-10]).to be_within(0.001).of(17.434)
401
+ expect(ma5[-15]).to be_within(0.001).of(17.74)
402
+ end
403
+
404
+ it "calculates rolling median" do
405
+ me10 = @shares.rolling_median.round(2)
406
+ expect(me10).to eq(Daru::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,17.525,17.525,17.525,17.475,17.430,17.380,17.330,17.165,17.020,16.94,16.860]).round(2))
407
+
408
+ me5 = @shares.rolling(:median, 5).round(2)
409
+ expect(me5).to eq(Daru::Vector.new([nil,nil,nil,nil,17.74,17.82,17.82,17.74,17.56,17.49,17.46,17.46,17.46,17.40,17.03,17.01,16.86,16.86,16.66,16.66]))
410
+ end
411
+
412
+ it "calculates rolling max" do
413
+ max10 = @shares.rolling_max.round(2)
414
+ expect(max10).to eq(Daru::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,17.85,17.85,17.85,17.85,17.85,17.85,17.56,17.56,17.56,17.49,17.46]))
415
+
416
+ max5 = @shares.rolling(:max, 5).round(2)
417
+ expect(max5).to eq(Daru::Vector.new([nil, nil, nil, nil,17.84,17.85,17.85,17.85,17.85,17.85,17.56,17.56,17.56,17.49,17.46,17.40,17.03,17.01,16.86,16.86]))
418
+ end
419
+
420
+ it "calculates rolling min" do
421
+ min10 = @shares.rolling_min.round(2)
422
+ expect(min10).to eq(Daru::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,17.28,17.30,17.30,17.03,17.01,16.86,16.86,16.56,16.36,16.36,16.36]))
423
+
424
+ min5 = @shares.rolling(:min, 5).round(2)
425
+ expect(min5).to eq(Daru::Vector.new([nil,nil,nil,nil,17.28,17.45,17.36,17.30,17.30,17.30,17.30,17.30,17.03,17.01,16.86,16.86,16.56,16.36,16.36,16.36]))
426
+ end
427
+
428
+ it "calculates rolling sum" do
429
+ sum10 = @shares.rolling_sum.round(2)
430
+ expect(sum10).to eq(Daru::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,175.69,175.87,175.82,175.01,174.28,173.32,172.33,171.53,170.59,169.69,168.97]))
431
+
432
+ sum5 = @shares.rolling(:sum, 5).round(2)
433
+ expect(sum5).to eq(Daru::Vector.new([nil,nil,nil,nil,88.13,88.70,88.61,88.07,87.89,87.56,87.17,87.21,86.94,86.39,85.76,85.16,84.32,83.65,83.30,83.21]))
434
+ end
435
+
436
+ it "calculates rolling std" do
437
+ std10 = @shares.rolling_std.round(2)
438
+ expect(std10).to eq(Daru::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,0.227227,0.208116,0.212331,0.253485,0.280666,0.295477,0.267127,0.335826,0.412834,0.388886,0.345995]).round(2))
439
+
440
+ std5 = @shares.rolling(:std, 5).round(2)
441
+ expect(std5).to eq(Daru::Vector.new([nil,nil,nil,nil,0.248556,0.167780,0.206930,0.263211,0.253811,0.215105,0.103827,0.098082,0.208255,0.237844,0.263002,0.220839,0.187963,0.263629,0.212132,0.193959]).round(2))
442
+ end
443
+
444
+ it "calculates rolling variance" do
445
+ var10 = @shares.rolling_variance.round(2)
446
+ expect(var10).to eq(Daru::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,0.051632,0.043312,0.045084,0.064254,0.078773,0.087307,0.071357,0.112779,0.170432,0.151232,0.119712]).round(2))
447
+
448
+ var5 = @shares.rolling(:variance, 5).round(2)
449
+ expect(var5).to eq(Daru::Vector.new([nil,nil,nil,nil,0.06178,0.02815,0.04282,0.06928,0.06442,0.04627,0.01078,0.00962,0.04337,0.05657,0.06917,0.04877,0.03533,0.06950,0.04500,0.03762]).round(2))
450
+ end
451
+
452
+ it "calculates rolling non-nil count" do
453
+ @shares.rolling_count
454
+ end
455
+ end
456
+
457
+ context "#ema" do
458
+ it "calculates exponential moving average" do
459
+ # test default
460
+ ema10 = @shares.ema
461
+
462
+ expect(ema10[-1]) .to be_within(0.00001).of( 16.87187)
463
+ expect(ema10[-5]) .to be_within(0.00001).of( 17.19187)
464
+ expect(ema10[-10]).to be_within(0.00001).of( 17.54918)
465
+
466
+ # test with a different lookback period
467
+ ema5 = @shares.ema 5
468
+
469
+ expect(ema5[-1]) .to be_within( 0.0001).of(16.71299)
470
+ expect(ema5[-10]).to be_within( 0.0001).of(17.49079)
471
+ expect(ema5[-15]).to be_within( 0.0001).of(17.70067)
472
+
473
+ # test with a different smoother
474
+ ema_w = @shares.ema 10, true
475
+
476
+ expect(ema_w[-1]) .to be_within(0.00001).of(17.08044)
477
+ expect(ema_w[-5]) .to be_within(0.00001).of(17.33219)
478
+ expect(ema_w[-10]).to be_within(0.00001).of(17.55810)
479
+ end
480
+ end
481
+
482
+ context "#macd" do
483
+ it "calculates moving average convergence divergence" do
484
+ # MACD uses a lot more data than the other ones, so we need a bigger vector
485
+ data = Daru::Vector.new(
486
+ File.readlines("spec/fixtures/stock_data.csv").map(&:to_f))
487
+
488
+ macd, signal = data.macd
489
+
490
+ # check the MACD
491
+ expect(macd[-1]).to be_within(1e-6).of(3.12e-4)
492
+ expect(macd[-10]).to be_within(1e-4).of(-1.07e-2)
493
+ expect(macd[-20]).to be_within(1e-5).of(-5.65e-3)
494
+
495
+ # check the signal
496
+ expect(signal[-1]).to be_within(1e-5).of(-0.00628)
497
+ expect(signal[-10]).to be_within(1e-5).of(-0.00971)
498
+ expect(signal[-20]).to be_within(1e-5).of(-0.00338)
499
+ end
500
+ end
501
+
502
+ context "#cumsum" do
503
+ it "calculates cumulative sum" do
504
+ vector = Daru::Vector.new([1,2,3,4,5,6,7,8,9,10])
505
+ expect(vector.cumsum).to eq(
506
+ Daru::Vector.new([1,3,6,10,15,21,28,36,45,55]))
507
+ end
508
+ end
509
+ end
@@ -2,6 +2,10 @@ require 'spec_helper.rb'
2
2
 
3
3
  describe "Monkeys" do
4
4
  context Array do
5
+ it "#recode_repeated" do
6
+ expect([1,1,'a','a','b',:c,2].recode_repeated).to eq(
7
+ ['1_1', '1_2','a_1','a_2','b',:c,2])
8
+ end
5
9
  end
6
10
 
7
11
  context Matrix do
@@ -3,6 +3,7 @@ require 'matrix'
3
3
  require 'awesome_print'
4
4
  require 'distribution'
5
5
  require 'tempfile'
6
+ require 'pry-byebug'
6
7
 
7
8
  def mri?
8
9
  RUBY_ENGINE == 'ruby'
@@ -18,6 +19,8 @@ else
18
19
  require 'nmatrix'
19
20
  end
20
21
 
22
+ RSpec::Expectations.configuration.warn_about_potential_false_positives = false
23
+
21
24
 
22
25
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
23
26
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -18,7 +18,7 @@ describe Daru::Vector do
18
18
  [:b, :two, :baz]
19
19
  ]
20
20
 
21
- @multi_index = Daru::MultiIndex.new(@tuples)
21
+ @multi_index = Daru::MultiIndex.from_tuples(@tuples)
22
22
  end
23
23
 
24
24
  it "initializes from an Array" do
@@ -77,6 +77,12 @@ describe Daru::Vector do
77
77
  dv = Daru::Vector.new [1,2], name: :mi, index: @multi_index, dtype: :array
78
78
  expect(dv).to eq(Daru::Vector.new([1,2,nil,nil], name: :mi, index: @multi_index, dtype: :array))
79
79
  end
80
+
81
+ it "accepts all sorts of objects for indexing" do
82
+ dv = Daru::Vector.new [1,2,3,4], index: ['a', 'b', :r, 0]
83
+ expect(dv.to_a).to eq([1,2,3,4])
84
+ expect(dv.index.to_a).to eq(['a', 'b', :r, 0])
85
+ end
80
86
  end
81
87
 
82
88
  context ".new_with_size" do
@@ -147,6 +153,14 @@ describe Daru::Vector do
147
153
  expect(@dv[3..4]).to eq(Daru::Vector.new([4,5], name: :yoga,
148
154
  index: [:padme, :r2d2], dtype: dtype))
149
155
  end
156
+
157
+ it "returns correct results for index of multiple index" do
158
+ v = Daru::Vector.new([1,2,3,4], index: ['a','c',1,:a])
159
+ expect(v['a']).to eq(1)
160
+ expect(v[:a]).to eq(4)
161
+ expect(v[1]).to eq(3)
162
+ expect(v[0]).to eq(1)
163
+ end
150
164
  end
151
165
 
152
166
  context Daru::MultiIndex do
@@ -165,9 +179,10 @@ describe Daru::Vector do
165
179
  [:c,:two,:foo],
166
180
  [:c,:two,:bar]
167
181
  ]
168
- @multi_index = Daru::MultiIndex.new(@tuples)
169
- @vector = Daru::Vector.new Array.new(12) { |i| i }, index: @multi_index,
170
- dtype: dtype, name: :mi_vector
182
+ @multi_index = Daru::MultiIndex.from_tuples(@tuples)
183
+ @vector = Daru::Vector.new(
184
+ Array.new(12) { |i| i }, index: @multi_index,
185
+ dtype: dtype, name: :mi_vector)
171
186
  end
172
187
 
173
188
  it "returns a single element when passed a row number" do
@@ -179,7 +194,7 @@ describe Daru::Vector do
179
194
  end
180
195
 
181
196
  it "returns sub vector when passed first layer of tuple" do
182
- mi = Daru::MultiIndex.new([
197
+ mi = Daru::MultiIndex.from_tuples([
183
198
  [:one,:bar],
184
199
  [:one,:baz],
185
200
  [:two,:bar],
@@ -189,7 +204,7 @@ describe Daru::Vector do
189
204
  end
190
205
 
191
206
  it "returns sub vector when passed first and second layer of tuple" do
192
- mi = Daru::MultiIndex.new([
207
+ mi = Daru::MultiIndex.from_tuples([
193
208
  [:foo],
194
209
  [:bar]])
195
210
  expect(@vector[:c,:two]).to eq(Daru::Vector.new([10,11], index: mi,
@@ -197,7 +212,7 @@ describe Daru::Vector do
197
212
  end
198
213
 
199
214
  it "returns a vector with corresponding MultiIndex when specified numeric Range" do
200
- mi = Daru::MultiIndex.new([
215
+ mi = Daru::MultiIndex.from_tuples([
201
216
  [:a,:two,:baz],
202
217
  [:b,:one,:bar],
203
218
  [:b,:two,:bar],
@@ -233,6 +248,21 @@ describe Daru::Vector do
233
248
  @dv[0] = nil
234
249
  expect(@dv.dtype).to eq(:array)
235
250
  end
251
+
252
+ it "assigns correctly for a mixed index Vector" do
253
+ v = Daru::Vector.new [1,2,3,4], index: ['a',:a,0,66]
254
+ v['a'] = 666
255
+ expect(v['a']).to eq(666)
256
+
257
+ v[0] = 666
258
+ expect(v[0]).to eq(666)
259
+
260
+ v[3] = 666
261
+ expect(v[3]).to eq(666)
262
+
263
+ expect(v).to eq(Daru::Vector.new([666,2,666,666],
264
+ index: ['a',:a,0,66]))
265
+ end
236
266
  end
237
267
 
238
268
  context Daru::MultiIndex do
@@ -251,7 +281,7 @@ describe Daru::Vector do
251
281
  [:c,:two,:foo],
252
282
  [:c,:two,:bar]
253
283
  ]
254
- @multi_index = Daru::MultiIndex.new(@tuples)
284
+ @multi_index = Daru::MultiIndex.from_tuples(@tuples)
255
285
  @vector = Daru::Vector.new Array.new(12) { |i| i }, index: @multi_index,
256
286
  dtype: dtype, name: :mi_vector
257
287
  end
@@ -293,21 +323,12 @@ describe Daru::Vector do
293
323
  @dv.concat 6, :ibanez
294
324
 
295
325
  expect(@dv.index) .to eq(
296
- [:warwick, :thompson, :jackson, :fender, :esp, :ibanez].to_index)
326
+ Daru::Index.new([:warwick, :thompson, :jackson, :fender, :esp, :ibanez]))
297
327
  expect(@dv[:ibanez]).to eq(6)
298
328
  expect(@dv[5]) .to eq(6)
299
329
  end
300
330
 
301
- it "concatenates without index if index is default numeric" do
302
- vector = Daru::Vector.new [1,2,3,4,5], name: :nums, dtype: dtype
303
-
304
- vector.concat 6
305
-
306
- expect(vector.index).to eq([0,1,2,3,4,5].to_index)
307
- expect(vector[5]) .to eq(6)
308
- end
309
-
310
- it "raises error if index not specified and non-numeric index" do
331
+ it "raises error if index not specified" do
311
332
  expect {
312
333
  @dv.concat 6
313
334
  }.to raise_error
@@ -320,13 +341,10 @@ describe Daru::Vector do
320
341
  dv = Daru::Vector.new [1,2,3,4,5], name: :a, dtype: dtype
321
342
 
322
343
  dv.delete 3
323
- expect(dv).to eq(Daru::Vector.new [1,2,4,5], name: :a)
344
+ expect(dv).to eq(
345
+ Daru::Vector.new [1,2,4,5], name: :a, index: [0,1,3,4])
324
346
  end
325
347
  end
326
-
327
- context Daru::MultiIndex do
328
- pending
329
- end
330
348
  end
331
349
 
332
350
  context "#delete_at" do
@@ -344,22 +362,19 @@ describe Daru::Vector do
344
362
  end
345
363
 
346
364
  it "deletes element of specified integer index" do
365
+ pending
347
366
  @dv.delete_at 2
348
367
 
349
368
  expect(@dv).to eq(Daru::Vector.new [1,2,4,5], name: :a,
350
369
  index: [:one, :two, :four, :five], dtype: dtype)
351
370
  end
352
371
  end
353
-
354
- context Daru::MultiIndex do
355
- pending "Possibly next release"
356
- end
357
372
  end
358
373
 
359
374
  context "#delete_if" do
360
375
  it "deletes elements if block evaluates to true" do
361
376
  v = Daru::Vector.new [1,22,33,45,65,32,524,656,123,99,77], dtype: dtype
362
- ret = v.delete_if { |d| d % 11 != 0 }
377
+ ret = v.delete_if { |d| d % 11 == 0 }
363
378
  expect(ret).to eq(
364
379
  Daru::Vector.new([1,45,65,32,524,656,123],
365
380
  index: [0,3,4,5,6,7,8], dtype: dtype))
@@ -367,6 +382,17 @@ describe Daru::Vector do
367
382
  end
368
383
  end
369
384
 
385
+ context "#keep_if" do
386
+ it "keeps elements if block returns true" do
387
+ v = Daru::Vector.new([1,22,33,45,65,32,524,656,123,99,77], dtype: dtype)
388
+ ret = v.keep_if { |d| d < 35 }
389
+
390
+ expect(ret).to eq(
391
+ Daru::Vector.new([1,22,33,32], index: [0,1,2,5], dtype: dtype))
392
+ expect(v.dtype).to eq(ret.dtype)
393
+ end
394
+ end
395
+
370
396
  context "#index_of" do
371
397
  context Daru::Index do
372
398
  it "returns index of specified value" do
@@ -379,7 +405,7 @@ describe Daru::Vector do
379
405
 
380
406
  context Daru::MultiIndex do
381
407
  it "returns tuple of specified value" do
382
- mi = Daru::MultiIndex.new([
408
+ mi = Daru::MultiIndex.from_tuples([
383
409
  [:a,:two,:bar],
384
410
  [:a,:two,:baz],
385
411
  [:b,:one,:bar],
@@ -405,7 +431,7 @@ describe Daru::Vector do
405
431
  pending
406
432
  # it "returns vector as a Hash" do
407
433
  # pending
408
- # mi = Daru::MultiIndex.new([
434
+ # mi = Daru::MultiIndex.from_tuples([
409
435
  # [:a,:two,:bar],
410
436
  # [:a,:two,:baz],
411
437
  # [:b,:one,:bar],
@@ -469,7 +495,7 @@ describe Daru::Vector do
469
495
 
470
496
  context Daru::MultiIndex do
471
497
  before do
472
- mi = Daru::MultiIndex.new([
498
+ mi = Daru::MultiIndex.from_tuples([
473
499
  [:a, :one, :foo],
474
500
  [:a, :two, :bar],
475
501
  [:b, :one, :bar],
@@ -481,7 +507,7 @@ describe Daru::Vector do
481
507
  end
482
508
 
483
509
  it "sorts vector" do
484
- mi_asc = Daru::MultiIndex.new([
510
+ mi_asc = Daru::MultiIndex.from_tuples([
485
511
  [:b, :three, :bar],
486
512
  [:b, :two, :baz],
487
513
  [:a, :two, :bar],
@@ -493,7 +519,7 @@ describe Daru::Vector do
493
519
  end
494
520
 
495
521
  it "sorts in descending" do
496
- mi_dsc = Daru::MultiIndex.new([
522
+ mi_dsc = Daru::MultiIndex.from_tuples([
497
523
  [:b, :one, :bar],
498
524
  [:a, :one, :foo],
499
525
  [:a, :two, :bar],
@@ -505,7 +531,7 @@ describe Daru::Vector do
505
531
  end
506
532
 
507
533
  it "sorts using the supplied block" do
508
- mi_abs = Daru::MultiIndex.new([
534
+ mi_abs = Daru::MultiIndex.from_tuples([
509
535
  [:b, :two, :baz],
510
536
  [:a, :two, :bar],
511
537
  [:a, :one, :foo],
@@ -518,29 +544,33 @@ describe Daru::Vector do
518
544
  end
519
545
  end
520
546
 
521
- context "#reindex" do
522
- context Daru::Index do
523
- before do
524
- @dv = Daru::Vector.new [1,2,3,4,5], name: :dv, index: [:a, :b, :c, :d, :e]
525
- end
526
-
527
- it "recreates index with sequential numbers" do
528
- a = @dv.reindex(:seq)
547
+ context "#index=" do
548
+ before do
549
+ @vector = Daru::Vector.new([1,2,3,4,5])
550
+ end
529
551
 
530
- expect(a).to eq(Daru::Vector.new([1,2,3,4,5], name: :dv, index: [0,1,2,3,4]))
531
- expect(a).to_not eq(@dv)
532
- end
552
+ it "simply reassigns index" do
553
+ index = Daru::DateTimeIndex.date_range(:start => '2012', :periods => 5)
554
+ @vector.index = index
533
555
 
534
- it "accepts a new non-numeric index" do
535
- a = @dv.reindex([:hello, :my, :name, :is, :ted])
556
+ expect(@vector.index.class).to eq(DateTimeIndex)
557
+ expect(@vector['2012-1-1']).to eq(1)
558
+ end
536
559
 
537
- expect(a).to eq(Daru::Vector.new([1,2,3,4,5], name: :dv, index: [:hello, :my, :name, :is, :ted]))
538
- expect(a).to_not eq(@dv)
539
- end
560
+ it "raises error for index size != vector size" do
561
+ expect {
562
+ @vector.index = Daru::Index.new([4,2,6])
563
+ }.to raise_error
540
564
  end
565
+ end
541
566
 
542
- context Daru::MultiIndex do
543
- pending
567
+ context "#reindex" do
568
+ it "intelligently reindexes" do
569
+ vector = Daru::Vector.new([1,2,3,4,5])
570
+ index = Daru::Index.new([3,4,1,0,6])
571
+
572
+ expect(vector.reindex(index)).to eq(
573
+ Daru::Vector.new([4,5,2,1,nil], index: index))
544
574
  end
545
575
  end
546
576
 
@@ -739,7 +769,24 @@ describe Daru::Vector do
739
769
  end
740
770
 
741
771
  context Daru::MultiIndex do
742
- pending
772
+ it "returns indexes of nils" do
773
+ mi = Daru::MultiIndex.from_tuples([
774
+ ['M', 2000],
775
+ ['M', 2001],
776
+ ['M', 2002],
777
+ ['M', 2003],
778
+ ['F', 2000],
779
+ ['F', 2001],
780
+ ['F', 2002],
781
+ ['F', 2003]
782
+ ])
783
+ vector = Daru::Vector.new([nil,2,4,5,3,nil,2,nil], index: mi)
784
+ expect(vector.missing_positions).to eq([
785
+ ['M',2000],
786
+ ['F',2001],
787
+ ['F',2003]
788
+ ])
789
+ end
743
790
  end
744
791
  end
745
792
 
@@ -757,9 +804,9 @@ describe Daru::Vector do
757
804
 
758
805
  context "#type" do
759
806
  before(:each) do
760
- @numeric = Daru::Vector.new([1,2,3,4,5])
761
- @multi = Daru::Vector.new([1,2,3,'sameer','d'])
762
- @with_nils = Daru::Vector.new([1,2,3,4,nil])
807
+ @numeric = Daru::Vector.new([1,2,3,4,5])
808
+ @multi = Daru::Vector.new([1,2,3,'sameer','d'])
809
+ @with_nils = Daru::Vector.new([1,2,3,4,nil])
763
810
  end
764
811
 
765
812
  it "checks numeric data correctly" do
@@ -922,7 +969,7 @@ describe Daru::Vector do
922
969
 
923
970
  it "stores name as a symbol" do
924
971
  @v.rename "This is a vector"
925
- expect(@v.name).to eq(:"This is a vector")
972
+ expect(@v.name).to eq("This is a vector")
926
973
  end
927
974
  end
928
975
 
@@ -966,11 +1013,29 @@ describe Daru::Vector do
966
1013
 
967
1014
  context "#detach_index" do
968
1015
  it "creates a DataFrame with first Vector as index and second as values of the Vector" do
969
- v = Daru::Vector.new([1,2,3,4,5,6], index: [:a, :b, :c, :d, :e, :f], name: :values)
1016
+ v = Daru::Vector.new([1,2,3,4,5,6],
1017
+ index: ['a', 'b', 'c', 'd', 'e', 'f'], name: :values)
970
1018
  expect(v.detach_index).to eq(Daru::DataFrame.new({
971
1019
  index: ['a', 'b', 'c', 'd', 'e', 'f'],
972
- vector: [1,2,3,4,5,6]
1020
+ values: [1,2,3,4,5,6]
973
1021
  }))
974
1022
  end
975
1023
  end
1024
+
1025
+ context "#lag" do
1026
+ it "lags the vector by specified amount" do
1027
+ xiu = Daru::Vector.new([17.28, 17.45, 17.84, 17.74, 17.82, 17.85, 17.36, 17.3, 17.56, 17.49, 17.46, 17.4, 17.03, 17.01,
1028
+ 16.86, 16.86, 16.56, 16.36, 16.66, 16.77])
1029
+ lag1 = xiu.lag
1030
+
1031
+ expect(lag1[lag1.size - 1]).to be_within(0.001).of(16.66)
1032
+ expect(lag1[lag1.size - 2]).to be_within(0.001).of(16.36)
1033
+
1034
+ #test with different lagging unit
1035
+ lag2 = xiu.lag(2)
1036
+
1037
+ expect(lag2[lag2.size - 1]).to be_within(0.001).of(16.36)
1038
+ expect(lag2[lag2.size - 2]).to be_within(0.001).of(16.56)
1039
+ end
1040
+ end
976
1041
  end if mri?