daru_lite 0.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 (149) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +18 -0
  3. data/.github/workflows/ci.yml +33 -0
  4. data/.gitignore +10 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +27 -0
  7. data/.rubocop_todo.yml +137 -0
  8. data/CONTRIBUTING.md +47 -0
  9. data/Gemfile +2 -0
  10. data/History.md +4 -0
  11. data/LICENSE +24 -0
  12. data/README.md +218 -0
  13. data/Rakefile +69 -0
  14. data/ReleasePolicy.md +20 -0
  15. data/benchmarks/TradeoffData.csv +65 -0
  16. data/benchmarks/csv_reading.rb +22 -0
  17. data/benchmarks/dataframe_creation.rb +39 -0
  18. data/benchmarks/db_loading.rb +34 -0
  19. data/benchmarks/duplicating.rb +45 -0
  20. data/benchmarks/group_by.rb +32 -0
  21. data/benchmarks/joining.rb +52 -0
  22. data/benchmarks/row_access.rb +41 -0
  23. data/benchmarks/row_assign.rb +36 -0
  24. data/benchmarks/sorting.rb +51 -0
  25. data/benchmarks/statistics.rb +28 -0
  26. data/benchmarks/vector_access.rb +31 -0
  27. data/benchmarks/vector_assign.rb +42 -0
  28. data/benchmarks/where_clause.rb +48 -0
  29. data/benchmarks/where_vs_filter.rb +28 -0
  30. data/daru_lite.gemspec +55 -0
  31. data/images/README.md +5 -0
  32. data/images/con0.png +0 -0
  33. data/images/con1.png +0 -0
  34. data/images/init0.png +0 -0
  35. data/images/init1.png +0 -0
  36. data/images/man0.png +0 -0
  37. data/images/man1.png +0 -0
  38. data/images/man2.png +0 -0
  39. data/images/man3.png +0 -0
  40. data/images/man4.png +0 -0
  41. data/images/man5.png +0 -0
  42. data/images/man6.png +0 -0
  43. data/lib/daru_lite/accessors/array_wrapper.rb +109 -0
  44. data/lib/daru_lite/accessors/dataframe_by_row.rb +25 -0
  45. data/lib/daru_lite/accessors/mdarray_wrapper.rb +7 -0
  46. data/lib/daru_lite/category.rb +929 -0
  47. data/lib/daru_lite/configuration.rb +34 -0
  48. data/lib/daru_lite/core/group_by.rb +403 -0
  49. data/lib/daru_lite/core/merge.rb +270 -0
  50. data/lib/daru_lite/core/query.rb +109 -0
  51. data/lib/daru_lite/dataframe.rb +3080 -0
  52. data/lib/daru_lite/date_time/index.rb +569 -0
  53. data/lib/daru_lite/date_time/offsets.rb +397 -0
  54. data/lib/daru_lite/exceptions.rb +2 -0
  55. data/lib/daru_lite/extensions/which_dsl.rb +53 -0
  56. data/lib/daru_lite/formatters/table.rb +52 -0
  57. data/lib/daru_lite/helpers/array.rb +53 -0
  58. data/lib/daru_lite/index/categorical_index.rb +201 -0
  59. data/lib/daru_lite/index/index.rb +374 -0
  60. data/lib/daru_lite/index/multi_index.rb +374 -0
  61. data/lib/daru_lite/io/csv/converters.rb +21 -0
  62. data/lib/daru_lite/io/io.rb +294 -0
  63. data/lib/daru_lite/io/sql_data_source.rb +97 -0
  64. data/lib/daru_lite/iruby/helpers.rb +38 -0
  65. data/lib/daru_lite/iruby/templates/dataframe.html.erb +5 -0
  66. data/lib/daru_lite/iruby/templates/dataframe_mi.html.erb +5 -0
  67. data/lib/daru_lite/iruby/templates/dataframe_mi_tbody.html.erb +35 -0
  68. data/lib/daru_lite/iruby/templates/dataframe_mi_thead.html.erb +21 -0
  69. data/lib/daru_lite/iruby/templates/dataframe_tbody.html.erb +28 -0
  70. data/lib/daru_lite/iruby/templates/dataframe_thead.html.erb +21 -0
  71. data/lib/daru_lite/iruby/templates/multi_index.html.erb +12 -0
  72. data/lib/daru_lite/iruby/templates/vector.html.erb +5 -0
  73. data/lib/daru_lite/iruby/templates/vector_mi.html.erb +5 -0
  74. data/lib/daru_lite/iruby/templates/vector_mi_tbody.html.erb +26 -0
  75. data/lib/daru_lite/iruby/templates/vector_mi_thead.html.erb +8 -0
  76. data/lib/daru_lite/iruby/templates/vector_tbody.html.erb +17 -0
  77. data/lib/daru_lite/iruby/templates/vector_thead.html.erb +8 -0
  78. data/lib/daru_lite/maths/arithmetic/dataframe.rb +91 -0
  79. data/lib/daru_lite/maths/arithmetic/vector.rb +117 -0
  80. data/lib/daru_lite/maths/statistics/dataframe.rb +202 -0
  81. data/lib/daru_lite/maths/statistics/vector.rb +1019 -0
  82. data/lib/daru_lite/monkeys.rb +56 -0
  83. data/lib/daru_lite/vector.rb +1678 -0
  84. data/lib/daru_lite/version.rb +3 -0
  85. data/lib/daru_lite.rb +99 -0
  86. data/profile/_base.rb +23 -0
  87. data/profile/df_to_a.rb +10 -0
  88. data/profile/filter.rb +13 -0
  89. data/profile/joining.rb +13 -0
  90. data/profile/sorting.rb +12 -0
  91. data/profile/vector_each_with_index.rb +9 -0
  92. data/profile/vector_new.rb +9 -0
  93. data/spec/accessors/array_wrapper_spec.rb +3 -0
  94. data/spec/category_spec.rb +1741 -0
  95. data/spec/core/group_by_spec.rb +655 -0
  96. data/spec/core/merge_spec.rb +179 -0
  97. data/spec/core/query_spec.rb +347 -0
  98. data/spec/daru_lite_spec.rb +22 -0
  99. data/spec/dataframe_spec.rb +4330 -0
  100. data/spec/date_time/data_spec.rb +197 -0
  101. data/spec/date_time/date_time_index_helper_spec.rb +72 -0
  102. data/spec/date_time/index_spec.rb +588 -0
  103. data/spec/date_time/offsets_spec.rb +465 -0
  104. data/spec/extensions/which_dsl_spec.rb +38 -0
  105. data/spec/fixtures/bank2.dat +200 -0
  106. data/spec/fixtures/boolean_converter_test.csv +5 -0
  107. data/spec/fixtures/countries.json +7794 -0
  108. data/spec/fixtures/duplicates.csv +32 -0
  109. data/spec/fixtures/eciresults.html +394 -0
  110. data/spec/fixtures/empties.dat +2 -0
  111. data/spec/fixtures/empty_rows_test.csv +17 -0
  112. data/spec/fixtures/macau.html +3691 -0
  113. data/spec/fixtures/macd_data.csv +150 -0
  114. data/spec/fixtures/matrix_test.csv +100 -0
  115. data/spec/fixtures/moneycontrol.html +6812 -0
  116. data/spec/fixtures/music_data.tsv +2501 -0
  117. data/spec/fixtures/repeated_fields.csv +7 -0
  118. data/spec/fixtures/sales-funnel.csv +18 -0
  119. data/spec/fixtures/scientific_notation.csv +4 -0
  120. data/spec/fixtures/string_converter_test.csv +5 -0
  121. data/spec/fixtures/strings.dat +2 -0
  122. data/spec/fixtures/test_xls.xls +0 -0
  123. data/spec/fixtures/test_xls_2.xls +0 -0
  124. data/spec/fixtures/url_test.txt~ +0 -0
  125. data/spec/fixtures/valid_markup.html +62 -0
  126. data/spec/fixtures/wiki_climate.html +1243 -0
  127. data/spec/fixtures/wiki_table_info.html +631 -0
  128. data/spec/formatters/table_formatter_spec.rb +137 -0
  129. data/spec/helpers_spec.rb +8 -0
  130. data/spec/index/categorical_index_spec.rb +170 -0
  131. data/spec/index/index_spec.rb +417 -0
  132. data/spec/index/multi_index_spec.rb +680 -0
  133. data/spec/io/io_spec.rb +373 -0
  134. data/spec/io/sql_data_source_spec.rb +56 -0
  135. data/spec/iruby/dataframe_spec.rb +170 -0
  136. data/spec/iruby/helpers_spec.rb +49 -0
  137. data/spec/iruby/multi_index_spec.rb +37 -0
  138. data/spec/iruby/vector_spec.rb +105 -0
  139. data/spec/maths/arithmetic/dataframe_spec.rb +148 -0
  140. data/spec/maths/arithmetic/vector_spec.rb +165 -0
  141. data/spec/maths/statistics/dataframe_spec.rb +178 -0
  142. data/spec/maths/statistics/vector_spec.rb +756 -0
  143. data/spec/monkeys_spec.rb +42 -0
  144. data/spec/shared/vector_display_spec.rb +213 -0
  145. data/spec/spec_helper.rb +87 -0
  146. data/spec/support/database_helper.rb +30 -0
  147. data/spec/support/matchers.rb +5 -0
  148. data/spec/vector_spec.rb +2293 -0
  149. metadata +571 -0
