daru 0.1.5 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +18 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +21 -7
  5. data/.travis.yml +10 -5
  6. data/CONTRIBUTING.md +15 -10
  7. data/History.md +124 -2
  8. data/README.md +37 -9
  9. data/ReleasePolicy.md +20 -0
  10. data/benchmarks/db_loading.rb +34 -0
  11. data/benchmarks/statistics.rb +6 -6
  12. data/benchmarks/where_clause.rb +1 -1
  13. data/benchmarks/where_vs_filter.rb +1 -1
  14. data/daru.gemspec +17 -41
  15. data/lib/daru.rb +10 -13
  16. data/lib/daru/accessors/gsl_wrapper.rb +1 -1
  17. data/lib/daru/accessors/nmatrix_wrapper.rb +2 -0
  18. data/lib/daru/category.rb +29 -15
  19. data/lib/daru/configuration.rb +34 -0
  20. data/lib/daru/core/group_by.rb +158 -77
  21. data/lib/daru/core/merge.rb +12 -3
  22. data/lib/daru/core/query.rb +20 -4
  23. data/lib/daru/dataframe.rb +692 -118
  24. data/lib/daru/date_time/index.rb +14 -11
  25. data/lib/daru/date_time/offsets.rb +9 -1
  26. data/lib/daru/extensions/which_dsl.rb +55 -0
  27. data/lib/daru/formatters/table.rb +3 -5
  28. data/lib/daru/index/categorical_index.rb +4 -4
  29. data/lib/daru/index/index.rb +131 -42
  30. data/lib/daru/index/multi_index.rb +118 -10
  31. data/lib/daru/io/csv/converters.rb +21 -0
  32. data/lib/daru/io/io.rb +105 -33
  33. data/lib/daru/io/sql_data_source.rb +10 -0
  34. data/lib/daru/iruby/templates/dataframe.html.erb +4 -51
  35. data/lib/daru/iruby/templates/dataframe_mi.html.erb +3 -56
  36. data/lib/daru/iruby/templates/dataframe_mi_tbody.html.erb +35 -0
  37. data/lib/daru/iruby/templates/dataframe_mi_thead.html.erb +21 -0
  38. data/lib/daru/iruby/templates/dataframe_tbody.html.erb +28 -0
  39. data/lib/daru/iruby/templates/dataframe_thead.html.erb +21 -0
  40. data/lib/daru/iruby/templates/vector.html.erb +3 -25
  41. data/lib/daru/iruby/templates/vector_mi.html.erb +3 -34
  42. data/lib/daru/iruby/templates/vector_mi_tbody.html.erb +26 -0
  43. data/lib/daru/iruby/templates/vector_mi_thead.html.erb +8 -0
  44. data/lib/daru/iruby/templates/vector_tbody.html.erb +17 -0
  45. data/lib/daru/iruby/templates/vector_thead.html.erb +8 -0
  46. data/lib/daru/maths/arithmetic/vector.rb +38 -2
  47. data/lib/daru/maths/statistics/dataframe.rb +28 -30
  48. data/lib/daru/maths/statistics/vector.rb +295 -41
  49. data/lib/daru/plotting/gruff/dataframe.rb +13 -15
  50. data/lib/daru/plotting/nyaplot/category.rb +1 -1
  51. data/lib/daru/plotting/nyaplot/dataframe.rb +15 -4
  52. data/lib/daru/plotting/nyaplot/vector.rb +1 -2
  53. data/lib/daru/vector.rb +308 -96
  54. data/lib/daru/version.rb +1 -1
  55. data/profile/vector_new.rb +9 -0
  56. data/spec/accessors/gsl_wrapper_spec.rb +38 -35
  57. data/spec/accessors/nmatrix_wrapper_spec.rb +25 -22
  58. data/spec/category_spec.rb +24 -20
  59. data/spec/core/group_by_spec.rb +238 -4
  60. data/spec/core/merge_spec.rb +1 -1
  61. data/spec/core/query_spec.rb +65 -50
  62. data/spec/daru_spec.rb +22 -0
  63. data/spec/dataframe_spec.rb +473 -16
  64. data/spec/date_time/date_time_index_helper_spec.rb +72 -0
  65. data/spec/date_time/index_spec.rb +34 -16
  66. data/spec/date_time/offsets_spec.rb +14 -0
  67. data/spec/extensions/rserve_spec.rb +1 -1
  68. data/spec/extensions/which_dsl_spec.rb +38 -0
  69. data/spec/fixtures/boolean_converter_test.csv +5 -0
  70. data/spec/fixtures/duplicates.csv +32 -0
  71. data/spec/fixtures/eciresults.html +394 -0
  72. data/spec/fixtures/empty_rows_test.csv +17 -0
  73. data/spec/fixtures/macau.html +3691 -0
  74. data/spec/fixtures/macd_data.csv +150 -0
  75. data/spec/fixtures/matrix_test.csv +55 -55
  76. data/spec/fixtures/moneycontrol.html +6812 -0
  77. data/spec/fixtures/string_converter_test.csv +5 -0
  78. data/spec/fixtures/test_xls.xls +0 -0
  79. data/spec/fixtures/test_xls_2.xls +0 -0
  80. data/spec/fixtures/url_test.txt~ +0 -0
  81. data/spec/fixtures/valid_markup.html +62 -0
  82. data/spec/fixtures/wiki_climate.html +1243 -0
  83. data/spec/fixtures/wiki_table_info.html +631 -0
  84. data/spec/formatters/table_formatter_spec.rb +29 -0
  85. data/spec/index/categorical_index_spec.rb +33 -33
  86. data/spec/index/index_spec.rb +160 -41
  87. data/spec/index/multi_index_spec.rb +143 -33
  88. data/spec/io/io_spec.rb +246 -2
  89. data/spec/io/sql_data_source_spec.rb +31 -41
  90. data/spec/iruby/dataframe_spec.rb +17 -19
  91. data/spec/iruby/vector_spec.rb +26 -28
  92. data/spec/maths/arithmetic/dataframe_spec.rb +1 -1
  93. data/spec/maths/arithmetic/vector_spec.rb +18 -0
  94. data/spec/maths/statistics/vector_spec.rb +153 -15
  95. data/spec/plotting/gruff/category_spec.rb +3 -3
  96. data/spec/plotting/gruff/dataframe_spec.rb +14 -4
  97. data/spec/plotting/gruff/vector_spec.rb +9 -9
  98. data/spec/plotting/nyaplot/category_spec.rb +5 -9
  99. data/spec/plotting/nyaplot/dataframe_spec.rb +95 -47
  100. data/spec/plotting/nyaplot/vector_spec.rb +5 -11
  101. data/spec/shared/vector_display_spec.rb +12 -14
  102. data/spec/spec_helper.rb +30 -7
  103. data/spec/support/matchers.rb +5 -0
  104. data/spec/vector_spec.rb +306 -72
  105. metadata +96 -55
  106. data/spec/fixtures/stock_data.csv +0 -500
