daru 0.1.5 → 0.3

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 (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?