@@ -0,0 +1,2293 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe DaruLite::Vector do
4
+ ALL_DTYPES.each do |dtype|
5
+ describe dtype.to_s do
6
+ before do
7
+ @common_all_dtypes = DaruLite::Vector.new(
8
+ [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99],
9
+ dtype: dtype, name: :common_all_dtypes)
10
+ end
11
+
12
+ context "#initialize" do
13
+ before do
14
+ @tuples = [
15
+ [:a, :one, :foo],
16
+ [:a, :two, :bar],
17
+ [:b, :one, :bar],
18
+ [:b, :two, :baz]
19
+ ]
20
+
21
+ @multi_index = DaruLite::MultiIndex.from_tuples(@tuples)
22
+ end
23
+
24
+ it "initializes from an Array" do
25
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :ravan,
26
+ index: [:ek, :don, :teen, :char, :pach], dtype: dtype
27
+
28
+ expect(dv.name) .to eq(:ravan)
29
+ expect(dv.index).to eq(DaruLite::Index.new [:ek, :don, :teen, :char, :pach])
30
+ end
31
+
32
+ it "accepts Index object" do
33
+ idx = DaruLite::Index.new [:yoda, :anakin, :obi, :padme, :r2d2]
34
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga, index: idx, dtype: dtype
35
+
36
+ expect(dv.name) .to eq(:yoga)
37
+ expect(dv.index).to eq(idx)
38
+ end
39
+
40
+ it "accepts a MultiIndex object" do
41
+ dv = DaruLite::Vector.new [1,2,3,4], name: :mi, index: @multi_index, dtype: dtype
42
+
43
+ expect(dv.name).to eq(:mi)
44
+ expect(dv.index).to eq(@multi_index)
45
+ end
46
+
47
+ it "raises error for improper Index" do
48
+ expect {
49
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga, index: [:i, :j, :k]
50
+ }.to raise_error
51
+
52
+ expect {
53
+ idx = DaruLite::Index.new [:i, :j, :k]
54
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoda, index: idx, dtype: dtype
55
+ }.to raise_error
56
+ end
57
+
58
+ it "raises error for improper MultiIndex" do
59
+ expect {
60
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :mi, index: @multi_index
61
+ }.to raise_error
62
+ end
63
+
64
+ it "initializes without specifying an index" do
65
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :vishnu, dtype: dtype
66
+
67
+ expect(dv.index).to eq(DaruLite::Index.new [0,1,2,3,4])
68
+ end
69
+
70
+ it "inserts nils for extra indices" do
71
+ dv = DaruLite::Vector.new [1,2,3], name: :yoga, index: [0,1,2,3,4], dtype: dtype
72
+
73
+ expect(dv).to eq([1,2,3,nil,nil].dv(:yoga,nil, :array))
74
+ end
75
+
76
+ it "inserts nils for extra indices (MultiIndex)" do
77
+ dv = DaruLite::Vector.new [1,2], name: :mi, index: @multi_index, dtype: :array
78
+ expect(dv).to eq(DaruLite::Vector.new([1,2,nil,nil], name: :mi, index: @multi_index, dtype: :array))
79
+ end
80
+
81
+ it "accepts all sorts of objects for indexing" do
82
+ dv = DaruLite::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
86
+ end
87
+
88
+ context "#reorder!" do
89
+ let(:vector_with_dtype) do
90
+ DaruLite::Vector.new(
91
+ [1, 2, 3, 4],
92
+ index: [:a, :b, :c, :d],
93
+ dtype: dtype)
94
+ end
95
+ let(:arranged_vector) do
96
+ DaruLite::Vector.new([4,3,2,1], index: [:d, :c, :b, :a], dtype: dtype)
97
+ end
98
+
99
+ before do
100
+ vector_with_dtype.reorder! [3, 2, 1, 0]
101
+ end
102
+
103
+ it "rearranges with passed order" do
104
+ expect(vector_with_dtype).to eq arranged_vector
105
+ end
106
+
107
+ it "doesn't change dtype" do
108
+ expect(vector_with_dtype.data.class).to eq arranged_vector.data.class
109
+ end
110
+ end
111
+
112
+ context ".new_with_size" do
113
+ it "creates new vector from only size" do
114
+ v1 = DaruLite::Vector.new 10.times.map { nil }, dtype: dtype
115
+ v2 = DaruLite::Vector.new_with_size 10, dtype: dtype
116
+ expect(v2).to eq(v1)
117
+ end if dtype == :array
118
+
119
+ it "creates new vector from only size and value" do
120
+ a = rand
121
+ v1 = DaruLite::Vector.new 10.times.map { a }, dtype: dtype
122
+ v2 = DaruLite::Vector.new_with_size(10, value: a, dtype: dtype)
123
+ expect(v2).to eq(v1)
124
+ end
125
+
126
+ it "accepts block" do
127
+ v1 = DaruLite::Vector.new 10.times.map {|i| i * 2 }
128
+ v2 = DaruLite::Vector.new_with_size(10, dtype: dtype) { |i| i * 2 }
129
+ expect(v2).to eq(v1)
130
+ end
131
+ end
132
+
133
+ context ".[]" do
134
+ it "returns same results as R-c()" do
135
+ reference = DaruLite::Vector.new([0, 4, 5, 6, 10])
136
+ expect(DaruLite::Vector[0, 4, 5, 6, 10]) .to eq(reference)
137
+ expect(DaruLite::Vector[0, 4..6, 10]) .to eq(reference)
138
+ expect(DaruLite::Vector[[0], [4, 5, 6], [10]]) .to eq(reference)
139
+ expect(DaruLite::Vector[[0], [4, [5, [6]]], [10]]).to eq(reference)
140
+
141
+ expect(DaruLite::Vector[[0], DaruLite::Vector.new([4, 5, 6]), [10]])
142
+ .to eq(reference)
143
+ end
144
+ end
145
+
146
+ context "#[]" do
147
+ context DaruLite::Index do
148
+ before :each do
149
+ @dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga,
150
+ index: [:yoda, :anakin, :obi, :padme, :r2d2], dtype: dtype
151
+ end
152
+
153
+ it "returns an element after passing an index" do
154
+ expect(@dv[:yoda]).to eq(1)
155
+ end
156
+
157
+ it "returns an element after passing a numeric index" do
158
+ expect(@dv[0]).to eq(1)
159
+ end
160
+
161
+ it "returns a vector with given indices for multiple indices" do
162
+ expect(@dv[:yoda, :anakin]).to eq(DaruLite::Vector.new([1,2], name: :yoda,
163
+ index: [:yoda, :anakin], dtype: dtype))
164
+ end
165
+
166
+ it "returns a vector with given indices for multiple numeric indices" do
167
+ expect(@dv[0,1]).to eq(DaruLite::Vector.new([1,2], name: :yoda,
168
+ index: [:yoda, :anakin], dtype: dtype))
169
+ end
170
+
171
+ it "returns a vector when specified symbol Range" do
172
+ expect(@dv[:yoda..:anakin]).to eq(DaruLite::Vector.new([1,2],
173
+ index: [:yoda, :anakin], name: :yoga, dtype: dtype))
174
+ end
175
+
176
+ it "returns a vector when specified numeric Range" do
177
+ expect(@dv[3..4]).to eq(DaruLite::Vector.new([4,5], name: :yoga,
178
+ index: [:padme, :r2d2], dtype: dtype))
179
+ end
180
+
181
+ it "returns correct results for index of multiple index" do
182
+ v = DaruLite::Vector.new([1,2,3,4], index: ['a','c',1,:a])
183
+ expect(v['a']).to eq(1)
184
+ expect(v[:a]).to eq(4)
185
+ expect(v[1]).to eq(3)
186
+ expect(v[0]).to eq(1)
187
+ end
188
+
189
+ it "raises exception for invalid index" do
190
+ expect { @dv[:foo] }.to raise_error(IndexError)
191
+ expect { @dv[:obi, :foo] }.to raise_error(IndexError)
192
+ end
193
+ end
194
+
195
+ context DaruLite::MultiIndex do
196
+ before do
197
+ @tuples = [
198
+ [:a,:one,:bar],
199
+ [:a,:one,:baz],
200
+ [:a,:two,:bar],
201
+ [:a,:two,:baz],
202
+ [:b,:one,:bar],
203
+ [:b,:two,:bar],
204
+ [:b,:two,:baz],
205
+ [:b,:one,:foo],
206
+ [:c,:one,:bar],
207
+ [:c,:one,:baz],
208
+ [:c,:two,:foo],
209
+ [:c,:two,:bar],
210
+ [:d,:one,:foo]
211
+ ]
212
+ @multi_index = DaruLite::MultiIndex.from_tuples(@tuples)
213
+ @vector = DaruLite::Vector.new(
214
+ Array.new(13) { |i| i }, index: @multi_index,
215
+ dtype: dtype, name: :mi_vector)
216
+ end
217
+
218
+ it "returns a single element when passed a row number" do
219
+ expect(@vector[1]).to eq(1)
220
+ end
221
+
222
+ it "returns a single element when passed the full tuple" do
223
+ expect(@vector[:a, :one, :baz]).to eq(1)
224
+ end
225
+
226
+ it "returns sub vector when passed first layer of tuple" do
227
+ mi = DaruLite::MultiIndex.from_tuples([
228
+ [:one,:bar],
229
+ [:one,:baz],
230
+ [:two,:bar],
231
+ [:two,:baz]])
232
+ expect(@vector[:a]).to eq(DaruLite::Vector.new([0,1,2,3], index: mi,
233
+ dtype: dtype, name: :sub_vector))
234
+ end
235
+
236
+ it "returns sub vector when passed first and second layer of tuple" do
237
+ mi = DaruLite::MultiIndex.from_tuples([
238
+ [:foo],
239
+ [:bar]])
240
+ expect(@vector[:c,:two]).to eq(DaruLite::Vector.new([10,11], index: mi,
241
+ dtype: dtype, name: :sub_sub_vector))
242
+ end
243
+
244
+ it "returns sub vector not a single element when passed the partial tuple" do
245
+ mi = DaruLite::MultiIndex.from_tuples([[:foo]])
246
+ expect(@vector[:d, :one]).to eq(DaruLite::Vector.new([12], index: mi,
247
+ dtype: dtype, name: :sub_sub_vector))
248
+ end
249
+
250
+ it "returns a vector with corresponding MultiIndex when specified numeric Range" do
251
+ mi = DaruLite::MultiIndex.from_tuples([
252
+ [:a,:two,:baz],
253
+ [:b,:one,:bar],
254
+ [:b,:two,:bar],
255
+ [:b,:two,:baz],
256
+ [:b,:one,:foo],
257
+ [:c,:one,:bar],
258
+ [:c,:one,:baz]
259
+ ])
260
+ expect(@vector[3..9]).to eq(DaruLite::Vector.new([3,4,5,6,7,8,9], index: mi,
261
+ dtype: dtype, name: :slice))
262
+ end
263
+
264
+ it "raises exception for invalid index" do
265
+ expect { @vector[:foo] }.to raise_error(IndexError)
266
+ expect { @vector[:a, :two, :foo] }.to raise_error(IndexError)
267
+ expect { @vector[:x, :one] }.to raise_error(IndexError)
268
+ end
269
+ end
270
+
271
+ context DaruLite::CategoricalIndex do
272
+ # before { skip }
273
+ context "non-numerical index" do
274
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, :b, :a, :a, :c] }
275
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
276
+
277
+ context "single category" do
278
+ context "multiple instances" do
279
+ subject { dv[:a] }
280
+
281
+ it { is_expected.to be_a DaruLite::Vector }
282
+ its(:size) { is_expected.to eq 3 }
283
+ its(:to_a) { is_expected.to eq ['a', 'c', 'd'] }
284
+ its(:index) { is_expected.to eq(
285
+ DaruLite::CategoricalIndex.new([:a, :a, :a])) }
286
+ end
287
+
288
+ context "single instance" do
289
+ subject { dv[:c] }
290
+
291
+ it { is_expected.to eq 'e' }
292
+ end
293
+ end
294
+
295
+ context "multiple categories" do
296
+ subject { dv[:a, :c] }
297
+
298
+ it { is_expected.to be_a DaruLite::Vector }
299
+ its(:size) { is_expected.to eq 4 }
300
+ its(:to_a) { is_expected.to eq ['a', 'c', 'd', 'e'] }
301
+ its(:index) { is_expected.to eq(
302
+ DaruLite::CategoricalIndex.new([:a, :a, :a, :c])) }
303
+ end
304
+
305
+ context "multiple positional indexes" do
306
+ subject { dv[0, 1, 2] }
307
+
308
+ it { is_expected.to be_a DaruLite::Vector }
309
+ its(:size) { is_expected.to eq 3 }
310
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
311
+ its(:index) { is_expected.to eq(
312
+ DaruLite::CategoricalIndex.new([:a, :b, :a])) }
313
+ end
314
+
315
+ context "single positional index" do
316
+ subject { dv[1] }
317
+
318
+ it { is_expected.to eq 'b' }
319
+ end
320
+
321
+ context "invalid category" do
322
+ it { expect { dv[:x] }.to raise_error IndexError }
323
+ end
324
+
325
+ context "invalid positional index" do
326
+ it { expect { dv[30] }.to raise_error IndexError }
327
+ end
328
+ end
329
+
330
+ context "numerical index" do
331
+ let (:idx) { DaruLite::CategoricalIndex.new [1, 1, 2, 2, 3] }
332
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
333
+
334
+ context "single category" do
335
+ context "multiple instances" do
336
+ subject { dv[1] }
337
+
338
+ it { is_expected.to be_a DaruLite::Vector }
339
+ its(:size) { is_expected.to eq 2 }
340
+ its(:to_a) { is_expected.to eq ['a', 'b'] }
341
+ its(:index) { is_expected.to eq(
342
+ DaruLite::CategoricalIndex.new([1, 1])) }
343
+ end
344
+
345
+ context "single instance" do
346
+ subject { dv[3] }
347
+
348
+ it { is_expected.to eq 'e' }
349
+ end
350
+ end
351
+ end
352
+ end
353
+ end
354
+
355
+ context "#at" do
356
+ context DaruLite::Index do
357
+ let (:idx) { DaruLite::Index.new [1, 0, :c] }
358
+ let (:dv) { DaruLite::Vector.new ['a', 'b', 'c'], index: idx }
359
+
360
+ let (:idx_dt) { DaruLite::DateTimeIndex.new(['2017-01-01', '2017-02-01', '2017-03-01']) }
361
+ let (:dv_dt) { DaruLite::Vector.new(['a', 'b', 'c'], index: idx_dt) }
362
+
363
+ context "single position" do
364
+ it { expect(dv.at 1).to eq 'b' }
365
+ end
366
+
367
+ context "multiple positions" do
368
+ subject { dv.at 0, 2 }
369
+
370
+ it { is_expected.to be_a DaruLite::Vector }
371
+ its(:size) { is_expected.to eq 2 }
372
+ its(:to_a) { is_expected.to eq ['a', 'c'] }
373
+ its(:'index.to_a') { is_expected.to eq [1, :c] }
374
+ end
375
+
376
+ context "invalid position" do
377
+ it { expect { dv.at 3 }.to raise_error IndexError }
378
+ end
379
+
380
+ context "invalid positions" do
381
+ it { expect { dv.at 2, 3 }.to raise_error IndexError }
382
+ end
383
+
384
+ context "range" do
385
+ subject { dv.at 0..1 }
386
+
387
+ it { is_expected.to be_a DaruLite::Vector }
388
+ its(:size) { is_expected.to eq 2 }
389
+ its(:to_a) { is_expected.to eq ['a', 'b'] }
390
+ its(:'index.to_a') { is_expected.to eq [1, 0] }
391
+ end
392
+
393
+ context "range with negative end" do
394
+ subject { dv.at 0..-2 }
395
+
396
+ it { is_expected.to be_a DaruLite::Vector }
397
+ its(:size) { is_expected.to eq 2 }
398
+ its(:to_a) { is_expected.to eq ['a', 'b'] }
399
+ its(:'index.to_a') { is_expected.to eq [1, 0] }
400
+ end
401
+
402
+ context "range with single element" do
403
+ subject { dv.at 0..0 }
404
+
405
+ it { is_expected.to be_a DaruLite::Vector }
406
+ its(:size) { is_expected.to eq 1 }
407
+ its(:to_a) { is_expected.to eq ['a'] }
408
+ its(:'index.to_a') { is_expected.to eq [1] }
409
+ end
410
+
411
+ context "Splat .at on DateTime index" do
412
+ subject { dv_dt.at(*[1,2]) }
413
+
414
+ it { is_expected.to be_a DaruLite::Vector }
415
+ its(:size) { is_expected.to eq 2 }
416
+ its(:to_a) { is_expected.to eq ['b', 'c'] }
417
+ its(:'index.to_a') { is_expected.to eq ['2017-02-01', '2017-03-01'] }
418
+ end
419
+ end
420
+
421
+ context DaruLite::MultiIndex do
422
+ let (:idx) do
423
+ DaruLite::MultiIndex.from_tuples [
424
+ [:a,:one,:bar],
425
+ [:a,:one,:baz],
426
+ [:b,:two,:bar],
427
+ [:a,:two,:baz],
428
+ ]
429
+ end
430
+ let (:dv) { DaruLite::Vector.new 1..4, index: idx }
431
+
432
+ context "single position" do
433
+ it { expect(dv.at 1).to eq 2 }
434
+ end
435
+
436
+ context "multiple positions" do
437
+ subject { dv.at 2, 3 }
438
+
439
+ it { is_expected.to be_a DaruLite::Vector }
440
+ its(:size) { is_expected.to eq 2 }
441
+ its(:to_a) { is_expected.to eq [3, 4] }
442
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar],
443
+ [:a, :two, :baz]] }
444
+ end
445
+
446
+ context "invalid position" do
447
+ it { expect { dv.at 4 }.to raise_error IndexError }
448
+ end
449
+
450
+ context "invalid positions" do
451
+ it { expect { dv.at 2, 4 }.to raise_error IndexError }
452
+ end
453
+
454
+ context "range" do
455
+ subject { dv.at 2..3 }
456
+
457
+ it { is_expected.to be_a DaruLite::Vector }
458
+ its(:size) { is_expected.to eq 2 }
459
+ its(:to_a) { is_expected.to eq [3, 4] }
460
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar],
461
+ [:a, :two, :baz]] }
462
+ end
463
+
464
+ context "range with negative end" do
465
+ subject { dv.at 2..-1 }
466
+
467
+ it { is_expected.to be_a DaruLite::Vector }
468
+ its(:size) { is_expected.to eq 2 }
469
+ its(:to_a) { is_expected.to eq [3, 4] }
470
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar],
471
+ [:a, :two, :baz]] }
472
+ end
473
+
474
+ context "range with single element" do
475
+ subject { dv.at 2..2 }
476
+
477
+ it { is_expected.to be_a DaruLite::Vector }
478
+ its(:size) { is_expected.to eq 1 }
479
+ its(:to_a) { is_expected.to eq [3] }
480
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar]] }
481
+ end
482
+ end
483
+
484
+ context DaruLite::CategoricalIndex do
485
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, 1, 1, :a, :c] }
486
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
487
+
488
+ context "multiple positional indexes" do
489
+ subject { dv.at 0, 1, 2 }
490
+
491
+ it { is_expected.to be_a DaruLite::Vector }
492
+ its(:size) { is_expected.to eq 3 }
493
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
494
+ its(:index) { is_expected.to eq(
495
+ DaruLite::CategoricalIndex.new([:a, 1, 1])) }
496
+ end
497
+
498
+ context "single positional index" do
499
+ subject { dv.at 1 }
500
+
501
+ it { is_expected.to eq 'b' }
502
+ end
503
+
504
+ context "invalid position" do
505
+ it { expect { dv.at 5 }.to raise_error IndexError }
506
+ end
507
+
508
+ context "invalid positions" do
509
+ it { expect { dv.at 2, 5 }.to raise_error IndexError }
510
+ end
511
+
512
+ context "range" do
513
+ subject { dv.at 0..2 }
514
+
515
+ it { is_expected.to be_a DaruLite::Vector }
516
+ its(:size) { is_expected.to eq 3 }
517
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
518
+ its(:index) { is_expected.to eq(
519
+ DaruLite::CategoricalIndex.new([:a, 1, 1])) }
520
+ end
521
+
522
+ context "range with negative end" do
523
+ subject { dv.at 0..-3 }
524
+
525
+ it { is_expected.to be_a DaruLite::Vector }
526
+ its(:size) { is_expected.to eq 3 }
527
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
528
+ its(:index) { is_expected.to eq(
529
+ DaruLite::CategoricalIndex.new([:a, 1, 1])) }
530
+ end
531
+
532
+ context "range with single element" do
533
+ subject { dv.at 0..0 }
534
+
535
+ it { is_expected.to be_a DaruLite::Vector }
536
+ its(:size) { is_expected.to eq 1 }
537
+ its(:to_a) { is_expected.to eq ['a'] }
538
+ its(:index) { is_expected.to eq(
539
+ DaruLite::CategoricalIndex.new([:a])) }
540
+ end
541
+ end
542
+ end
543
+
544
+ context "#[]=" do
545
+ context DaruLite::Index do
546
+ before :each do
547
+ @dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga,
548
+ index: [:yoda, :anakin, :obi, :padme, :r2d2], dtype: dtype
549
+ end
550
+
551
+ it "assigns at the specified index" do
552
+ @dv[:yoda] = 666
553
+ expect(@dv[:yoda]).to eq(666)
554
+ end
555
+
556
+ it "assigns at the specified Integer index" do
557
+ @dv[0] = 666
558
+ expect(@dv[:yoda]).to eq(666)
559
+ end
560
+
561
+ it "sets dtype to Array if a nil is assigned" do
562
+ @dv[0] = nil
563
+ expect(@dv.dtype).to eq(:array)
564
+ end
565
+
566
+ it "assigns correctly for a mixed index Vector" do
567
+ v = DaruLite::Vector.new [1,2,3,4], index: ['a',:a,0,66]
568
+ v['a'] = 666
569
+ expect(v['a']).to eq(666)
570
+
571
+ v[0] = 666
572
+ expect(v[0]).to eq(666)
573
+
574
+ v[3] = 666
575
+ expect(v[3]).to eq(666)
576
+
577
+ expect(v).to eq(DaruLite::Vector.new([666,2,666,666],
578
+ index: ['a',:a,0,66]))
579
+ end
580
+ end
581
+
582
+ context DaruLite::MultiIndex do
583
+ before :each do
584
+ @tuples = [
585
+ [:a,:one,:bar],
586
+ [:a,:one,:baz],
587
+ [:a,:two,:bar],
588
+ [:a,:two,:baz],
589
+ [:b,:one,:bar],
590
+ [:b,:two,:bar],
591
+ [:b,:two,:baz],
592
+ [:b,:one,:foo],
593
+ [:c,:one,:bar],
594
+ [:c,:one,:baz],
595
+ [:c,:two,:foo],
596
+ [:c,:two,:bar]
597
+ ]
598
+ @multi_index = DaruLite::MultiIndex.from_tuples(@tuples)
599
+ @vector = DaruLite::Vector.new Array.new(12) { |i| i }, index: @multi_index,
600
+ dtype: dtype, name: :mi_vector
601
+ end
602
+
603
+ it "assigns all lower layer indices when specified a first layer index" do
604
+ @vector[:b] = 69
605
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,69,69,69,69,8,9,10,11],
606
+ index: @multi_index, name: :top_layer_assignment, dtype: dtype
607
+ ))
608
+ end
609
+
610
+ it "assigns all lower indices when specified first and second layer index" do
611
+ @vector[:b, :one] = 69
612
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,69,5,6,69,8,9,10,11],
613
+ index: @multi_index, name: :second_layer_assignment, dtype: dtype))
614
+ end
615
+
616
+ it "assigns just the precise value when specified complete tuple" do
617
+ @vector[:b, :one, :foo] = 69
618
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,4,5,6,69,8,9,10,11],
619
+ index: @multi_index, name: :precise_assignment, dtype: dtype))
620
+ end
621
+
622
+ it "assigns correctly when numeric index" do
623
+ @vector[7] = 69
624
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,4,5,6,69,8,9,10,11],
625
+ index: @multi_index, name: :precise_assignment, dtype: dtype))
626
+ end
627
+
628
+ it "fails predictably on unknown index" do
629
+ expect { @vector[:d] = 69 }.to raise_error(IndexError)
630
+ expect { @vector[:b, :three] = 69 }.to raise_error(IndexError)
631
+ expect { @vector[:b, :two, :test] = 69 }.to raise_error(IndexError)
632
+ end
633
+ end
634
+
635
+ context DaruLite::CategoricalIndex do
636
+ context "non-numerical index" do
637
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, :b, :a, :a, :c] }
638
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
639
+
640
+ context "single category" do
641
+ context "multiple instances" do
642
+ subject { dv }
643
+ before { dv[:a] = 'x' }
644
+
645
+ its(:size) { is_expected.to eq 5 }
646
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x', 'x', 'e'] }
647
+ its(:index) { is_expected.to eq idx }
648
+ end
649
+
650
+ context "single instance" do
651
+ subject { dv }
652
+ before { dv[:b] = 'x' }
653
+
654
+ its(:size) { is_expected.to eq 5 }
655
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
656
+ its(:index) { is_expected.to eq idx }
657
+ end
658
+ end
659
+
660
+ context "multiple categories" do
661
+ subject { dv }
662
+ before { dv[:a, :c] = 'x' }
663
+
664
+ its(:size) { is_expected.to eq 5 }
665
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x', 'x', 'x'] }
666
+ its(:index) { is_expected.to eq idx }
667
+ end
668
+
669
+ context "multiple positional indexes" do
670
+ subject { dv }
671
+ before { dv[0, 1, 2] = 'x' }
672
+
673
+ its(:size) { is_expected.to eq 5 }
674
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'd', 'e'] }
675
+ its(:index) { is_expected.to eq idx }
676
+ end
677
+
678
+ context "single positional index" do
679
+ subject { dv }
680
+ before { dv[1] = 'x' }
681
+
682
+ its(:size) { is_expected.to eq 5 }
683
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
684
+ its(:index) { is_expected.to eq idx }
685
+ end
686
+
687
+ context "invalid category" do
688
+ it { expect { dv[:x] = 'x' }.to raise_error IndexError }
689
+ end
690
+
691
+ context "invalid positional index" do
692
+ it { expect { dv[30] = 'x'}.to raise_error IndexError }
693
+ end
694
+ end
695
+
696
+ context "numerical index" do
697
+ let (:idx) { DaruLite::CategoricalIndex.new [1, 1, 2, 2, 3] }
698
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
699
+
700
+ context "single category" do
701
+ subject { dv }
702
+ before { dv[1] = 'x' }
703
+
704
+ its(:size) { is_expected.to eq 5 }
705
+ its(:to_a) { is_expected.to eq ['x', 'x', 'c', 'd', 'e'] }
706
+ its(:index) { is_expected.to eq idx }
707
+ end
708
+
709
+ context "multiple categories" do
710
+ subject { dv }
711
+ before { dv[1, 2] = 'x' }
712
+
713
+ its(:size) { is_expected.to eq 5 }
714
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'x', 'e'] }
715
+ its(:index) { is_expected.to eq idx }
716
+ end
717
+ end
718
+ end
719
+ end
720
+
721
+ context "#==" do
722
+ subject { vector == other_vector }
723
+
724
+ let(:vector) { DaruLite::Vector.new(data, name:, index:, dtype:) }
725
+ let(:data) { [1, 2, 3, 4, 5] }
726
+ let(:index) { [:yoda, :anakin, :obi, :padme, :r2d2] }
727
+ let(:name) { :yoga }
728
+ let(:other_vector) { DaruLite::Vector.new(other_data, name: other_name, index: other_index, dtype:) }
729
+ let(:other_data) { data }
730
+ let(:other_index) { index }
731
+ let(:other_name) { name }
732
+
733
+ context DaruLite::Index do
734
+
735
+ context 'vectors are identical' do
736
+ it { is_expected.to eq(true) }
737
+ end
738
+
739
+ context 'name is different' do
740
+ let(:other_name) { :yogi }
741
+
742
+ it { is_expected.to eq(true) }
743
+ end
744
+
745
+ context 'data is different' do
746
+ let(:other_data) { [2, 1, 3, 4, 5] }
747
+
748
+ it { is_expected.to eq(false) }
749
+ end
750
+
751
+ context 'data size is different' do
752
+ let(:other_data) { [1, 2, 3, 4, 5, 6] }
753
+ let(:other_index) { [:yoda, :anakin, :obi, :padme, :r2d2, :darth_vader] }
754
+
755
+ it { is_expected.to eq(false) }
756
+ end
757
+
758
+ context 'vector index is different' do
759
+ let(:other_index) { [:anakin, :yoda, :darth_vader, :padme, :r2d2] }
760
+
761
+ it { is_expected.to eq(false) }
762
+ end
763
+ end
764
+
765
+ context DaruLite::MultiIndex do
766
+ let(:tuples) do
767
+ [
768
+ [:a,:one,:bar],
769
+ [:a,:one,:baz],
770
+ [:a,:two,:bar],
771
+ [:a,:two,:baz],
772
+ [:b,:one,:bar],
773
+ [:b,:two,:bar],
774
+ [:b,:two,:baz],
775
+ [:b,:one,:foo],
776
+ [:c,:one,:bar],
777
+ [:c,:one,:baz],
778
+ [:c,:two,:foo],
779
+ [:c,:two,:bar]
780
+ ]
781
+ end
782
+ let(:data) { Array.new(12) { |i| i } }
783
+ let(:index) { DaruLite::MultiIndex.from_tuples(tuples) }
784
+
785
+ context 'vectors are identical' do
786
+ it { is_expected.to eq(true) }
787
+ end
788
+
789
+ context 'name is different' do
790
+ let(:other_name) { :yogi }
791
+
792
+ it { is_expected.to eq(true) }
793
+ end
794
+
795
+ context 'data is different' do
796
+ let(:other_data) { Array.new(12) { |i| i * i } }
797
+
798
+ it { is_expected.to eq(false) }
799
+ end
800
+
801
+ context 'data size is different' do
802
+ let(:other_data) { Array.new(10) { |i| i * i } }
803
+
804
+ it { is_expected.to eq(false) }
805
+ end
806
+
807
+ context 'vector index is different' do
808
+ let(:other_tuples) do
809
+ [
810
+ [:a,:two,:bar],
811
+ [:a,:one,:baz],
812
+ [:a,:two,:bar],
813
+ [:a,:two,:baz],
814
+ [:b,:one,:bar],
815
+ [:b,:two,:bar],
816
+ [:b,:two,:baz],
817
+ [:b,:one,:foo],
818
+ [:c,:one,:bar],
819
+ [:c,:one,:baz],
820
+ [:c,:two,:foo],
821
+ [:c,:two,:bar]
822
+ ]
823
+ end
824
+ let(:other_index) { DaruLite::MultiIndex.from_tuples(other_tuples) }
825
+
826
+ it { is_expected.to eq(false) }
827
+ end
828
+ end
829
+
830
+ context DaruLite::CategoricalIndex do
831
+ let(:index) { DaruLite::CategoricalIndex.new([:yoda, :r2d2, :obi, :padme, :r2d2]) }
832
+
833
+ context 'vectors are identical' do
834
+ it { is_expected.to eq(true) }
835
+ end
836
+
837
+ context 'name is different' do
838
+ let(:other_name) { :yogi }
839
+
840
+ it { is_expected.to eq(true) }
841
+ end
842
+
843
+ context 'data is different' do
844
+ let(:other_data) { [2, 1, 3, 4, 5] }
845
+
846
+ it { is_expected.to eq(false) }
847
+ end
848
+
849
+ context 'data size is different' do
850
+ let(:other_data) { [1, 2, 3, 4, 5, 6] }
851
+ let(:other_index) { [:yoda, :anakin, :obi, :padme, :r2d2, :darth_vader] }
852
+
853
+ it { is_expected.to eq(false) }
854
+ end
855
+
856
+ context 'vector index is different' do
857
+ let(:other_index) { DaruLite::CategoricalIndex.new([:r2d2, :yoda, :obi, :padme, :r2d2]) }
858
+
859
+ it { is_expected.to eq(false) }
860
+ end
861
+ end
862
+ end
863
+
864
+ context "#set_at" do
865
+ context DaruLite::Index do
866
+ let (:idx) { DaruLite::Index.new [1, 0, :c] }
867
+ let (:dv) { DaruLite::Vector.new ['a', 'b', 'c'], index: idx }
868
+
869
+ context "single position" do
870
+ subject { dv }
871
+ before { dv.set_at [1], 'x' }
872
+
873
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c'] }
874
+ end
875
+
876
+ context "multiple positions" do
877
+ subject { dv }
878
+ before { dv.set_at [0, 2], 'x' }
879
+
880
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x'] }
881
+ end
882
+
883
+ context "invalid position" do
884
+ it { expect { dv.set_at [3], 'x' }.to raise_error IndexError }
885
+ end
886
+
887
+ context "invalid positions" do
888
+ it { expect { dv.set_at [2, 3], 'x' }.to raise_error IndexError }
889
+ end
890
+ end
891
+
892
+ context DaruLite::MultiIndex do
893
+ let(:idx) do
894
+ DaruLite::MultiIndex.from_tuples [
895
+ [:a,:one,:bar],
896
+ [:a,:one,:baz],
897
+ [:b,:two,:bar],
898
+ [:a,:two,:baz],
899
+ ]
900
+ end
901
+ let(:dv) { DaruLite::Vector.new 1..4, index: idx }
902
+
903
+ context "single position" do
904
+ subject { dv }
905
+ before { dv.set_at [1], 'x' }
906
+
907
+ its(:to_a) { is_expected.to eq [1, 'x', 3, 4] }
908
+ end
909
+
910
+ context "multiple positions" do
911
+ subject { dv }
912
+ before { dv.set_at [2, 3], 'x' }
913
+
914
+ its(:to_a) { is_expected.to eq [1, 2, 'x', 'x'] }
915
+ end
916
+
917
+ context "invalid position" do
918
+ it { expect { dv.set_at [4], 'x' }.to raise_error IndexError }
919
+ end
920
+
921
+ context "invalid positions" do
922
+ it { expect { dv.set_at [2, 4], 'x' }.to raise_error IndexError }
923
+ end
924
+ end
925
+
926
+ context DaruLite::CategoricalIndex do
927
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, 1, 1, :a, :c] }
928
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
929
+
930
+ context "multiple positional indexes" do
931
+ subject { dv }
932
+ before { dv.set_at [0, 1, 2], 'x' }
933
+
934
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'd', 'e'] }
935
+ end
936
+
937
+ context "single positional index" do
938
+ subject { dv }
939
+ before { dv.set_at [1], 'x' }
940
+
941
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
942
+ end
943
+
944
+ context "invalid position" do
945
+ it { expect { dv.set_at [5], 'x' }.to raise_error IndexError }
946
+ end
947
+
948
+ context "invalid positions" do
949
+ it { expect { dv.set_at [2, 5], 'x' }.to raise_error IndexError }
950
+ end
951
+ end
952
+ end
953
+
954
+ context '#head' do
955
+ subject(:vector) do
956
+ DaruLite::Vector.new (1..20).to_a, dtype: dtype
957
+ end
958
+
959
+ it 'takes 10 by default' do
960
+ expect(vector.head).to eq DaruLite::Vector.new (1..10).to_a
961
+ end
962
+
963
+ it 'takes num if provided' do
964
+ expect(vector.head(3)).to eq DaruLite::Vector.new (1..3).to_a
965
+ end
966
+
967
+ it 'does not fail on too large num' do
968
+ expect(vector.head(3000)).to eq vector
969
+ end
970
+ end
971
+
972
+ context '#tail' do
973
+ subject(:vector) do
974
+ DaruLite::Vector.new (1..20).to_a, dtype: dtype
975
+ end
976
+
977
+ it 'takes 10 by default' do
978
+ expect(vector.tail).to eq DaruLite::Vector.new (11..20).to_a, index: (10..19).to_a
979
+ end
980
+
981
+ it 'takes num if provided' do
982
+ expect(vector.tail(3)).to eq DaruLite::Vector.new (18..20).to_a, index: (17..19).to_a
983
+ end
984
+
985
+ it 'does not fail on too large num' do
986
+ expect(vector.tail(3000)).to eq vector
987
+ end
988
+ end
989
+
990
+ context '#last' do
991
+ subject(:vector) do
992
+ DaruLite::Vector.new (1..20).to_a, dtype: dtype
993
+ end
994
+
995
+ it 'takes 1 by default' do
996
+ expect(vector.last).to eq 20
997
+ end
998
+
999
+ it 'takes num if provided' do
1000
+ expect(vector.last(3)).to eq DaruLite::Vector.new (18..20).to_a, index: (17..19).to_a
1001
+ end
1002
+
1003
+ it 'does not fail on too large num' do
1004
+ expect(vector.last(3000)).to eq vector
1005
+ end
1006
+ end
1007
+
1008
+ context "#concat" do
1009
+ before :each do
1010
+ @dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga,
1011
+ index: [:warwick, :thompson, :jackson, :fender, :esp], dtype: dtype
1012
+ end
1013
+
1014
+ it "concatenates a new element at the end of vector with index" do
1015
+ @dv.concat 6, :ibanez
1016
+
1017
+ expect(@dv.index) .to eq(
1018
+ DaruLite::Index.new([:warwick, :thompson, :jackson, :fender, :esp, :ibanez]))
1019
+ expect(@dv[:ibanez]).to eq(6)
1020
+ expect(@dv[5]) .to eq(6)
1021
+ end
1022
+
1023
+ it "raises error if index not specified" do
1024
+ expect {
1025
+ @dv.concat 6
1026
+ }.to raise_error
1027
+ end
1028
+ end
1029
+
1030
+ context "#delete" do
1031
+ context DaruLite::Index do
1032
+ it "deletes specified value in the vector" do
1033
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :a, dtype: dtype
1034
+
1035
+ dv.delete 3
1036
+ expect(dv).to eq(
1037
+ DaruLite::Vector.new [1,2,4,5], name: :a, index: [0,1,3,4])
1038
+ end
1039
+ end
1040
+ end
1041
+
1042
+ context "#delete_at" do
1043
+ context DaruLite::Index do
1044
+ before :each do
1045
+ @dv = DaruLite::Vector.new [1,2,3,4,5], name: :a,
1046
+ index: [:one, :two, :three, :four, :five], dtype: dtype
1047
+ end
1048
+
1049
+ it "deletes element of specified index" do
1050
+ @dv.delete_at :one
1051
+
1052
+ expect(@dv).to eq(DaruLite::Vector.new [2,3,4,5], name: :a,
1053
+ index: [:two, :three, :four, :five], dtype: dtype)
1054
+ end
1055
+
1056
+ it "deletes element of specified integer index" do
1057
+ pending
1058
+ @dv.delete_at 2
1059
+
1060
+ expect(@dv).to eq(DaruLite::Vector.new [1,2,4,5], name: :a,
1061
+ index: [:one, :two, :four, :five], dtype: dtype)
1062
+ end
1063
+ end
1064
+ end
1065
+
1066
+ context "#delete_if" do
1067
+ it "deletes elements if block evaluates to true" do
1068
+ v = DaruLite::Vector.new [1,22,33,45,65,32,524,656,123,99,77], dtype: dtype
1069
+ ret = v.delete_if { |d| d % 11 == 0 }
1070
+ expect(ret).to eq(
1071
+ DaruLite::Vector.new([1,45,65,32,524,656,123],
1072
+ index: [0,3,4,5,6,7,8], dtype: dtype))
1073
+ expect(ret.dtype).to eq(dtype)
1074
+ end
1075
+ end
1076
+
1077
+ context "#keep_if" do
1078
+ it "keeps elements if block returns true" do
1079
+ v = DaruLite::Vector.new([1,22,33,45,65,32,524,656,123,99,77], dtype: dtype)
1080
+ ret = v.keep_if { |d| d < 35 }
1081
+
1082
+ expect(ret).to eq(
1083
+ DaruLite::Vector.new([1,22,33,32], index: [0,1,2,5], dtype: dtype))
1084
+ expect(v.dtype).to eq(ret.dtype)
1085
+ end
1086
+ end
1087
+
1088
+ context "#index_of" do
1089
+ context DaruLite::Index do
1090
+ it "returns index of specified value" do
1091
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :a,
1092
+ index: [:one, :two, :three, :four, :five], dtype: dtype
1093
+
1094
+ expect(dv.index_of(1)).to eq(:one)
1095
+ end
1096
+ end
1097
+
1098
+ context DaruLite::MultiIndex do
1099
+ it "returns tuple of specified value" do
1100
+ mi = DaruLite::MultiIndex.from_tuples([
1101
+ [:a,:two,:bar],
1102
+ [:a,:two,:baz],
1103
+ [:b,:one,:bar],
1104
+ [:b,:two,:bar]
1105
+ ])
1106
+ vector = DaruLite::Vector.new([1,2,3,4], index: mi, dtype: dtype)
1107
+ expect(vector.index_of(3)).to eq([:b,:one,:bar])
1108
+ end
1109
+ end
1110
+ end
1111
+
1112
+ context "#to_df" do
1113
+ let(:dv) { DaruLite::Vector.new(['a','b','c'], name: :my_dv, index: ['alpha', 'beta', 'gamma']) }
1114
+ let(:df) { dv.to_df }
1115
+
1116
+ it 'is a dataframe' do
1117
+ expect(df).to be_a DaruLite::DataFrame
1118
+ end
1119
+
1120
+ it 'converts the vector to a single-vector dataframe' do
1121
+ expect(df[:my_dv]).to eq dv
1122
+ end
1123
+
1124
+ it 'has the same index as the original vector' do
1125
+ expect(df.index).to eq dv.index
1126
+ end
1127
+
1128
+ it 'has the same name as the vector' do
1129
+ expect(df.name).to eq :my_dv
1130
+ end
1131
+ end
1132
+
1133
+ context "#to_h" do
1134
+ context DaruLite::Index do
1135
+ it "returns the vector as a hash" do
1136
+ dv = DaruLite::Vector.new [1,2,3,4,5], name: :a,
1137
+ index: [:one, :two, :three, :four, :five], dtype: dtype
1138
+
1139
+ expect(dv.to_h).to eq({one: 1, two: 2, three: 3, four: 4, five: 5})
1140
+ end
1141
+ end
1142
+
1143
+ context DaruLite::MultiIndex do
1144
+ pending
1145
+ # it "returns vector as a Hash" do
1146
+ # pending
1147
+ # mi = DaruLite::MultiIndex.from_tuples([
1148
+ # [:a,:two,:bar],
1149
+ # [:a,:two,:baz],
1150
+ # [:b,:one,:bar],
1151
+ # [:b,:two,:bar]
1152
+ # ])
1153
+ # vector = DaruLite::Vector.new([1,2,3,4], index: mi, dtype: dtype)
1154
+ # expect(vector.to_h).to eq({
1155
+ # [:a,:two,:bar] => 1,
1156
+ # [:a,:two,:baz] => 2,
1157
+ # [:b,:one,:bar] => 3,
1158
+ # [:b,:two,:bar] => 4
1159
+ # })
1160
+ # end
1161
+ end
1162
+ end
1163
+
1164
+ context "#to_json" do
1165
+ subject(:vector) do
1166
+ DaruLite::Vector.new [1,2,3,4,5], name: :a,
1167
+ index: [:one, :two, :three, :four, :five], dtype: dtype
1168
+ end
1169
+
1170
+ its(:to_json) { is_expected.to eq(vector.to_h.to_json) }
1171
+ end
1172
+
1173
+ context "#to_s" do
1174
+ before do
1175
+ @v = DaruLite::Vector.new ["a", "b"], index: [1, 2]
1176
+ end
1177
+
1178
+ it 'produces a class, size description' do
1179
+ expect(@v.to_s).to eq("#<DaruLite::Vector(2)>")
1180
+ end
1181
+
1182
+ it 'produces a class, name, size description' do
1183
+ @v.name = "Test"
1184
+ expect(@v.to_s).to eq("#<DaruLite::Vector: Test(2)>")
1185
+ end
1186
+
1187
+ it 'produces a class, name, size description when the name is a symbol' do
1188
+ @v.name = :Test
1189
+ expect(@v.to_s).to eq("#<DaruLite::Vector: Test(2)>")
1190
+ end
1191
+ end
1192
+
1193
+ context "#uniq" do
1194
+ before do
1195
+ @v = DaruLite::Vector.new [1, 2, 2, 2.0, 3, 3.0], index:[:a, :b, :c, :d, :e, :f]
1196
+ end
1197
+ it "keeps only unique values" do
1198
+ expect(@v.uniq).to eq(DaruLite::Vector.new [1, 2, 2.0, 3, 3.0], index: [:a, :b, :d, :e, :f])
1199
+ end
1200
+ end
1201
+
1202
+ context "#cast" do
1203
+ ALL_DTYPES.each do |new_dtype|
1204
+ it "casts from #{dtype} to #{new_dtype}" do
1205
+ v = DaruLite::Vector.new [1,2,3,4], dtype: dtype
1206
+ v.cast(dtype: new_dtype)
1207
+ expect(v.dtype).to eq(new_dtype)
1208
+ end
1209
+ end
1210
+ end
1211
+
1212
+ context "#sort" do
1213
+ context DaruLite::Index do
1214
+ before do
1215
+ @dv = DaruLite::Vector.new [33,2,15,332,1], name: :dv, index: [:a, :b, :c, :d, :e]
1216
+ end
1217
+
1218
+ it "sorts the vector with defaults and returns a new vector, preserving indexing" do
1219
+ expect(@dv.sort).to eq(DaruLite::Vector.new([1,2,15,33,332], name: :dv, index: [:e, :b, :c, :a, :d]))
1220
+ end
1221
+
1222
+ it "sorts the vector in descending order" do
1223
+ expect(@dv.sort(ascending: false)).to eq(DaruLite::Vector.new([332,33,15,2,1], name: :dv, index: [:d, :a, :c, :b, :e]))
1224
+ end
1225
+
1226
+ it "accepts a block" do
1227
+ str_dv = DaruLite::Vector.new ["My Jazz Guitar", "Jazz", "My", "Guitar"]
1228
+
1229
+ sorted = str_dv.sort { |a,b| a.length <=> b.length }
1230
+ expect(sorted).to eq(DaruLite::Vector.new(["My", "Jazz", "Guitar", "My Jazz Guitar"], index: [2,1,3,0]))
1231
+ end
1232
+
1233
+ it "places nils near the beginning of the vector when sorting ascendingly" do
1234
+ with_nils = DaruLite::Vector.new [22,4,nil,111,nil,2]
1235
+
1236
+ expect(with_nils.sort).to eq(DaruLite::Vector.new([nil,nil,2,4,22,111], index: [2,4,5,1,0,3]))
1237
+ end if dtype == :array
1238
+
1239
+ it "places nils near the beginning of the vector when sorting descendingly" do
1240
+ with_nils = DaruLite::Vector.new [22,4,nil,111,nil,2]
1241
+
1242
+ expect(with_nils.sort(ascending: false)).to eq(
1243
+ DaruLite::Vector.new [111,22,4,2,nil,nil], index: [3,0,1,5,4,2])
1244
+ end
1245
+
1246
+ it "correctly sorts vector in ascending order with non-numeric data and nils" do
1247
+ non_numeric = DaruLite::Vector.new ['a','b', nil, 'aa', '1234', nil]
1248
+
1249
+ expect(non_numeric.sort(ascending: true)).to eq(
1250
+ DaruLite::Vector.new [nil,nil,'1234','a','aa','b'], index: [2,5,4,0,3,1])
1251
+ end
1252
+
1253
+ it "correctly sorts vector in descending order with non-numeric data and nils" do
1254
+ non_numeric = DaruLite::Vector.new ['a','b', nil, 'aa', '1234', nil]
1255
+
1256
+ expect(non_numeric.sort(ascending: false)).to eq(
1257
+ DaruLite::Vector.new ['b','aa','a','1234',nil,nil], index: [1,3,0,4,5,2])
1258
+ end
1259
+ end
1260
+
1261
+ context DaruLite::MultiIndex do
1262
+ before do
1263
+ mi = DaruLite::MultiIndex.from_tuples([
1264
+ [:a, :one, :foo],
1265
+ [:a, :two, :bar],
1266
+ [:b, :one, :bar],
1267
+ [:b, :two, :baz],
1268
+ [:b, :three, :bar]
1269
+ ])
1270
+ @vector = DaruLite::Vector.new([44,22,111,0,-56], index: mi, name: :unsorted,
1271
+ dtype: dtype)
1272
+ end
1273
+
1274
+ it "sorts vector" do
1275
+ mi_asc = DaruLite::MultiIndex.from_tuples([
1276
+ [:b, :three, :bar],
1277
+ [:b, :two, :baz],
1278
+ [:a, :two, :bar],
1279
+ [:a, :one, :foo],
1280
+ [:b, :one, :bar]
1281
+ ])
1282
+ expect(@vector.sort).to eq(DaruLite::Vector.new([-56,0,22,44,111], index: mi_asc,
1283
+ name: :ascending, dtype: dtype))
1284
+ end
1285
+
1286
+ it "sorts in descending" do
1287
+ mi_dsc = DaruLite::MultiIndex.from_tuples([
1288
+ [:b, :one, :bar],
1289
+ [:a, :one, :foo],
1290
+ [:a, :two, :bar],
1291
+ [:b, :two, :baz],
1292
+ [:b, :three, :bar]
1293
+ ])
1294
+ expect(@vector.sort(ascending: false)).to eq(DaruLite::Vector.new(
1295
+ [111,44,22,0,-56], index: mi_dsc, name: :descending, dtype: dtype))
1296
+ end
1297
+
1298
+ it "sorts using the supplied block" do
1299
+ mi_abs = DaruLite::MultiIndex.from_tuples([
1300
+ [:b, :two, :baz],
1301
+ [:a, :two, :bar],
1302
+ [:a, :one, :foo],
1303
+ [:b, :three, :bar],
1304
+ [:b, :one, :bar]
1305
+ ])
1306
+ expect(@vector.sort { |a,b| a.abs <=> b.abs }).to eq(DaruLite::Vector.new(
1307
+ [0,22,44,-56,111], index: mi_abs, name: :sort_abs, dtype: dtype))
1308
+ end
1309
+ end
1310
+
1311
+ context DaruLite::CategoricalIndex do
1312
+ let(:idx) { DaruLite::CategoricalIndex.new [:a, 1, :a, 1, :c] }
1313
+ let(:dv_numeric) { DaruLite::Vector.new [4, 5, 3, 2, 1], index: idx }
1314
+ let(:dv_string) { DaruLite::Vector.new ['xxxx', 'zzzzz', 'ccc', 'bb', 'a'], index: idx }
1315
+ let(:dv_nil) { DaruLite::Vector.new [3, nil, 2, 1, -1], index: idx }
1316
+
1317
+ context "increasing order" do
1318
+ context "numeric" do
1319
+ subject { dv_numeric.sort }
1320
+
1321
+ its(:size) { is_expected.to eq 5 }
1322
+ its(:to_a) { is_expected.to eq [1, 2, 3, 4, 5] }
1323
+ its(:'index.to_a') { is_expected.to eq [:c, 1, :a, :a, 1] }
1324
+ end
1325
+
1326
+ context "non-numeric" do
1327
+ subject { dv_string.sort }
1328
+
1329
+ its(:size) { is_expected.to eq 5 }
1330
+ its(:to_a) { is_expected.to eq ['a', 'bb', 'ccc', 'xxxx', 'zzzzz'] }
1331
+ its(:'index.to_a') { is_expected.to eq [:c, 1, :a, :a, 1] }
1332
+ end
1333
+
1334
+ context "block" do
1335
+ subject { dv_string.sort { |a, b| a.length <=> b.length } }
1336
+
1337
+ its(:to_a) { is_expected.to eq ['a', 'bb', 'ccc', 'xxxx', 'zzzzz'] }
1338
+ its(:'index.to_a') { is_expected.to eq [:c, 1, :a, :a, 1] }
1339
+ end
1340
+
1341
+ context "nils" do
1342
+ subject { dv_nil.sort }
1343
+
1344
+ its(:to_a) { is_expected.to eq [nil, -1, 1, 2, 3] }
1345
+ its(:'index.to_a') { is_expected.to eq [1, :c, 1, :a, :a] }
1346
+ end
1347
+ end
1348
+
1349
+ context "decreasing order" do
1350
+ context "numeric" do
1351
+ subject { dv_numeric.sort(ascending: false) }
1352
+
1353
+ its(:size) { is_expected.to eq 5 }
1354
+ its(:to_a) { is_expected.to eq [5, 4, 3, 2, 1] }
1355
+ its(:'index.to_a') { is_expected.to eq [1, :a, :a, 1, :c] }
1356
+ end
1357
+
1358
+ context "non-numeric" do
1359
+ subject { dv_string.sort(ascending: false) }
1360
+
1361
+ its(:size) { is_expected.to eq 5 }
1362
+ its(:to_a) { is_expected.to eq ['zzzzz', 'xxxx', 'ccc', 'bb', 'a'] }
1363
+ its(:'index.to_a') { is_expected.to eq [1, :a, :a, 1, :c] }
1364
+ end
1365
+
1366
+ context "block" do
1367
+ subject do
1368
+ dv_string.sort(ascending: false) { |a, b| a.length <=> b.length }
1369
+ end
1370
+
1371
+ its(:to_a) { is_expected.to eq ['zzzzz', 'xxxx', 'ccc', 'bb', 'a'] }
1372
+ its(:'index.to_a') { is_expected.to eq [1, :a, :a, 1, :c] }
1373
+ end
1374
+
1375
+ context "nils" do
1376
+ subject { dv_nil.sort(ascending: false) }
1377
+
1378
+ its(:to_a) { is_expected.to eq [3, 2, 1, -1, nil] }
1379
+ its(:'index.to_a') { is_expected.to eq [:a, :a, 1, :c, 1] }
1380
+ end
1381
+ end
1382
+ end
1383
+ end
1384
+
1385
+ context "#index=" do
1386
+ before do
1387
+ @vector = DaruLite::Vector.new([1,2,3,4,5])
1388
+ end
1389
+
1390
+ it "simply reassigns index" do
1391
+ index = DaruLite::DateTimeIndex.date_range(:start => '2012', :periods => 5)
1392
+ @vector.index = index
1393
+
1394
+ expect(@vector.index.class).to eq(DaruLite::DateTimeIndex)
1395
+ expect(@vector['2012-1-1']).to eq(1)
1396
+ end
1397
+
1398
+ it "accepts an array as index" do
1399
+ @vector.index = [5,4,3,2,1]
1400
+
1401
+ expect(@vector.index.class).to eq(DaruLite::Index)
1402
+ expect(@vector[5]).to eq(1)
1403
+ end
1404
+
1405
+ it "accepts an range as index" do
1406
+ @vector.index = 'a'..'e'
1407
+
1408
+ expect(@vector.index.class).to eq(DaruLite::Index)
1409
+ expect(@vector['a']).to eq(1)
1410
+ end
1411
+
1412
+ it "raises error for index size != vector size" do
1413
+ expect {
1414
+ @vector.index = DaruLite::Index.new([4,2,6])
1415
+ }.to raise_error(ArgumentError, 'Size of supplied index 3 '\
1416
+ 'does not match size of Vector')
1417
+ end
1418
+ end
1419
+
1420
+ context "#reindex!" do
1421
+ before do
1422
+ @vector = DaruLite::Vector.new([1,2,3,4,5])
1423
+ @index = DaruLite::Index.new([3,4,1,0,6])
1424
+ end
1425
+ it "intelligently reindexes" do
1426
+ @vector.reindex!(@index)
1427
+ expect(@vector).to eq(
1428
+ DaruLite::Vector.new([4,5,2,1,nil], index: @index))
1429
+ end
1430
+ end
1431
+
1432
+ context "#reindex" do
1433
+ before do
1434
+ @vector = DaruLite::Vector.new([1,2,3,4,5])
1435
+ @index = DaruLite::Index.new([3,4,1,0,6])
1436
+ end
1437
+ it "intelligently reindexes" do
1438
+ expect(@vector.reindex(@index)).to eq(
1439
+ DaruLite::Vector.new([4,5,2,1,nil], index: @index))
1440
+ end
1441
+ end
1442
+
1443
+ context "#dup" do
1444
+ before do
1445
+ @dv = DaruLite::Vector.new [1,2], name: :yoda, index: [:happy, :lightsaber]
1446
+ end
1447
+
1448
+ it "copies the original data" do
1449
+ expect(@dv.dup.send(:data)).to eq([1,2])
1450
+ end
1451
+
1452
+ it "creates a new data object" do
1453
+ expect(@dv.dup.send(:data).object_id).not_to eq(@dv.send(:data).object_id)
1454
+ end
1455
+
1456
+ it "copies the name" do
1457
+ expect(@dv.dup.name).to eq(:yoda)
1458
+ end
1459
+
1460
+ it "copies the original index" do
1461
+ expect(@dv.dup.index).to eq(DaruLite::Index.new([:happy, :lightsaber]))
1462
+ end
1463
+
1464
+ it "creates a new index object" do
1465
+ expect(@dv.dup.index.object_id).not_to eq(@dv.index.object_id)
1466
+ end
1467
+ end
1468
+
1469
+ context "#collect" do
1470
+ it "returns an Array" do
1471
+ a = @common_all_dtypes.collect { |v| v }
1472
+ expect(a).to eq([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99])
1473
+ end
1474
+ end
1475
+
1476
+ context "#map" do
1477
+ it "maps" do
1478
+ a = @common_all_dtypes.map { |v| v }
1479
+ expect(a).to eq([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99])
1480
+ end
1481
+ end
1482
+
1483
+ context "#map!" do
1484
+ it "destructively maps" do
1485
+ @common_all_dtypes.map! { |v| v + 1 }
1486
+ expect(@common_all_dtypes).to eq(DaruLite::Vector.new(
1487
+ [6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 2, 3, 4, 5, 12, -98, -98],
1488
+ dtype: dtype))
1489
+ end
1490
+ end
1491
+
1492
+ context "#recode" do
1493
+ it "maps and returns a vector of dtype of self by default" do
1494
+ a = @common_all_dtypes.recode { |v| v == -99 ? 1 : 0 }
1495
+ exp = DaruLite::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
1496
+ expect(a).to eq(exp)
1497
+ expect(a.dtype).to eq(:array)
1498
+ end
1499
+ end
1500
+
1501
+ context "#recode!" do
1502
+ before :each do
1503
+ @vector = DaruLite::Vector.new(
1504
+ [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99],
1505
+ dtype: dtype, name: :common_all_dtypes)
1506
+ end
1507
+
1508
+ it "destructively maps and returns a vector of dtype of self by default" do
1509
+ @vector.recode! { |v| v == -99 ? 1 : 0 }
1510
+ exp = DaruLite::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
1511
+ expect(@vector).to eq(exp)
1512
+ expect(@vector.dtype).to eq(dtype)
1513
+ end
1514
+ end
1515
+
1516
+ context "#verify" do
1517
+ it "returns a hash of invalid data and index of data" do
1518
+ v = DaruLite::Vector.new [1,2,3,4,5,6,-99,35,-100], dtype: dtype
1519
+ h = v.verify { |d| d > 0 }
1520
+ e = { 6 => -99, 8 => -100 }
1521
+ expect(h).to eq(e)
1522
+ end
1523
+ end
1524
+
1525
+ context "#summary" do
1526
+ subject { dv.summary }
1527
+
1528
+ context 'all types' do
1529
+ let(:dv) { DaruLite::Vector.new([1,2,3,4,5], name: 'vector') }
1530
+
1531
+ it { is_expected.to include dv.name }
1532
+
1533
+ it { is_expected.to include "n :#{dv.size}" }
1534
+
1535
+ it { is_expected.to include "non-missing:#{dv.size - dv.count_values(*DaruLite::MISSING_VALUES)}" }
1536
+ end
1537
+
1538
+
1539
+ context "numeric type" do
1540
+ let(:dv) { DaruLite::Vector.new([1,2,5], name: 'numeric') }
1541
+
1542
+ it { is_expected. to eq %Q{
1543
+ |= numeric
1544
+ | n :3
1545
+ | non-missing:3
1546
+ | median: 2
1547
+ | mean: 2.6667
1548
+ | std.dev.: 2.0817
1549
+ | std.err.: 1.2019
1550
+ | skew: 0.2874
1551
+ | kurtosis: -2.3333
1552
+ }.unindent }
1553
+ end
1554
+
1555
+ context "numeric type with missing values" do
1556
+ let(:dv) { DaruLite::Vector.new([1,2,5,nil,Float::NAN], name: 'numeric') }
1557
+
1558
+ it { is_expected.not_to include 'skew' }
1559
+ it { is_expected.not_to include 'kurtosis' }
1560
+ end
1561
+
1562
+ if dtype == :array
1563
+ context "object type" do
1564
+ let(:dv) { DaruLite::Vector.new([1,1,2,2,"string",nil,Float::NAN], name: 'object') }
1565
+
1566
+ if RUBY_VERSION >= '2.2'
1567
+ it { is_expected.to eq %Q{
1568
+ |= object
1569
+ | n :7
1570
+ | non-missing:5
1571
+ | factors: 1,2,string
1572
+ | mode: 1,2
1573
+ | Distribution
1574
+ | string 1 50.00%
1575
+ | NaN 1 50.00%
1576
+ | 1 2 100.00%
1577
+ | 2 2 100.00%
1578
+ }.unindent }
1579
+ else
1580
+ it { is_expected.to eq %Q{
1581
+ |= object
1582
+ | n :7
1583
+ | non-missing:5
1584
+ | factors: 1,2,string
1585
+ | mode: 1,2
1586
+ | Distribution
1587
+ | NaN 1 50.00%
1588
+ | string 1 50.00%
1589
+ | 2 2 100.00%
1590
+ | 1 2 100.00%
1591
+ }.unindent }
1592
+ end
1593
+ end
1594
+ end
1595
+ end
1596
+
1597
+ context "#bootstrap" do
1598
+ it "returns a vector with mean=mu and sd=se" do
1599
+ rng = Distribution::Normal.rng(0, 1)
1600
+ vector =DaruLite::Vector.new_with_size(100, dtype: dtype) { rng.call}
1601
+
1602
+ df = vector.bootstrap([:mean, :sd], 200)
1603
+ se = 1 / Math.sqrt(vector.size)
1604
+ expect(df[:mean].mean).to be_within(0.3).of(0)
1605
+ expect(df[:mean].sd).to be_within(0.02).of(se)
1606
+ end
1607
+ end
1608
+ end
1609
+ end # describe ALL_DTYPES.each
1610
+
1611
+ # -----------------------------------------------------------------------
1612
+ # works with arrays only
1613
+
1614
+ context "#splitted" do
1615
+ it "splits correctly" do
1616
+ a = DaruLite::Vector.new ['a', 'a,b', 'c,d', 'a,d', 'd', 10, nil]
1617
+ expect(a.splitted).to eq([%w(a), %w(a b), %w(c d), %w(a d), %w(d), [10], nil])
1618
+ end
1619
+ end
1620
+
1621
+ context '#is_values' do
1622
+ let(:dv) { DaruLite::Vector.new [10, 11, 10, nil, nil] }
1623
+
1624
+ context 'single value' do
1625
+ subject { dv.is_values 10 }
1626
+ it { is_expected.to be_a DaruLite::Vector }
1627
+ its(:to_a) { is_expected.to eq [true, false, true, false, false] }
1628
+ end
1629
+
1630
+ context 'multiple values' do
1631
+ subject { dv.is_values 10, nil }
1632
+ it { is_expected.to be_a DaruLite::Vector }
1633
+ its(:to_a) { is_expected.to eq [true, false, true, true, true] }
1634
+ end
1635
+ end
1636
+
1637
+ context "#clone_structure" do
1638
+ context DaruLite::Index do
1639
+ before do
1640
+ @vec = DaruLite::Vector.new([1,2,3,4,5], index: [:a,:b,:c,:d,:e])
1641
+ end
1642
+
1643
+ it "clones a vector with its index and fills it with nils" do
1644
+ expect(@vec.clone_structure).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil], index: [:a,:b,:c,:d,:e]))
1645
+ end
1646
+ end
1647
+
1648
+ context DaruLite::MultiIndex do
1649
+ pending
1650
+ end
1651
+ end
1652
+
1653
+ context '#reject_values'do
1654
+ let(:dv) { DaruLite::Vector.new [1, nil, 3, :a, Float::NAN, nil, Float::NAN, 1],
1655
+ index: 11..18 }
1656
+ context 'reject only nils' do
1657
+ subject { dv.reject_values nil }
1658
+
1659
+ it { is_expected.to be_a DaruLite::Vector }
1660
+ its(:to_a) { is_expected.to eq [1, 3, :a, Float::NAN, Float::NAN, 1] }
1661
+ its(:'index.to_a') { is_expected.to eq [11, 13, 14, 15, 17, 18] }
1662
+ end
1663
+
1664
+ context 'reject only float::NAN' do
1665
+ subject { dv.reject_values Float::NAN }
1666
+
1667
+ it { is_expected.to be_a DaruLite::Vector }
1668
+ its(:to_a) { is_expected.to eq [1, nil, 3, :a, nil, 1] }
1669
+ its(:'index.to_a') { is_expected.to eq [11, 12, 13, 14, 16, 18] }
1670
+ end
1671
+
1672
+ context 'reject both nil and float::NAN' do
1673
+ subject { dv.reject_values nil, Float::NAN }
1674
+
1675
+ it { is_expected.to be_a DaruLite::Vector }
1676
+ its(:to_a) { is_expected.to eq [1, 3, :a, 1] }
1677
+ its(:'index.to_a') { is_expected.to eq [11, 13, 14, 18] }
1678
+ end
1679
+
1680
+ context 'reject any other value' do
1681
+ subject { dv.reject_values 1, 3 }
1682
+
1683
+ it { is_expected.to be_a DaruLite::Vector }
1684
+ its(:to_a) { is_expected.to eq [nil, :a, Float::NAN, nil, Float::NAN] }
1685
+ its(:'index.to_a') { is_expected.to eq [12, 14, 15, 16, 17] }
1686
+ end
1687
+
1688
+ context 'when resultant vector has only one value' do
1689
+ subject { dv.reject_values 1, :a, nil, Float::NAN }
1690
+
1691
+ it { is_expected.to be_a DaruLite::Vector }
1692
+ its(:to_a) { is_expected.to eq [3] }
1693
+ its(:'index.to_a') { is_expected.to eq [13] }
1694
+ end
1695
+
1696
+ context 'when resultant vector has no value' do
1697
+ subject { dv.reject_values 1, 3, :a, nil, Float::NAN, 5 }
1698
+
1699
+ it { is_expected.to be_a DaruLite::Vector }
1700
+ its(:to_a) { is_expected.to eq [] }
1701
+ its(:'index.to_a') { is_expected.to eq [] }
1702
+ end
1703
+
1704
+ context 'test caching' do
1705
+ let(:dv) { DaruLite::Vector.new [nil]*8, index: 11..18}
1706
+ before do
1707
+ dv.reject_values nil
1708
+ [1, nil, 3, :a, Float::NAN, nil, Float::NAN, 1].each_with_index do |v, pos|
1709
+ dv.set_at [pos], v
1710
+ end
1711
+ end
1712
+
1713
+ context 'reject only nils' do
1714
+ subject { dv.reject_values nil }
1715
+
1716
+ it { is_expected.to be_a DaruLite::Vector }
1717
+ its(:to_a) { is_expected.to eq [1, 3, :a, Float::NAN, Float::NAN, 1] }
1718
+ its(:'index.to_a') { is_expected.to eq [11, 13, 14, 15, 17, 18] }
1719
+ end
1720
+
1721
+ context 'reject only float::NAN' do
1722
+ subject { dv.reject_values Float::NAN }
1723
+
1724
+ it { is_expected.to be_a DaruLite::Vector }
1725
+ its(:to_a) { is_expected.to eq [1, nil, 3, :a, nil, 1] }
1726
+ its(:'index.to_a') { is_expected.to eq [11, 12, 13, 14, 16, 18] }
1727
+ end
1728
+
1729
+ context 'reject both nil and float::NAN' do
1730
+ subject { dv.reject_values nil, Float::NAN }
1731
+
1732
+ it { is_expected.to be_a DaruLite::Vector }
1733
+ its(:to_a) { is_expected.to eq [1, 3, :a, 1] }
1734
+ its(:'index.to_a') { is_expected.to eq [11, 13, 14, 18] }
1735
+ end
1736
+
1737
+ context 'reject any other value' do
1738
+ subject { dv.reject_values 1, 3 }
1739
+
1740
+ it { is_expected.to be_a DaruLite::Vector }
1741
+ its(:to_a) { is_expected.to eq [nil, :a, Float::NAN, nil, Float::NAN] }
1742
+ its(:'index.to_a') { is_expected.to eq [12, 14, 15, 16, 17] }
1743
+ end
1744
+ end
1745
+ end
1746
+
1747
+ context '#include_values?' do
1748
+ context 'only nils' do
1749
+ context 'true' do
1750
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, :a, 'Unknown', nil] }
1751
+ it { expect(dv.include_values? nil).to eq true }
1752
+ end
1753
+
1754
+ context 'false' do
1755
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, :a, 'Unknown'] }
1756
+ it { expect(dv.include_values? nil).to eq false }
1757
+ end
1758
+ end
1759
+
1760
+ context 'only Float::NAN' do
1761
+ context 'true' do
1762
+ let(:dv) { DaruLite::Vector.new [1, nil, 2, 3, Float::NAN] }
1763
+ it { expect(dv.include_values? Float::NAN).to eq true }
1764
+ end
1765
+
1766
+ context 'false' do
1767
+ let(:dv) { DaruLite::Vector.new [1, nil, 2, 3] }
1768
+ it { expect(dv.include_values? Float::NAN).to eq false }
1769
+ end
1770
+ end
1771
+
1772
+ context 'both nil and Float::NAN' do
1773
+ context 'true with only nil' do
1774
+ let(:dv) { DaruLite::Vector.new [1, Float::NAN, 2, 3] }
1775
+ it { expect(dv.include_values? nil, Float::NAN).to eq true }
1776
+ end
1777
+
1778
+ context 'true with only Float::NAN' do
1779
+ let(:dv) { DaruLite::Vector.new [1, nil, 2, 3] }
1780
+ it { expect(dv.include_values? nil, Float::NAN).to eq true }
1781
+ end
1782
+
1783
+ context 'false' do
1784
+ let(:dv) { DaruLite::Vector.new [1, 2, 3] }
1785
+ it { expect(dv.include_values? nil, Float::NAN).to eq false }
1786
+ end
1787
+ end
1788
+
1789
+ context 'any other value' do
1790
+ context 'true' do
1791
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, 4, nil] }
1792
+ it { expect(dv.include_values? 1, 2, 3, 5).to eq true }
1793
+ end
1794
+
1795
+ context 'false' do
1796
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, 4, nil] }
1797
+ it { expect(dv.include_values? 5, 6).to eq false }
1798
+ end
1799
+ end
1800
+ end
1801
+
1802
+ context '#count_values' do
1803
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, 1, 2, nil, nil] }
1804
+ it { expect(dv.count_values 1, 2).to eq 4 }
1805
+ it { expect(dv.count_values nil).to eq 2 }
1806
+ it { expect(dv.count_values 3, Float::NAN).to eq 1 }
1807
+ it { expect(dv.count_values 4).to eq 0 }
1808
+ end
1809
+
1810
+ context '#indexes' do
1811
+ context DaruLite::Index do
1812
+ let(:dv) { DaruLite::Vector.new [1, 2, 1, 2, 3, nil, nil, Float::NAN],
1813
+ index: 11..18 }
1814
+
1815
+ subject { dv.indexes 1, 2, nil, Float::NAN }
1816
+ it { is_expected.to be_a Array }
1817
+ it { is_expected.to eq [11, 12, 13, 14, 16, 17, 18] }
1818
+ end
1819
+
1820
+ context DaruLite::MultiIndex do
1821
+ let(:mi) do
1822
+ DaruLite::MultiIndex.from_tuples([
1823
+ ['M', 2000],
1824
+ ['M', 2001],
1825
+ ['M', 2002],
1826
+ ['M', 2003],
1827
+ ['F', 2000],
1828
+ ['F', 2001],
1829
+ ['F', 2002],
1830
+ ['F', 2003]
1831
+ ])
1832
+ end
1833
+ let(:dv) { DaruLite::Vector.new [1, 2, 1, 2, 3, nil, nil, Float::NAN],
1834
+ index: mi }
1835
+
1836
+ subject { dv.indexes 1, 2, Float::NAN }
1837
+ it { is_expected.to be_a Array }
1838
+ it { is_expected.to eq(
1839
+ [
1840
+ ['M', 2000],
1841
+ ['M', 2001],
1842
+ ['M', 2002],
1843
+ ['M', 2003],
1844
+ ['F', 2003]
1845
+ ]) }
1846
+ end
1847
+ end
1848
+
1849
+ context '#replace_values' do
1850
+ subject do
1851
+ DaruLite::Vector.new(
1852
+ [1, 2, 1, 4, nil, Float::NAN, nil, Float::NAN],
1853
+ index: 11..18
1854
+ )
1855
+ end
1856
+
1857
+ context 'replace nils and NaNs' do
1858
+ before { subject.replace_values [nil, Float::NAN], 10 }
1859
+ its(:to_a) { is_expected.to eq [1, 2, 1, 4, 10, 10, 10, 10] }
1860
+ end
1861
+
1862
+ context 'replace arbitrary values' do
1863
+ before { subject.replace_values [1, 2], 10 }
1864
+ its(:to_a) { is_expected.to eq(
1865
+ [10, 10, 10, 4, nil, Float::NAN, nil, Float::NAN]) }
1866
+ end
1867
+
1868
+ context 'works for single value' do
1869
+ before { subject.replace_values nil, 10 }
1870
+ its(:to_a) { is_expected.to eq(
1871
+ [1, 2, 1, 4, 10, Float::NAN, 10, Float::NAN]) }
1872
+ end
1873
+ end
1874
+
1875
+ context "#replace_nils" do
1876
+ it "replaces all nils with the specified value" do
1877
+ vec = DaruLite::Vector.new([1,2,3,nil,nil,4])
1878
+ expect(vec.replace_nils(2)).to eq(DaruLite::Vector.new([1,2,3,2,2,4]))
1879
+ end
1880
+
1881
+ it "replaces all nils with the specified value (bang)" do
1882
+ vec = DaruLite::Vector.new([1,2,3,nil,nil,4]).replace_nils!(2)
1883
+ expect(vec).to eq(DaruLite::Vector.new([1,2,3,2,2,4]))
1884
+ end
1885
+ end
1886
+
1887
+ context '#rolling_fillna!' do
1888
+ subject do
1889
+ DaruLite::Vector.new(
1890
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN]
1891
+ )
1892
+ end
1893
+
1894
+ context 'rolling_fillna! forwards' do
1895
+ before { subject.rolling_fillna!(:forward) }
1896
+ its(:to_a) { is_expected.to eq [0, 2, 1, 4, 4, 4, 3, 3, 3] }
1897
+ end
1898
+
1899
+ context 'rolling_fillna! backwards' do
1900
+ before { subject.rolling_fillna!(direction: :backward) }
1901
+ its(:to_a) { is_expected.to eq [2, 2, 1, 4, 3, 3, 3, 0, 0] }
1902
+ end
1903
+
1904
+ context 'all invalid vector' do
1905
+ subject do
1906
+ DaruLite::Vector.new(
1907
+ [Float::NAN, Float::NAN, Float::NAN, Float::NAN, Float::NAN]
1908
+ )
1909
+ end
1910
+ before { subject.rolling_fillna!(:forward) }
1911
+ its(:to_a) { is_expected.to eq [0, 0, 0, 0, 0] }
1912
+ end
1913
+
1914
+ context 'with non-default index' do
1915
+ subject do
1916
+ DaruLite::Vector.new(
1917
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN],
1918
+ index: %w[a b c d e f g h i]
1919
+ )
1920
+ end
1921
+ before { subject.rolling_fillna!(direction: :backward) }
1922
+ it { is_expected.to eq DaruLite::Vector.new([2, 2, 1, 4, 3, 3, 3, 0, 0], index: %w[a b c d e f g h i]) }
1923
+ end
1924
+ end
1925
+
1926
+ context '#rolling_fillna' do
1927
+ subject do
1928
+ DaruLite::Vector.new(
1929
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN]
1930
+ )
1931
+ end
1932
+
1933
+ context 'rolling_fillna forwards' do
1934
+ it { expect(subject.rolling_fillna(:forward).to_a).to eq [0, 2, 1, 4, 4, 4, 3, 3, 3] }
1935
+ end
1936
+
1937
+ context 'rolling_fillna backwards' do
1938
+ it { expect(subject.rolling_fillna(direction: :backward).to_a).to eq [2, 2, 1, 4, 3, 3, 3, 0, 0] }
1939
+ end
1940
+ end
1941
+
1942
+ context "#type" do
1943
+ before(:each) do
1944
+ @numeric = DaruLite::Vector.new([1,2,3,4,5])
1945
+ @multi = DaruLite::Vector.new([1,2,3,'sameer','d'])
1946
+ @with_nils = DaruLite::Vector.new([1,2,3,4,nil])
1947
+ end
1948
+
1949
+ it "checks numeric data correctly" do
1950
+ expect(@numeric.type).to eq(:numeric)
1951
+ end
1952
+
1953
+ it "checks for multiple types of data" do
1954
+ expect(@multi.type).to eq(:object)
1955
+ end
1956
+
1957
+ it "changes type to object as per assignment" do
1958
+ expect(@numeric.type).to eq(:numeric)
1959
+ @numeric[2] = 'my string'
1960
+ expect(@numeric.type).to eq(:object)
1961
+ end
1962
+
1963
+ it "changes type to numeric as per assignment" do
1964
+ expect(@multi.type).to eq(:object)
1965
+ @multi[3] = 45
1966
+ @multi[4] = 54
1967
+ expect(@multi.type).to eq(:numeric)
1968
+ end
1969
+
1970
+ it "reports numeric if nils with number data" do
1971
+ expect(@with_nils.type).to eq(:numeric)
1972
+ end
1973
+
1974
+ it "stays numeric when nil is reassigned to a number" do
1975
+ @with_nils[4] = 66
1976
+ expect(@with_nils.type).to eq(:numeric)
1977
+ end
1978
+
1979
+ it "changes to :object when nil is reassigned to anything but a number" do
1980
+ @with_nils[4] = 'string'
1981
+ expect(@with_nils.type).to eq(:object)
1982
+ end
1983
+ end
1984
+
1985
+ context "#to_matrix" do
1986
+ before do
1987
+ @vector = DaruLite::Vector.new [1,2,3,4,5,6]
1988
+ end
1989
+
1990
+ it "converts DaruLite::Vector to a horizontal Ruby Matrix" do
1991
+ expect(@vector.to_matrix).to eq(Matrix[[1,2,3,4,5,6]])
1992
+ end
1993
+
1994
+ it "converts DaruLite::Vector to a vertical Ruby Matrix" do
1995
+ expect(@vector.to_matrix(:vertical)).to eq(Matrix.columns([[1,2,3,4,5,6]]))
1996
+ end
1997
+
1998
+ it 'raises on wrong axis' do
1999
+ expect { @vector.to_matrix(:strange) }.to raise_error(ArgumentError)
2000
+ end
2001
+ end
2002
+
2003
+ context "#only_numerics" do
2004
+ it "returns only numerical or missing data" do
2005
+ v = DaruLite::Vector.new([1,2,nil,3,4,'s','a',nil])
2006
+ expect(v.only_numerics).to eq(DaruLite::Vector.new([1,2,nil,3,4,nil],
2007
+ index: [0,1,2,3,4,7]))
2008
+ end
2009
+ end
2010
+
2011
+ context "#split_by_separator" do
2012
+ def expect_correct_tokens hash
2013
+ expect(hash['a'].to_a).to eq([1, 1, 0, 1, 0, nil])
2014
+ expect(hash['b'].to_a).to eq([0, 1, 0, 0, 0, nil])
2015
+ expect(hash['c'].to_a).to eq([0, 0, 1, 0, 0, nil])
2016
+ expect(hash['d'].to_a).to eq([0, 0, 1, 1, 0, nil])
2017
+ expect(hash[10].to_a).to eq([0, 0, 0, 0, 1, nil])
2018
+ end
2019
+
2020
+ before do
2021
+ @a = DaruLite::Vector.new ['a', 'a,b', 'c,d', 'a,d', 10, nil]
2022
+ @b = @a.split_by_separator(',')
2023
+ end
2024
+
2025
+ it "returns a Hash" do
2026
+ expect(@b.class).to eq(Hash)
2027
+ end
2028
+
2029
+ it "returned Hash has keys with with different values of @a" do
2030
+ expect(@b.keys).to eq(['a', 'b', 'c', 'd', 10])
2031
+ end
2032
+
2033
+ it "returns a Hash, whose values are DaruLite::Vector" do
2034
+ @b.each_key do |key|
2035
+ expect(@b[key].class).to eq(DaruLite::Vector)
2036
+ end
2037
+ end
2038
+
2039
+ it "ensures that hash values are n times the tokens appears" do
2040
+ expect_correct_tokens @b
2041
+ end
2042
+
2043
+ it "gives the same values using a different separator" do
2044
+ a = DaruLite::Vector.new ['a', 'a*b', 'c*d', 'a*d', 10, nil]
2045
+ b = a.split_by_separator '*'
2046
+ expect_correct_tokens b
2047
+ end
2048
+ end
2049
+
2050
+ context "#split_by_separator_freq" do
2051
+ it "returns the number of ocurrences of tokens" do
2052
+ a = DaruLite::Vector.new ['a', 'a,b', 'c,d', 'a,d', 10, nil]
2053
+ expect(a.split_by_separator_freq).to eq(
2054
+ { 'a' => 3, 'b' => 1, 'c' => 1, 'd' => 2, 10 => 1 })
2055
+ end
2056
+ end
2057
+
2058
+ context "#reset_index!" do
2059
+ it "resets any index to a numerical serialized index" do
2060
+ v = DaruLite::Vector.new([1,2,3,4,5,nil,nil,4,nil])
2061
+ r = v.reject_values(*DaruLite::MISSING_VALUES).reset_index!
2062
+ expect(r).to eq(DaruLite::Vector.new([1,2,3,4,5,4]))
2063
+ expect(r.index).to eq(DaruLite::Index.new([0,1,2,3,4,5]))
2064
+
2065
+ indexed = DaruLite::Vector.new([1,2,3,4,5], index: [:a, :b, :c, :d, :e])
2066
+ expect(indexed.reset_index!.index).to eq(DaruLite::Index.new([0,1,2,3,4]))
2067
+ end
2068
+ end
2069
+
2070
+ context "#rename" do
2071
+ before :each do
2072
+ @v = DaruLite::Vector.new [1,2,3,4,5,5], name: :this_vector
2073
+ end
2074
+
2075
+ it "assings name" do
2076
+ @v.rename :that_vector
2077
+ expect(@v.name).to eq(:that_vector)
2078
+ end
2079
+
2080
+ it "stores name as a symbol" do
2081
+ @v.rename "This is a vector"
2082
+ expect(@v.name).to eq("This is a vector")
2083
+ end
2084
+
2085
+ it "returns vector" do
2086
+ expect(@v.rename 'hello').to be_a DaruLite::Vector
2087
+ end
2088
+ end
2089
+
2090
+ context "#any?" do
2091
+ before do
2092
+ @v = DaruLite::Vector.new([1,2,3,4,5])
2093
+ end
2094
+
2095
+ it "returns true if block returns true for any one of the elements" do
2096
+ expect(@v.any?{ |e| e == 1 }).to eq(true)
2097
+ end
2098
+
2099
+ it "returns false if block is false for all elements" do
2100
+ expect(@v.any?{ |e| e > 10 }).to eq(false)
2101
+ end
2102
+ end
2103
+
2104
+ context "#all?" do
2105
+ before do
2106
+ @v = DaruLite::Vector.new([1,2,3,4,5])
2107
+ end
2108
+
2109
+ it "returns true if block is true for all elements" do
2110
+ expect(@v.all? { |e| e < 6 }).to eq(true)
2111
+ end
2112
+
2113
+ it "returns false if block is false for any one element" do
2114
+ expect(@v.all? { |e| e == 2 }).to eq(false)
2115
+ end
2116
+ end
2117
+
2118
+ context "#detach_index" do
2119
+ it "creates a DataFrame with first Vector as index and second as values of the Vector" do
2120
+ v = DaruLite::Vector.new([1,2,3,4,5,6],
2121
+ index: ['a', 'b', 'c', 'd', 'e', 'f'], name: :values)
2122
+ expect(v.detach_index).to eq(DaruLite::DataFrame.new({
2123
+ index: ['a', 'b', 'c', 'd', 'e', 'f'],
2124
+ values: [1,2,3,4,5,6]
2125
+ }))
2126
+ end
2127
+ end
2128
+
2129
+ describe '#lag' do
2130
+ let(:source) { DaruLite::Vector.new(1..5) }
2131
+
2132
+ context 'by default' do
2133
+ subject { source.lag }
2134
+ it { is_expected.to eq DaruLite::Vector.new([nil, 1, 2, 3, 4]) }
2135
+ end
2136
+
2137
+ subject { source.lag(amount) }
2138
+
2139
+ context '0' do
2140
+ let(:amount) { 0 }
2141
+ it { is_expected.to eq DaruLite::Vector.new([1, 2, 3, 4, 5]) }
2142
+ end
2143
+
2144
+ context 'same as vector size' do
2145
+ let(:amount) { source.size }
2146
+ it { is_expected.to eq DaruLite::Vector.new([nil]*source.size) }
2147
+ end
2148
+
2149
+ context 'same as vector -ve size' do
2150
+ let(:amount) { -source.size }
2151
+ it { is_expected.to eq DaruLite::Vector.new([nil]*source.size) }
2152
+ end
2153
+
2154
+ context 'positive' do
2155
+ let(:amount) { 2 }
2156
+ it { is_expected.to eq DaruLite::Vector.new([nil, nil, 1, 2, 3]) }
2157
+ end
2158
+
2159
+ context 'negative' do
2160
+ let(:amount) { -1 }
2161
+ it { is_expected.to eq DaruLite::Vector.new([2, 3, 4, 5, nil]) }
2162
+ end
2163
+
2164
+ context 'large positive' do
2165
+ let(:amount) { source.size + 100 }
2166
+ it { is_expected.to eq DaruLite::Vector.new([nil]*source.size) }
2167
+ end
2168
+
2169
+ context 'large negative' do
2170
+ let(:amount) { -(source.size + 100) }
2171
+ it { is_expected.to eq DaruLite::Vector.new([nil]*source.size) }
2172
+ end
2173
+
2174
+ end
2175
+
2176
+ context "#group_by" do
2177
+ let(:dv) { DaruLite::Vector.new [:a, :b, :a, :b, :c] }
2178
+
2179
+ context 'vector not specified' do
2180
+ subject { dv.group_by }
2181
+
2182
+ it { is_expected.to be_a DaruLite::Core::GroupBy }
2183
+ its(:'groups.size') { is_expected.to eq 3 }
2184
+ its(:groups) { is_expected.to eq({[:a]=>[0, 2], [:b]=>[1, 3], [:c]=>[4]}) }
2185
+ end
2186
+
2187
+ context 'vector name specified' do
2188
+ before { dv.name = :hello }
2189
+ subject { dv.group_by :hello }
2190
+
2191
+ it { is_expected.to be_a DaruLite::Core::GroupBy }
2192
+ its(:'groups.size') { is_expected.to eq 3 }
2193
+ its(:groups) { is_expected.to eq({[:a]=>[0, 2], [:b]=>[1, 3], [:c]=>[4]}) }
2194
+ end
2195
+
2196
+ context 'vector name invalid' do
2197
+ before { dv.name = :hello }
2198
+ it { expect { dv.group_by :abc }.to raise_error }
2199
+ end
2200
+ end
2201
+
2202
+ context '#match' do
2203
+ subject { dv.match(regexp) }
2204
+
2205
+ context 'returns matching array for a given regexp' do
2206
+ let(:dv) { DaruLite::Vector.new ['3 days', '5 weeks', '2 weeks'] }
2207
+ let(:regexp) { /weeks/ }
2208
+
2209
+ it { is_expected.to eq([false, true, true]) }
2210
+ end
2211
+ end
2212
+
2213
+ context '#method_missing' do
2214
+ context 'getting' do
2215
+ subject(:vector) { DaruLite::Vector.new [1,2,3], index: [:a, :b, :c] }
2216
+
2217
+ it 'returns value for existing index' do
2218
+ expect(vector.a).to eq 1
2219
+ end
2220
+
2221
+ it 'raises on getting non-existent index' do
2222
+ expect { vector.d }.to raise_error NoMethodError
2223
+ end
2224
+
2225
+ it 'sets existing index' do
2226
+ vector.a = 5
2227
+ expect(vector[:a]).to eq 5
2228
+ end
2229
+
2230
+ it 'raises on non-existent index setting' do
2231
+ # FIXME: inconsistency between IndexError here and NoMethodError on getting - zverok
2232
+ expect { vector.d = 5 }.to raise_error IndexError
2233
+ end
2234
+ end
2235
+ end
2236
+
2237
+ context "#sort_by_index" do
2238
+ let(:asc) { vector.sort_by_index }
2239
+ let(:desc) { vector.sort_by_index(ascending: false) }
2240
+
2241
+ context 'numeric vector' do
2242
+ let(:vector) { DaruLite::Vector.new [11, 13, 12], index: [23, 21, 22] }
2243
+ specify { expect(asc.to_a).to eq [13, 12, 11] }
2244
+ specify { expect(desc.to_a).to eq [11, 12, 13] }
2245
+ end
2246
+
2247
+ context 'mix variable type index' do
2248
+ let(:vector) { DaruLite::Vector.new [11, Float::NAN, nil],
2249
+ index: [21, 23, 22] }
2250
+ specify { expect(asc.to_a).to eq [11, nil, Float::NAN] }
2251
+ specify { expect(desc.to_a).to eq [Float::NAN, nil, 11] }
2252
+ end
2253
+ end
2254
+
2255
+ context '#db_type' do
2256
+ it 'is DATE for vector with any date in it' do
2257
+ # FIXME: is it sane?.. - zverok
2258
+ expect(DaruLite::Vector.new(['2016-03-01', 'foo', 4]).db_type).to eq 'DATE'
2259
+ end
2260
+
2261
+ it 'is INTEGER for digits-only values' do
2262
+ expect(DaruLite::Vector.new(['123', 456, 789]).db_type).to eq 'INTEGER'
2263
+ end
2264
+
2265
+ it 'is DOUBLE for digits-and-point values' do
2266
+ expect(DaruLite::Vector.new(['123.4', 456, 789e-10]).db_type).to eq 'DOUBLE'
2267
+ end
2268
+
2269
+ it 'is VARCHAR for everyting else' do
2270
+ expect(DaruLite::Vector.new(['123 and stuff', 456, 789e-10]).db_type).to eq 'VARCHAR (255)'
2271
+ end
2272
+ end
2273
+
2274
+ context 'on wrong dtypes' do
2275
+ it 'should not accept mdarray' do
2276
+ expect { DaruLite::Vector.new([], dtype: :mdarray) }.to raise_error(NotImplementedError)
2277
+ end
2278
+
2279
+ it 'should not accept anything else' do
2280
+ expect { DaruLite::Vector.new([], dtype: :kittens) }.to raise_error(ArgumentError)
2281
+ end
2282
+ end
2283
+
2284
+ context '#where clause when Nan, nil data value is present' do
2285
+ let(:v) { DaruLite::Vector.new([1,2,3,Float::NAN, nil]) }
2286
+
2287
+ it 'missing/undefined data in Vector/DataFrame' do
2288
+ expect(v.where(v.lt(4))).to eq(DaruLite::Vector.new([1,2,3]))
2289
+ expect(v.where(v.lt(3))).to eq(DaruLite::Vector.new([1,2]))
2290
+ expect(v.where(v.lt(2))).to eq(DaruLite::Vector.new([1]))
2291
+ end
2292
+ end
2293
+ end if mri?