@@ -12,24 +12,21 @@ describe Daru::Vector, 'plotting' do
12
12
 
13
13
  it 'plots the vector' do
14
14
  expect(plot).to receive(:add).with(:box, [11, 22, 33]).ordered
15
- expect(plot).to receive(:show).ordered
16
15
 
17
- vector.plot(type: :box)
16
+ expect(vector.plot(type: :box)).to eq plot
18
17
  end
19
18
 
20
19
  context 'scatter' do
21
20
  it 'is default type' do
22
21
  expect(plot).to receive(:add).with(:scatter, instance_of(Array), instance_of(Array)).ordered
23
- expect(plot).to receive(:show).ordered
24
22
 
25
- vector.plot
23
+ expect(vector.plot).to eq plot
26
24
  end
27
25
 
28
26
  it 'sets x_axis to 0...size' do
29
27
  expect(plot).to receive(:add).with(:scatter, [0, 1, 2], [11, 22, 33]).ordered
30
- expect(plot).to receive(:show).ordered
31
28
 
32
- vector.plot(type: :scatter)
29
+ expect(vector.plot(type: :scatter)).to eq plot
33
30
  end
34
31
  end
35
32
 
@@ -37,9 +34,8 @@ describe Daru::Vector, 'plotting' do
37
34
  context type.to_s do
38
35
  it 'does not set x axis' do
39
36
  expect(plot).to receive(:add).with(type, [11, 22, 33]).ordered
40
- expect(plot).to receive(:show).ordered
41
37
 
42
- vector.plot(type: type)
38
+ expect(vector.plot(type: type)).to eq plot
43
39
  end
44
40
  end
45
41
  end
@@ -48,9 +44,8 @@ describe Daru::Vector, 'plotting' do
48
44
  context type.to_s do
49
45
  it 'sets x axis to index' do
50
46
  expect(plot).to receive(:add).with(type, [:a, :b, :c], [11, 22, 33]).ordered
51
- expect(plot).to receive(:show).ordered
52
47
 
53
- vector.plot(type: type)
48
+ expect(vector.plot(type: type)).to eq plot
54
49
  end
55
50
  end
56
51
  end
@@ -58,7 +53,6 @@ describe Daru::Vector, 'plotting' do
58
53
  context 'with block provided' do
59
54
  it 'yields plot and diagram' do
60
55
  expect(plot).to receive(:add).with(:box, [11, 22, 33]).ordered.and_return(diagram)
61
- expect(plot).to receive(:show).ordered
62
56
 
63
57
  expect { |b| vector.plot(type: :box, &b) }.to yield_with_args(plot, diagram)
64
58
  end
@@ -109,7 +109,7 @@ describe Daru::Vector do
109
109
  context '#to_html' do
110
110
  let(:doc) { Nokogiri::HTML(vector.to_html) }
111
111
  subject(:table) { doc.at('table') }
112
- let(:header) { table.at('tr:first-child > th:first-child') }
112
+ let(:header) { doc.at('b') }
113
113
 
114
114
  context 'simple' do
115
115
  let(:vector) { Daru::Vector.new [1,nil,3],
@@ -119,13 +119,12 @@ describe Daru::Vector do
119
119
  describe 'header' do
120
120
  subject { header }
121
121
  it { is_expected.not_to be_nil }
122
- its(['colspan']) { is_expected.to eq '2' }
123
- its(:text) { is_expected.to eq "Daru::Vector(3)"\
124
- "#{":category" if type == :category}" }
122
+ its(:text) { is_expected.to eq " Daru::Vector(3)"\
123
+ "#{":category" if type == :category} " }
125
124
  end
126
125
 
127
126
  describe 'name' do
128
- subject(:name) { table.at('tr:nth-child(2) > th:nth-child(2)') }
127
+ subject(:name) { table.at('thead > tr:first-child > th:nth-child(2)') }
129
128
  it { is_expected.not_to be_nil }
130
129
  its(:text) { is_expected.to eq 'test' }
131
130
 
@@ -151,18 +150,18 @@ describe Daru::Vector do
151
150
 
152
151
  context 'large vector' do
153
152
  subject(:vector) { Daru::Vector.new [1,2,3] * 100, name: 'test', type: type }
154
- it 'has only 30 rows (+ 2 header rows, + 2 finishing rows)' do
155
- expect(table.search('tr').size).to eq 34
153
+ it 'has only 30 rows (+ 1 header rows, + 2 finishing rows)' do
154
+ expect(table.search('tr').size).to eq 33
156
155
  end
157
156
 
158
157
  describe '"skipped" row' do
159
- subject(:row) { table.search('tr:nth-child(33) td').map(&:text) }
158
+ subject(:row) { table.search('tr:nth-child(31) td').map(&:text) }
160
159
  its(:count) { is_expected.to eq 2 }
161
160
  it { is_expected.to eq ['...', '...'] }
162
161
  end
163
162
 
164
163
  describe 'last row' do
165
- subject(:row) { table.search('tr:nth-child(34) td').map(&:text) }
164
+ subject(:row) { table.search('tr:nth-child(32) td').map(&:text) }
166
165
  its(:count) { is_expected.to eq 2 }
167
166
  it { is_expected.to eq ['299', '3'] }
168
167
  end
@@ -189,19 +188,18 @@ describe Daru::Vector do
189
188
  describe 'header' do
190
189
  subject { header }
191
190
  it { is_expected.not_to be_nil }
192
- its(['colspan']) { is_expected.to eq '3' }
193
- its(:text) { is_expected.to eq "Daru::Vector(7)"\
194
- "#{":category" if type == :category}" }
191
+ its(:text) { is_expected.to eq " Daru::Vector(7)"\
192
+ "#{":category" if type == :category} " }
195
193
  end
196
194
 
197
195
  describe 'name row' do
198
- subject(:row) { table.at('tr:nth-child(2)').search('th') }
196
+ subject(:row) { table.at('thead > tr:nth-child(1)').search('th') }
199
197
  its(:count) { should == 2 }
200
198
  it { expect(row.first['colspan']).to eq '2' }
201
199
  end
202
200
 
203
201
  describe 'first data row' do
204
- let(:row) { table.at('tr:nth-child(3)') }
202
+ let(:row) { table.at('tbody > tr:first-child') }
205
203
  subject { row.inner_html.scan(/<t[dh].+?<\/t[dh]>/) }
206
204
  it { is_expected.to eq [
207
205
  '<th rowspan="3">foo</th>',
@@ -1,5 +1,6 @@
1
1
  require 'rspec'
2
2
  require 'rspec/its'
3
+ require 'rspec/expectations'
3
4
  require 'matrix'
4
5
  require 'awesome_print'
5
6
  require 'distribution'
@@ -7,6 +8,7 @@ require 'tempfile'
7
8
  require 'pry-byebug'
8
9
  require 'nokogiri'
9
10
  require 'gruff'
11
+ require 'webmock/rspec'
10
12
 
11
13
  def mri?
12
14
  RUBY_ENGINE == 'ruby'
@@ -16,25 +18,27 @@ def jruby?
16
18
  RUBY_ENGINE == 'jruby'
17
19
  end
18
20
 
19
- if jruby?
20
- require 'mdarray'
21
- else
22
- require 'nmatrix/nmatrix'
23
- end
24
-
25
21
  RSpec::Expectations.configuration.warn_about_potential_false_positives = false
26
22
 
27
23
  require 'simplecov'
28
24
  SimpleCov.start do
29
25
  add_filter 'vendor'
30
26
  add_filter 'spec'
31
- minimum_coverage_by_file 95
27
+ # minimum_coverage_by_file 95 -- too strict for now. Reconsider after specs redesign.
32
28
  end
33
29
 
34
30
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
35
31
  $LOAD_PATH.unshift(File.dirname(__FILE__))
36
32
  require 'daru'
37
33
 
34
+ if jruby?
35
+ require 'mdarray'
36
+ else
37
+ if Daru.has_nmatrix?
38
+ require 'nmatrix/nmatrix'
39
+ end
40
+ end
41
+
38
42
  ALL_DTYPES = [:nmatrix, :gsl, :array]
39
43
 
40
44
  # FIXME: This must go! Need to be able to use be_within
@@ -51,6 +55,25 @@ def expect_correct_df_in_delta df1, df2, delta
51
55
  end
52
56
  end
53
57
 
58
+ RSpec::Matchers.define :be_all_within do |delta|
59
+ match do |actual|
60
+ expect(@expected).to_not be_nil
61
+ expect(actual.size).to equal(actual.size)
62
+ (@act, @exp), @idx = actual.zip(@expected).each_with_index.detect { |(a, e), _| (a - e).abs > delta }
63
+ @idx.nil?
64
+ end
65
+
66
+ chain :of do |expected|
67
+ @expected = expected
68
+ end
69
+
70
+ failure_message do |actual|
71
+ return "expected value must be provided using '.of'." if @expected.nil?
72
+ return "expected.size must equal actual.size." if @expected.size != actual.size
73
+ "at index=[#{@idx}], expected '#{actual[@idx]}' to be within '#{delta}' of '#{@expected[@idx]}'."
74
+ end
75
+ end
76
+
54
77
  class String
55
78
  # allows to pretty test agains multiline strings:
56
79
  # %Q{
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :be_boolean do
2
+ match do |actual|
3
+ expect(actual.is_a?(TrueClass) || actual.is_a?(FalseClass)).to be true
4
+ end
5
+ end
@@ -84,6 +84,11 @@ describe Daru::Vector do
84
84
  expect(dv.index.to_a).to eq(['a', 'b', :r, 0])
85
85
  end
86
86
 
87
+ it "initializes array with nils with dtype NMatrix" do
88
+ dv = Daru::Vector.new [2, nil], dtype: :nmatrix
89
+ expect(dv.to_a).to eq([2, nil])
90
+ expect(dv.index.to_a).to eq([0, 1])
91
+ end
87
92
  end
88
93
 
89
94
  context "#reorder!" do
@@ -358,6 +363,9 @@ describe Daru::Vector do
358
363
  let (:idx) { Daru::Index.new [1, 0, :c] }
359
364
  let (:dv) { Daru::Vector.new ['a', 'b', 'c'], index: idx }
360
365
 
366
+ let (:idx_dt) { Daru::DateTimeIndex.new(['2017-01-01', '2017-02-01', '2017-03-01']) }
367
+ let (:dv_dt) { Daru::Vector.new(['a', 'b', 'c'], index: idx_dt) }
368
+
361
369
  context "single position" do
362
370
  it { expect(dv.at 1).to eq 'b' }
363
371
  end
@@ -405,6 +413,15 @@ describe Daru::Vector do
405
413
  its(:to_a) { is_expected.to eq ['a'] }
406
414
  its(:'index.to_a') { is_expected.to eq [1] }
407
415
  end
416
+
417
+ context "Splat .at on DateTime index" do
418
+ subject { dv_dt.at(*[1,2]) }
419
+
420
+ it { is_expected.to be_a Daru::Vector }
421
+ its(:size) { is_expected.to eq 2 }
422
+ its(:to_a) { is_expected.to eq ['b', 'c'] }
423
+ its(:'index.to_a') { is_expected.to eq ['2017-02-01', '2017-03-01'] }
424
+ end
408
425
  end
409
426
 
410
427
  context Daru::MultiIndex do
@@ -833,6 +850,24 @@ describe Daru::Vector do
833
850
  end
834
851
  end
835
852
 
853
+ context '#last' do
854
+ subject(:vector) do
855
+ Daru::Vector.new (1..20).to_a, dtype: dtype
856
+ end
857
+
858
+ it 'takes 1 by default' do
859
+ expect(vector.last).to eq 20
860
+ end
861
+
862
+ it 'takes num if provided' do
863
+ expect(vector.last(3)).to eq Daru::Vector.new (18..20).to_a, index: (17..19).to_a
864
+ end
865
+
866
+ it 'does not fail on too large num' do
867
+ expect(vector.last(3000)).to eq vector
868
+ end
869
+ end
870
+
836
871
  context "#concat" do
837
872
  before :each do
838
873
  @dv = Daru::Vector.new [1,2,3,4,5], name: :yoga,
@@ -998,6 +1033,26 @@ describe Daru::Vector do
998
1033
  its(:to_json) { is_expected.to eq(vector.to_h.to_json) }
999
1034
  end
1000
1035
 
1036
+ context "#to_s" do
1037
+ before do
1038
+ @v = Daru::Vector.new ["a", "b"], index: [1, 2]
1039
+ end
1040
+
1041
+ it 'produces a class, size description' do
1042
+ expect(@v.to_s).to eq("#<Daru::Vector(2)>")
1043
+ end
1044
+
1045
+ it 'produces a class, name, size description' do
1046
+ @v.name = "Test"
1047
+ expect(@v.to_s).to eq("#<Daru::Vector: Test(2)>")
1048
+ end
1049
+
1050
+ it 'produces a class, name, size description when the name is a symbol' do
1051
+ @v.name = :Test
1052
+ expect(@v.to_s).to eq("#<Daru::Vector: Test(2)>")
1053
+ end
1054
+ end
1055
+
1001
1056
  context "#uniq" do
1002
1057
  before do
1003
1058
  @v = Daru::Vector.new [1, 2, 2, 2.0, 3, 3.0], index:[:a, :b, :c, :d, :e, :f]
@@ -1359,8 +1414,75 @@ describe Daru::Vector do
1359
1414
  end
1360
1415
 
1361
1416
  context "#summary" do
1362
- it "has name in the summary" do
1363
- expect(@common_all_dtypes.summary.match("#{@common_all_dtypes.name}")).to_not eq(nil)
1417
+ subject { dv.summary }
1418
+
1419
+ context 'all types' do
1420
+ let(:dv) { Daru::Vector.new([1,2,3,4,5], name: 'vector') }
1421
+
1422
+ it { is_expected.to include dv.name }
1423
+
1424
+ it { is_expected.to include "n :#{dv.size}" }
1425
+
1426
+ it { is_expected.to include "non-missing:#{dv.size - dv.count_values(*Daru::MISSING_VALUES)}" }
1427
+ end
1428
+
1429
+ unless dtype == :nmatrix
1430
+ context "numeric type" do
1431
+ let(:dv) { Daru::Vector.new([1,2,5], name: 'numeric') }
1432
+
1433
+ it { is_expected. to eq %Q{
1434
+ |= numeric
1435
+ | n :3
1436
+ | non-missing:3
1437
+ | median: 2
1438
+ | mean: 2.6667
1439
+ | std.dev.: 2.0817
1440
+ | std.err.: 1.2019
1441
+ | skew: 0.2874
1442
+ | kurtosis: -2.3333
1443
+ }.unindent }
1444
+ end
1445
+
1446
+ context "numeric type with missing values" do
1447
+ let(:dv) { Daru::Vector.new([1,2,5,nil,Float::NAN], name: 'numeric') }
1448
+
1449
+ it { is_expected.not_to include 'skew' }
1450
+ it { is_expected.not_to include 'kurtosis' }
1451
+ end
1452
+ end
1453
+
1454
+ if dtype == :array
1455
+ context "object type" do
1456
+ let(:dv) { Daru::Vector.new([1,1,2,2,"string",nil,Float::NAN], name: 'object') }
1457
+
1458
+ if RUBY_VERSION >= '2.2'
1459
+ it { is_expected.to eq %Q{
1460
+ |= object
1461
+ | n :7
1462
+ | non-missing:5
1463
+ | factors: 1,2,string
1464
+ | mode: 1,2
1465
+ | Distribution
1466
+ | string 1 50.00%
1467
+ | NaN 1 50.00%
1468
+ | 1 2 100.00%
1469
+ | 2 2 100.00%
1470
+ }.unindent }
1471
+ else
1472
+ it { is_expected.to eq %Q{
1473
+ |= object
1474
+ | n :7
1475
+ | non-missing:5
1476
+ | factors: 1,2,string
1477
+ | mode: 1,2
1478
+ | Distribution
1479
+ | NaN 1 50.00%
1480
+ | string 1 50.00%
1481
+ | 2 2 100.00%
1482
+ | 1 2 100.00%
1483
+ }.unindent }
1484
+ end
1485
+ end
1364
1486
  end
1365
1487
  end
1366
1488
 
@@ -1388,27 +1510,19 @@ describe Daru::Vector do
1388
1510
  end
1389
1511
  end
1390
1512
 
1391
- context "#is_nil?" do
1392
- before(:each) do
1393
- @with_md = Daru::Vector.new([1,2,nil,3,4,nil])
1394
- @without_md = Daru::Vector.new([1,2,3,4,5,6])
1395
- end
1396
-
1397
- it "verifies missing data presence" do
1398
- expect(@with_md.is_nil?) .to eq(Daru::Vector.new([false,false,true,false,false,true]))
1399
- expect(@without_md.is_nil?).to eq(Daru::Vector.new([false,false,false,false,false,false]))
1400
- end
1401
- end
1513
+ context '#is_values' do
1514
+ let(:dv) { Daru::Vector.new [10, 11, 10, nil, nil] }
1402
1515
 
1403
- context "#not_nil?" do
1404
- before(:each) do
1405
- @with_md = Daru::Vector.new([1,2,nil,3,4,nil])
1406
- @without_md = Daru::Vector.new([1,2,3,4,5,6])
1516
+ context 'single value' do
1517
+ subject { dv.is_values 10 }
1518
+ it { is_expected.to be_a Daru::Vector }
1519
+ its(:to_a) { is_expected.to eq [true, false, true, false, false] }
1407
1520
  end
1408
1521
 
1409
- it "verifies missing data presence" do
1410
- expect(@with_md.not_nil?) .to eq(Daru::Vector.new([true,true,false,true,true,false]))
1411
- expect(@without_md.not_nil?).to eq(Daru::Vector.new([true,true,true,true,true,true]))
1522
+ context 'multiple values' do
1523
+ subject { dv.is_values 10, nil }
1524
+ it { is_expected.to be_a Daru::Vector }
1525
+ its(:to_a) { is_expected.to eq [true, false, true, true, true] }
1412
1526
  end
1413
1527
  end
1414
1528
 
@@ -1433,7 +1547,7 @@ describe Daru::Vector do
1433
1547
  index: 11..18 }
1434
1548
  context 'reject only nils' do
1435
1549
  subject { dv.reject_values nil }
1436
-
1550
+
1437
1551
  it { is_expected.to be_a Daru::Vector }
1438
1552
  its(:to_a) { is_expected.to eq [1, 3, :a, Float::NAN, Float::NAN, 1] }
1439
1553
  its(:'index.to_a') { is_expected.to eq [11, 13, 14, 15, 17, 18] }
@@ -1441,7 +1555,7 @@ describe Daru::Vector do
1441
1555
 
1442
1556
  context 'reject only float::NAN' do
1443
1557
  subject { dv.reject_values Float::NAN }
1444
-
1558
+
1445
1559
  it { is_expected.to be_a Daru::Vector }
1446
1560
  its(:to_a) { is_expected.to eq [1, nil, 3, :a, nil, 1] }
1447
1561
  its(:'index.to_a') { is_expected.to eq [11, 12, 13, 14, 16, 18] }
@@ -1449,15 +1563,15 @@ describe Daru::Vector do
1449
1563
 
1450
1564
  context 'reject both nil and float::NAN' do
1451
1565
  subject { dv.reject_values nil, Float::NAN }
1452
-
1566
+
1453
1567
  it { is_expected.to be_a Daru::Vector }
1454
1568
  its(:to_a) { is_expected.to eq [1, 3, :a, 1] }
1455
1569
  its(:'index.to_a') { is_expected.to eq [11, 13, 14, 18] }
1456
1570
  end
1457
-
1571
+
1458
1572
  context 'reject any other value' do
1459
1573
  subject { dv.reject_values 1, 3 }
1460
-
1574
+
1461
1575
  it { is_expected.to be_a Daru::Vector }
1462
1576
  its(:to_a) { is_expected.to eq [nil, :a, Float::NAN, nil, Float::NAN] }
1463
1577
  its(:'index.to_a') { is_expected.to eq [12, 14, 15, 16, 17] }
@@ -1465,25 +1579,25 @@ describe Daru::Vector do
1465
1579
 
1466
1580
  context 'when resultant vector has only one value' do
1467
1581
  subject { dv.reject_values 1, :a, nil, Float::NAN }
1468
-
1582
+
1469
1583
  it { is_expected.to be_a Daru::Vector }
1470
1584
  its(:to_a) { is_expected.to eq [3] }
1471
1585
  its(:'index.to_a') { is_expected.to eq [13] }
1472
1586
  end
1473
-
1587
+
1474
1588
  context 'when resultant vector has no value' do
1475
1589
  subject { dv.reject_values 1, 3, :a, nil, Float::NAN, 5 }
1476
-
1590
+
1477
1591
  it { is_expected.to be_a Daru::Vector }
1478
1592
  its(:to_a) { is_expected.to eq [] }
1479
1593
  its(:'index.to_a') { is_expected.to eq [] }
1480
1594
  end
1481
-
1595
+
1482
1596
  context 'works for gsl' do
1483
1597
  let(:dv) { Daru::Vector.new [1, 2, 3, Float::NAN], dtype: :gsl,
1484
1598
  index: 11..14 }
1485
1599
  subject { dv.reject_values Float::NAN }
1486
-
1600
+
1487
1601
  it { is_expected.to be_a Daru::Vector }
1488
1602
  its(:dtype) { is_expected.to eq :gsl }
1489
1603
  its(:to_a) { is_expected.to eq [1, 2, 3].map(&:to_f) }
@@ -1501,31 +1615,31 @@ describe Daru::Vector do
1501
1615
 
1502
1616
  context 'reject only nils' do
1503
1617
  subject { dv.reject_values nil }
1504
-
1618
+
1505
1619
  it { is_expected.to be_a Daru::Vector }
1506
1620
  its(:to_a) { is_expected.to eq [1, 3, :a, Float::NAN, Float::NAN, 1] }
1507
1621
  its(:'index.to_a') { is_expected.to eq [11, 13, 14, 15, 17, 18] }
1508
1622
  end
1509
-
1623
+
1510
1624
  context 'reject only float::NAN' do
1511
1625
  subject { dv.reject_values Float::NAN }
1512
-
1626
+
1513
1627
  it { is_expected.to be_a Daru::Vector }
1514
1628
  its(:to_a) { is_expected.to eq [1, nil, 3, :a, nil, 1] }
1515
1629
  its(:'index.to_a') { is_expected.to eq [11, 12, 13, 14, 16, 18] }
1516
1630
  end
1517
-
1631
+
1518
1632
  context 'reject both nil and float::NAN' do
1519
1633
  subject { dv.reject_values nil, Float::NAN }
1520
-
1634
+
1521
1635
  it { is_expected.to be_a Daru::Vector }
1522
1636
  its(:to_a) { is_expected.to eq [1, 3, :a, 1] }
1523
1637
  its(:'index.to_a') { is_expected.to eq [11, 13, 14, 18] }
1524
1638
  end
1525
-
1639
+
1526
1640
  context 'reject any other value' do
1527
1641
  subject { dv.reject_values 1, 3 }
1528
-
1642
+
1529
1643
  it { is_expected.to be_a Daru::Vector }
1530
1644
  its(:to_a) { is_expected.to eq [nil, :a, Float::NAN, nil, Float::NAN] }
1531
1645
  its(:'index.to_a') { is_expected.to eq [12, 14, 15, 16, 17] }
@@ -1563,24 +1677,24 @@ describe Daru::Vector do
1563
1677
  let(:dv) { Daru::Vector.new [1, Float::NAN, 2, 3] }
1564
1678
  it { expect(dv.include_values? nil, Float::NAN).to eq true }
1565
1679
  end
1566
-
1680
+
1567
1681
  context 'true with only Float::NAN' do
1568
1682
  let(:dv) { Daru::Vector.new [1, nil, 2, 3] }
1569
1683
  it { expect(dv.include_values? nil, Float::NAN).to eq true }
1570
1684
  end
1571
-
1685
+
1572
1686
  context 'false' do
1573
1687
  let(:dv) { Daru::Vector.new [1, 2, 3] }
1574
1688
  it { expect(dv.include_values? nil, Float::NAN).to eq false }
1575
1689
  end
1576
1690
  end
1577
-
1691
+
1578
1692
  context 'any other value' do
1579
1693
  context 'true' do
1580
1694
  let(:dv) { Daru::Vector.new [1, 2, 3, 4, nil] }
1581
1695
  it { expect(dv.include_values? 1, 2, 3, 5).to eq true }
1582
1696
  end
1583
-
1697
+
1584
1698
  context 'false' do
1585
1699
  let(:dv) { Daru::Vector.new [1, 2, 3, 4, nil] }
1586
1700
  it { expect(dv.include_values? 5, 6).to eq false }
@@ -1600,12 +1714,12 @@ describe Daru::Vector do
1600
1714
  context Daru::Index do
1601
1715
  let(:dv) { Daru::Vector.new [1, 2, 1, 2, 3, nil, nil, Float::NAN],
1602
1716
  index: 11..18 }
1603
-
1717
+
1604
1718
  subject { dv.indexes 1, 2, nil, Float::NAN }
1605
1719
  it { is_expected.to be_a Array }
1606
1720
  it { is_expected.to eq [11, 12, 13, 14, 16, 17, 18] }
1607
1721
  end
1608
-
1722
+
1609
1723
  context Daru::MultiIndex do
1610
1724
  let(:mi) do
1611
1725
  Daru::MultiIndex.from_tuples([
@@ -1621,7 +1735,7 @@ describe Daru::Vector do
1621
1735
  end
1622
1736
  let(:dv) { Daru::Vector.new [1, 2, 1, 2, 3, nil, nil, Float::NAN],
1623
1737
  index: mi }
1624
-
1738
+
1625
1739
  subject { dv.indexes 1, 2, Float::NAN }
1626
1740
  it { is_expected.to be_a Array }
1627
1741
  it { is_expected.to eq(
@@ -1634,7 +1748,7 @@ describe Daru::Vector do
1634
1748
  ]) }
1635
1749
  end
1636
1750
  end
1637
-
1751
+
1638
1752
  context '#replace_values' do
1639
1753
  subject do
1640
1754
  Daru::Vector.new(
@@ -1647,13 +1761,13 @@ describe Daru::Vector do
1647
1761
  before { subject.replace_values [nil, Float::NAN], 10 }
1648
1762
  its(:to_a) { is_expected.to eq [1, 2, 1, 4, 10, 10, 10, 10] }
1649
1763
  end
1650
-
1764
+
1651
1765
  context 'replace arbitrary values' do
1652
1766
  before { subject.replace_values [1, 2], 10 }
1653
1767
  its(:to_a) { is_expected.to eq(
1654
1768
  [10, 10, 10, 4, nil, Float::NAN, nil, Float::NAN]) }
1655
1769
  end
1656
-
1770
+
1657
1771
  context 'works for single value' do
1658
1772
  before { subject.replace_values nil, 10 }
1659
1773
  its(:to_a) { is_expected.to eq(
@@ -1673,6 +1787,61 @@ describe Daru::Vector do
1673
1787
  end
1674
1788
  end
1675
1789
 
1790
+ context '#rolling_fillna!' do
1791
+ subject do
1792
+ Daru::Vector.new(
1793
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN]
1794
+ )
1795
+ end
1796
+
1797
+ context 'rolling_fillna! forwards' do
1798
+ before { subject.rolling_fillna!(:forward) }
1799
+ its(:to_a) { is_expected.to eq [0, 2, 1, 4, 4, 4, 3, 3, 3] }
1800
+ end
1801
+
1802
+ context 'rolling_fillna! backwards' do
1803
+ before { subject.rolling_fillna!(direction: :backward) }
1804
+ its(:to_a) { is_expected.to eq [2, 2, 1, 4, 3, 3, 3, 0, 0] }
1805
+ end
1806
+
1807
+ context 'all invalid vector' do
1808
+ subject do
1809
+ Daru::Vector.new(
1810
+ [Float::NAN, Float::NAN, Float::NAN, Float::NAN, Float::NAN]
1811
+ )
1812
+ end
1813
+ before { subject.rolling_fillna!(:forward) }
1814
+ its(:to_a) { is_expected.to eq [0, 0, 0, 0, 0] }
1815
+ end
1816
+
1817
+ context 'with non-default index' do
1818
+ subject do
1819
+ Daru::Vector.new(
1820
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN],
1821
+ index: %w[a b c d e f g h i]
1822
+ )
1823
+ end
1824
+ before { subject.rolling_fillna!(direction: :backward) }
1825
+ it { is_expected.to eq Daru::Vector.new([2, 2, 1, 4, 3, 3, 3, 0, 0], index: %w[a b c d e f g h i]) }
1826
+ end
1827
+ end
1828
+
1829
+ context '#rolling_fillna' do
1830
+ subject do
1831
+ Daru::Vector.new(
1832
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN]
1833
+ )
1834
+ end
1835
+
1836
+ context 'rolling_fillna forwards' do
1837
+ it { expect(subject.rolling_fillna(:forward).to_a).to eq [0, 2, 1, 4, 4, 4, 3, 3, 3] }
1838
+ end
1839
+
1840
+ context 'rolling_fillna backwards' do
1841
+ it { expect(subject.rolling_fillna(direction: :backward).to_a).to eq [2, 2, 1, 4, 3, 3, 3, 0, 0] }
1842
+ end
1843
+ end
1844
+
1676
1845
  context "#type" do
1677
1846
  before(:each) do
1678
1847
  @numeric = Daru::Vector.new([1,2,3,4,5])
@@ -1741,7 +1910,7 @@ describe Daru::Vector do
1741
1910
 
1742
1911
  context '#to_nmatrix' do
1743
1912
  let(:dv) { Daru::Vector.new [1, 2, 3, 4, 5] }
1744
-
1913
+
1745
1914
  context 'horizontal axis' do
1746
1915
  subject { dv.to_nmatrix }
1747
1916
 
@@ -1749,19 +1918,19 @@ describe Daru::Vector do
1749
1918
  its(:shape) { is_expected.to eq [1, 5] }
1750
1919
  its(:to_a) { is_expected.to eq [1, 2, 3, 4, 5] }
1751
1920
  end
1752
-
1921
+
1753
1922
  context 'vertical axis' do
1754
1923
  subject { dv.to_nmatrix :vertical }
1755
-
1924
+
1756
1925
  it { is_expected.to be_a NMatrix }
1757
1926
  its(:shape) { is_expected.to eq [5, 1] }
1758
1927
  its(:to_a) { is_expected.to eq [1, 2, 3, 4, 5].map { |i| [i] } }
1759
1928
  end
1760
-
1929
+
1761
1930
  context 'invalid axis' do
1762
1931
  it { expect { dv.to_nmatrix :hello }.to raise_error ArgumentError }
1763
1932
  end
1764
-
1933
+
1765
1934
  context 'vector contain non-numeric' do
1766
1935
  let(:dv) { Daru::Vector.new [1, 2, nil, 4] }
1767
1936
  it { expect { dv.to_nmatrix }.to raise_error ArgumentError }
@@ -1904,52 +2073,90 @@ describe Daru::Vector do
1904
2073
  end
1905
2074
  end
1906
2075
 
1907
- context "#lag" do
1908
- before do
1909
- @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,
1910
- 16.86, 16.86, 16.56, 16.36, 16.66, 16.77])
2076
+ describe '#lag' do
2077
+ let(:source) { Daru::Vector.new(1..5) }
2078
+
2079
+ context 'by default' do
2080
+ subject { source.lag }
2081
+ it { is_expected.to eq Daru::Vector.new([nil, 1, 2, 3, 4]) }
1911
2082
  end
1912
2083
 
1913
- it "lags the vector by specified amount" do
1914
- lag1 = @xiu.lag
2084
+ subject { source.lag(amount) }
1915
2085
 
1916
- expect(lag1[lag1.size - 1]).to be_within(0.001).of(16.66)
1917
- expect(lag1[lag1.size - 2]).to be_within(0.001).of(16.36)
2086
+ context '0' do
2087
+ let(:amount) { 0 }
2088
+ it { is_expected.to eq Daru::Vector.new([1, 2, 3, 4, 5]) }
2089
+ end
1918
2090
 
1919
- #test with different lagging unit
1920
- lag2 = @xiu.lag(2)
2091
+ context 'same as vector size' do
2092
+ let(:amount) { source.size }
2093
+ it { is_expected.to eq Daru::Vector.new([nil]*source.size) }
2094
+ end
2095
+
2096
+ context 'same as vector -ve size' do
2097
+ let(:amount) { -source.size }
2098
+ it { is_expected.to eq Daru::Vector.new([nil]*source.size) }
2099
+ end
2100
+
2101
+ context 'positive' do
2102
+ let(:amount) { 2 }
2103
+ it { is_expected.to eq Daru::Vector.new([nil, nil, 1, 2, 3]) }
2104
+ end
2105
+
2106
+ context 'negative' do
2107
+ let(:amount) { -1 }
2108
+ it { is_expected.to eq Daru::Vector.new([2, 3, 4, 5, nil]) }
2109
+ end
1921
2110
 
1922
- expect(lag2[lag2.size - 1]).to be_within(0.001).of(16.36)
1923
- expect(lag2[lag2.size - 2]).to be_within(0.001).of(16.56)
2111
+ context 'large positive' do
2112
+ let(:amount) { source.size + 100 }
2113
+ it { is_expected.to eq Daru::Vector.new([nil]*source.size) }
1924
2114
  end
2115
+
2116
+ context 'large negative' do
2117
+ let(:amount) { -(source.size + 100) }
2118
+ it { is_expected.to eq Daru::Vector.new([nil]*source.size) }
2119
+ end
2120
+
1925
2121
  end
1926
-
2122
+
1927
2123
  context "#group_by" do
1928
2124
  let(:dv) { Daru::Vector.new [:a, :b, :a, :b, :c] }
1929
-
2125
+
1930
2126
  context 'vector not specified' do
1931
- subject { dv.group_by }
1932
-
2127
+ subject { dv.group_by }
2128
+
1933
2129
  it { is_expected.to be_a Daru::Core::GroupBy }
1934
2130
  its(:'groups.size') { is_expected.to eq 3 }
1935
2131
  its(:groups) { is_expected.to eq({[:a]=>[0, 2], [:b]=>[1, 3], [:c]=>[4]}) }
1936
2132
  end
1937
-
2133
+
1938
2134
  context 'vector name specified' do
1939
2135
  before { dv.name = :hello }
1940
2136
  subject { dv.group_by :hello }
1941
-
2137
+
1942
2138
  it { is_expected.to be_a Daru::Core::GroupBy }
1943
2139
  its(:'groups.size') { is_expected.to eq 3 }
1944
- its(:groups) { is_expected.to eq({[:a]=>[0, 2], [:b]=>[1, 3], [:c]=>[4]}) }
2140
+ its(:groups) { is_expected.to eq({[:a]=>[0, 2], [:b]=>[1, 3], [:c]=>[4]}) }
1945
2141
  end
1946
-
2142
+
1947
2143
  context 'vector name invalid' do
1948
2144
  before { dv.name = :hello }
1949
2145
  it { expect { dv.group_by :abc }.to raise_error }
1950
2146
  end
1951
2147
  end
1952
2148
 
2149
+ context '#match' do
2150
+ subject { dv.match(regexp) }
2151
+
2152
+ context 'returns matching array for a given regexp' do
2153
+ let(:dv) { Daru::Vector.new ['3 days', '5 weeks', '2 weeks'] }
2154
+ let(:regexp) { /weeks/ }
2155
+
2156
+ it { is_expected.to eq([false, true, true]) }
2157
+ end
2158
+ end
2159
+
1953
2160
  context '#method_missing' do
1954
2161
  context 'getting' do
1955
2162
  subject(:vector) { Daru::Vector.new [1,2,3], index: [:a, :b, :c] }
@@ -1974,6 +2181,24 @@ describe Daru::Vector do
1974
2181
  end
1975
2182
  end
1976
2183
 
2184
+ context "#sort_by_index" do
2185
+ let(:asc) { vector.sort_by_index }
2186
+ let(:desc) { vector.sort_by_index(ascending: false) }
2187
+
2188
+ context 'numeric vector' do
2189
+ let(:vector) { Daru::Vector.new [11, 13, 12], index: [23, 21, 22] }
2190
+ specify { expect(asc.to_a).to eq [13, 12, 11] }
2191
+ specify { expect(desc.to_a).to eq [11, 12, 13] }
2192
+ end
2193
+
2194
+ context 'mix variable type index' do
2195
+ let(:vector) { Daru::Vector.new [11, Float::NAN, nil],
2196
+ index: [21, 23, 22] }
2197
+ specify { expect(asc.to_a).to eq [11, nil, Float::NAN] }
2198
+ specify { expect(desc.to_a).to eq [Float::NAN, nil, 11] }
2199
+ end
2200
+ end
2201
+
1977
2202
  context '#db_type' do
1978
2203
  it 'is DATE for vector with any date in it' do
1979
2204
  # FIXME: is it sane?.. - zverok
@@ -2003,4 +2228,13 @@ describe Daru::Vector do
2003
2228
  end
2004
2229
  end
2005
2230
 
2231
+ context '#where clause when Nan, nil data value is present' do
2232
+ let(:v) { Daru::Vector.new([1,2,3,Float::NAN, nil]) }
2233
+
2234
+ it 'missing/undefined data in Vector/DataFrame' do
2235
+ expect(v.where(v.lt(4))).to eq(Daru::Vector.new([1,2,3]))
2236
+ expect(v.where(v.lt(3))).to eq(Daru::Vector.new([1,2]))
2237
+ expect(v.where(v.lt(2))).to eq(Daru::Vector.new([1]))
2238
+ end
2239
+ end
2006
2240
  end if mri?