daru_lite 0.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.github/workflows/ci.yml +20 -0
  5. data/.rubocop_todo.yml +35 -33
  6. data/README.md +19 -115
  7. data/daru_lite.gemspec +1 -0
  8. data/lib/daru_lite/data_frame/aggregatable.rb +165 -0
  9. data/lib/daru_lite/data_frame/calculatable.rb +140 -0
  10. data/lib/daru_lite/data_frame/convertible.rb +107 -0
  11. data/lib/daru_lite/data_frame/duplicatable.rb +64 -0
  12. data/lib/daru_lite/data_frame/fetchable.rb +301 -0
  13. data/lib/daru_lite/data_frame/filterable.rb +144 -0
  14. data/lib/daru_lite/data_frame/i_o_able.rb +179 -0
  15. data/lib/daru_lite/data_frame/indexable.rb +168 -0
  16. data/lib/daru_lite/data_frame/iterable.rb +339 -0
  17. data/lib/daru_lite/data_frame/joinable.rb +152 -0
  18. data/lib/daru_lite/data_frame/missable.rb +75 -0
  19. data/lib/daru_lite/data_frame/pivotable.rb +108 -0
  20. data/lib/daru_lite/data_frame/queryable.rb +67 -0
  21. data/lib/daru_lite/data_frame/setable.rb +109 -0
  22. data/lib/daru_lite/data_frame/sortable.rb +241 -0
  23. data/lib/daru_lite/dataframe.rb +142 -2355
  24. data/lib/daru_lite/index/index.rb +13 -0
  25. data/lib/daru_lite/maths/statistics/vector.rb +1 -1
  26. data/lib/daru_lite/vector/aggregatable.rb +9 -0
  27. data/lib/daru_lite/vector/calculatable.rb +78 -0
  28. data/lib/daru_lite/vector/convertible.rb +77 -0
  29. data/lib/daru_lite/vector/duplicatable.rb +17 -0
  30. data/lib/daru_lite/vector/fetchable.rb +175 -0
  31. data/lib/daru_lite/vector/filterable.rb +128 -0
  32. data/lib/daru_lite/vector/indexable.rb +77 -0
  33. data/lib/daru_lite/vector/iterable.rb +95 -0
  34. data/lib/daru_lite/vector/joinable.rb +17 -0
  35. data/lib/daru_lite/vector/missable.rb +124 -0
  36. data/lib/daru_lite/vector/queryable.rb +45 -0
  37. data/lib/daru_lite/vector/setable.rb +47 -0
  38. data/lib/daru_lite/vector/sortable.rb +113 -0
  39. data/lib/daru_lite/vector.rb +36 -932
  40. data/lib/daru_lite/version.rb +1 -1
  41. data/spec/data_frame/aggregatable_example.rb +65 -0
  42. data/spec/data_frame/buildable_example.rb +109 -0
  43. data/spec/data_frame/calculatable_example.rb +135 -0
  44. data/spec/data_frame/convertible_example.rb +180 -0
  45. data/spec/data_frame/duplicatable_example.rb +111 -0
  46. data/spec/data_frame/fetchable_example.rb +476 -0
  47. data/spec/data_frame/filterable_example.rb +250 -0
  48. data/spec/data_frame/indexable_example.rb +221 -0
  49. data/spec/data_frame/iterable_example.rb +465 -0
  50. data/spec/data_frame/joinable_example.rb +106 -0
  51. data/spec/data_frame/missable_example.rb +47 -0
  52. data/spec/data_frame/pivotable_example.rb +297 -0
  53. data/spec/data_frame/queryable_example.rb +92 -0
  54. data/spec/data_frame/setable_example.rb +482 -0
  55. data/spec/data_frame/sortable_example.rb +350 -0
  56. data/spec/dataframe_spec.rb +181 -3243
  57. data/spec/index/index_spec.rb +8 -0
  58. data/spec/vector/aggregatable_example.rb +27 -0
  59. data/spec/vector/calculatable_example.rb +82 -0
  60. data/spec/vector/convertible_example.rb +126 -0
  61. data/spec/vector/duplicatable_example.rb +48 -0
  62. data/spec/vector/fetchable_example.rb +463 -0
  63. data/spec/vector/filterable_example.rb +165 -0
  64. data/spec/vector/indexable_example.rb +201 -0
  65. data/spec/vector/iterable_example.rb +111 -0
  66. data/spec/vector/joinable_example.rb +25 -0
  67. data/spec/vector/missable_example.rb +88 -0
  68. data/spec/vector/queryable_example.rb +91 -0
  69. data/spec/vector/setable_example.rb +300 -0
  70. data/spec/vector/sortable_example.rb +242 -0
  71. data/spec/vector_spec.rb +111 -1805
  72. metadata +102 -3
  73. data/.github/ISSUE_TEMPLATE.md +0 -18
@@ -0,0 +1,300 @@
1
+ shared_examples_for 'a setable Vector' do |dtype|
2
+ describe "#[]=" do
3
+ context DaruLite::Index do
4
+ let(:vector) do
5
+ DaruLite::Vector.new(
6
+ [1,2,3,4,5],
7
+ name: :yoga,
8
+ index: [:yoda, :anakin, :obi, :padme, :r2d2],
9
+ dtype:
10
+ )
11
+ end
12
+
13
+ it "assigns at the specified index" do
14
+ vector[:yoda] = 666
15
+ expect(vector[:yoda]).to eq(666)
16
+ end
17
+
18
+ it "assigns at the specified Integer index" do
19
+ vector[0] = 666
20
+ expect(vector[:yoda]).to eq(666)
21
+ end
22
+
23
+ it "sets dtype to Array if a nil is assigned" do
24
+ vector[0] = nil
25
+ expect(vector.dtype).to eq(:array)
26
+ end
27
+
28
+ context 'mixed index Vector' do
29
+ let(:vector) do
30
+ DaruLite::Vector.new([1, 2, 3, 4], index: ['a', :a, 0, 66])
31
+ end
32
+
33
+ it "assigns correctly" do
34
+ vector['a'] = 666
35
+ expect(vector['a']).to eq(666)
36
+
37
+ vector[0] = 666
38
+ expect(vector[0]).to eq(666)
39
+
40
+ vector[3] = 666
41
+ expect(vector[3]).to eq(666)
42
+
43
+ expect(vector).to eq(
44
+ DaruLite::Vector.new(
45
+ [666, 2, 666, 666],
46
+ index: ['a', :a, 0, 66])
47
+ )
48
+ end
49
+ end
50
+ end
51
+
52
+ context DaruLite::MultiIndex do
53
+ let(:tuples) do
54
+ [
55
+ [:a,:one,:bar],
56
+ [:a,:one,:baz],
57
+ [:a,:two,:bar],
58
+ [:a,:two,:baz],
59
+ [:b,:one,:bar],
60
+ [:b,:two,:bar],
61
+ [:b,:two,:baz],
62
+ [:b,:one,:foo],
63
+ [:c,:one,:bar],
64
+ [:c,:one,:baz],
65
+ [:c,:two,:foo],
66
+ [:c,:two,:bar]
67
+ ]
68
+ end
69
+ let(:multi_index) { DaruLite::MultiIndex.from_tuples(tuples) }
70
+ let(:vector) do
71
+ DaruLite::Vector.new(
72
+ Array.new(12) { |i| i },
73
+ index: multi_index,
74
+ dtype:,
75
+ name: :mi_vector
76
+ )
77
+ end
78
+
79
+ it "assigns all lower layer indices when specified a first layer index" do
80
+ vector[:b] = 69
81
+ expect(vector).to eq(
82
+ DaruLite::Vector.new([0, 1, 2, 3, 69, 69, 69, 69, 8, 9, 10, 11],
83
+ index: multi_index,
84
+ name: :top_layer_assignment,
85
+ dtype:
86
+ )
87
+ )
88
+ end
89
+
90
+ it "assigns all lower indices when specified first and second layer index" do
91
+ vector[:b, :one] = 69
92
+ expect(vector).to eq(
93
+ DaruLite::Vector.new([0, 1, 2, 3, 69, 5, 6, 69, 8, 9, 10, 11],
94
+ index: multi_index,
95
+ name: :second_layer_assignment,
96
+ dtype:
97
+ )
98
+ )
99
+ end
100
+
101
+ it "assigns just the precise value when specified complete tuple" do
102
+ vector[:b, :one, :foo] = 69
103
+ expect(vector).to eq(
104
+ DaruLite::Vector.new([0, 1, 2, 3, 4, 5, 6, 69, 8, 9, 10, 11],
105
+ index: multi_index,
106
+ name: :precise_assignment,
107
+ dtype:
108
+ )
109
+ )
110
+ end
111
+
112
+ it "assigns correctly when numeric index" do
113
+ vector[7] = 69
114
+ expect(vector).to eq(
115
+ DaruLite::Vector.new([0, 1, 2, 3, 4, 5, 6, 69, 8, 9, 10, 11],
116
+ index: multi_index,
117
+ name: :precise_assignment,
118
+ dtype:
119
+ )
120
+ )
121
+ end
122
+
123
+ it "fails predictably on unknown index" do
124
+ expect { vector[:d] = 69 }.to raise_error(IndexError)
125
+ expect { vector[:b, :three] = 69 }.to raise_error(IndexError)
126
+ expect { vector[:b, :two, :test] = 69 }.to raise_error(IndexError)
127
+ end
128
+ end
129
+
130
+ context DaruLite::CategoricalIndex do
131
+ subject { vector }
132
+
133
+ context "non-numerical index" do
134
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, :b, :a, :a, :c] }
135
+ let (:vector) { DaruLite::Vector.new 'a'..'e', index: idx }
136
+
137
+ context "single category" do
138
+ context "multiple instances" do
139
+ before { vector[:a] = 'x' }
140
+
141
+ its(:size) { is_expected.to eq 5 }
142
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x', 'x', 'e'] }
143
+ its(:index) { is_expected.to eq idx }
144
+ end
145
+
146
+ context "single instance" do
147
+ before { vector[:b] = 'x' }
148
+
149
+ its(:size) { is_expected.to eq 5 }
150
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
151
+ its(:index) { is_expected.to eq idx }
152
+ end
153
+ end
154
+
155
+ context "multiple categories" do
156
+ before { vector[:a, :c] = 'x' }
157
+
158
+ its(:size) { is_expected.to eq 5 }
159
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x', 'x', 'x'] }
160
+ its(:index) { is_expected.to eq idx }
161
+ end
162
+
163
+ context "multiple positional indexes" do
164
+ before { vector[0, 1, 2] = 'x' }
165
+
166
+ its(:size) { is_expected.to eq 5 }
167
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'd', 'e'] }
168
+ its(:index) { is_expected.to eq idx }
169
+ end
170
+
171
+ context "single positional index" do
172
+ before { vector[1] = 'x' }
173
+
174
+ its(:size) { is_expected.to eq 5 }
175
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
176
+ its(:index) { is_expected.to eq idx }
177
+ end
178
+
179
+ context "invalid category" do
180
+ it { expect { vector[:x] = 'x' }.to raise_error IndexError }
181
+ end
182
+
183
+ context "invalid positional index" do
184
+ it { expect { vector[30] = 'x'}.to raise_error IndexError }
185
+ end
186
+ end
187
+
188
+ context "numerical index" do
189
+ let (:idx) { DaruLite::CategoricalIndex.new [1, 1, 2, 2, 3] }
190
+ let (:vector) { DaruLite::Vector.new 'a'..'e', index: idx }
191
+
192
+ context "single category" do
193
+ before { vector[1] = 'x' }
194
+
195
+ its(:size) { is_expected.to eq 5 }
196
+ its(:to_a) { is_expected.to eq ['x', 'x', 'c', 'd', 'e'] }
197
+ its(:index) { is_expected.to eq idx }
198
+ end
199
+
200
+ context "multiple categories" do
201
+ before { vector[1, 2] = 'x' }
202
+
203
+ its(:size) { is_expected.to eq 5 }
204
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'x', 'e'] }
205
+ its(:index) { is_expected.to eq idx }
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ describe "#set_at" do
212
+ context DaruLite::Index do
213
+ let (:idx) { DaruLite::Index.new [1, 0, :c] }
214
+ let (:dv) { DaruLite::Vector.new ['a', 'b', 'c'], index: idx }
215
+
216
+ context "single position" do
217
+ subject { dv }
218
+ before { dv.set_at [1], 'x' }
219
+
220
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c'] }
221
+ end
222
+
223
+ context "multiple positions" do
224
+ subject { dv }
225
+ before { dv.set_at [0, 2], 'x' }
226
+
227
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x'] }
228
+ end
229
+
230
+ context "invalid position" do
231
+ it { expect { dv.set_at [3], 'x' }.to raise_error IndexError }
232
+ end
233
+
234
+ context "invalid positions" do
235
+ it { expect { dv.set_at [2, 3], 'x' }.to raise_error IndexError }
236
+ end
237
+ end
238
+
239
+ context DaruLite::MultiIndex do
240
+ let(:idx) do
241
+ DaruLite::MultiIndex.from_tuples [
242
+ [:a,:one,:bar],
243
+ [:a,:one,:baz],
244
+ [:b,:two,:bar],
245
+ [:a,:two,:baz],
246
+ ]
247
+ end
248
+ let(:dv) { DaruLite::Vector.new 1..4, index: idx }
249
+
250
+ context "single position" do
251
+ subject { dv }
252
+ before { dv.set_at [1], 'x' }
253
+
254
+ its(:to_a) { is_expected.to eq [1, 'x', 3, 4] }
255
+ end
256
+
257
+ context "multiple positions" do
258
+ subject { dv }
259
+ before { dv.set_at [2, 3], 'x' }
260
+
261
+ its(:to_a) { is_expected.to eq [1, 2, 'x', 'x'] }
262
+ end
263
+
264
+ context "invalid position" do
265
+ it { expect { dv.set_at [4], 'x' }.to raise_error IndexError }
266
+ end
267
+
268
+ context "invalid positions" do
269
+ it { expect { dv.set_at [2, 4], 'x' }.to raise_error IndexError }
270
+ end
271
+ end
272
+
273
+ context DaruLite::CategoricalIndex do
274
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, 1, 1, :a, :c] }
275
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx }
276
+
277
+ context "multiple positional indexes" do
278
+ subject { dv }
279
+ before { dv.set_at [0, 1, 2], 'x' }
280
+
281
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'd', 'e'] }
282
+ end
283
+
284
+ context "single positional index" do
285
+ subject { dv }
286
+ before { dv.set_at [1], 'x' }
287
+
288
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
289
+ end
290
+
291
+ context "invalid position" do
292
+ it { expect { dv.set_at [5], 'x' }.to raise_error IndexError }
293
+ end
294
+
295
+ context "invalid positions" do
296
+ it { expect { dv.set_at [2, 5], 'x' }.to raise_error IndexError }
297
+ end
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,242 @@
1
+ shared_examples_for 'a sortable Vector' do |dtype|
2
+ describe "#reorder!" do
3
+ subject { vector_with_dtype.reorder!([3, 2, 1, 0]) }
4
+
5
+ let(:vector_with_dtype) do
6
+ DaruLite::Vector.new(
7
+ [1, 2, 3, 4],
8
+ index: [:a, :b, :c, :d],
9
+ dtype:
10
+ )
11
+ end
12
+ let(:arranged_vector) do
13
+ DaruLite::Vector.new([4,3,2,1], index: [:d, :c, :b, :a], dtype:)
14
+ end
15
+
16
+ before { subject }
17
+
18
+ it "rearranges with passed order" do
19
+ expect(vector_with_dtype).to eq arranged_vector
20
+ end
21
+
22
+ it "doesn't change dtype" do
23
+ expect(vector_with_dtype.data.class).to eq arranged_vector.data.class
24
+ end
25
+ end
26
+
27
+
28
+ context "#sort" do
29
+ context DaruLite::Index do
30
+ let(:vector) do
31
+ DaruLite::Vector.new([33, 2, 15, 332, 1], name: :dv, index: [:a, :b, :c, :d, :e])
32
+ end
33
+
34
+ it "sorts the vector with defaults and returns a new vector, preserving indexing" do
35
+ expect(vector.sort).to eq(
36
+ DaruLite::Vector.new([1,2,15,33,332], name: :dv, index: [:e, :b, :c, :a, :d])
37
+ )
38
+ end
39
+
40
+ it "sorts the vector in descending order" do
41
+ expect(vector.sort(ascending: false)).to eq(
42
+ DaruLite::Vector.new([332,33,15,2,1], name: :dv, index: [:d, :a, :c, :b, :e])
43
+ )
44
+ end
45
+
46
+ context 'when a block is passed' do
47
+ subject { vector.sort { |a,b| a.length <=> b.length } }
48
+
49
+ let(:vector) { DaruLite::Vector.new ["My Jazz Guitar", "Jazz", "My", "Guitar"] }
50
+
51
+ it "sorts vector accordingly" do
52
+ expect(subject).to eq(
53
+ DaruLite::Vector.new(["My", "Jazz", "Guitar", "My Jazz Guitar"], index: [2, 1, 3, 0])
54
+ )
55
+ end
56
+ end
57
+
58
+ context 'when vector contains nils and numeric data' do
59
+ let(:vector) { DaruLite::Vector.new([22, 4, nil, 111, nil, 2]) }
60
+
61
+ it "places nils near the beginning of the vector when sorting ascendingly" do
62
+ expect(vector.sort).to eq(
63
+ DaruLite::Vector.new([nil, nil, 2, 4, 22, 111], index: [2, 4, 5, 1, 0, 3])
64
+ )
65
+ end if dtype == :array
66
+
67
+ it "places nils near the beginning of the vector when sorting descendingly" do
68
+ expect(vector.sort(ascending: false)).to eq(
69
+ DaruLite::Vector.new [111, 22, 4, 2, nil, nil], index: [3, 0, 1, 5, 4, 2]
70
+ )
71
+ end
72
+ end
73
+
74
+ context 'when vector contains nils and non-numeric data' do
75
+ let(:vector) { DaruLite::Vector.new(['a','b', nil, 'aa', '1234', nil]) }
76
+
77
+ it "correctly sorts vector in ascending order" do
78
+ expect(vector.sort(ascending: true)).to eq(
79
+ DaruLite::Vector.new([nil, nil, '1234', 'a', 'aa', 'b'], index: [2, 5, 4, 0, 3, 1])
80
+ )
81
+ end
82
+
83
+ it "correctly sorts vector in descending order" do
84
+ expect(vector.sort(ascending: false)).to eq(
85
+ DaruLite::Vector.new(['b', 'aa', 'a', '1234', nil, nil], index: [1, 3, 0, 4, 5, 2])
86
+ )
87
+ end
88
+ end
89
+ end
90
+
91
+ context DaruLite::MultiIndex do
92
+ let(:multi_index) do
93
+ DaruLite::MultiIndex.from_tuples([
94
+ [:a, :one, :foo],
95
+ [:a, :two, :bar],
96
+ [:b, :one, :bar],
97
+ [:b, :two, :baz],
98
+ [:b, :three, :bar]
99
+ ])
100
+ end
101
+ let(:vector) do
102
+ DaruLite::Vector.new(
103
+ [44, 22, 111, 0, -56],
104
+ index: multi_index,
105
+ name: :unsorted,
106
+ dtype:
107
+ )
108
+ end
109
+
110
+ it "sorts vector" do
111
+ mi_asc = DaruLite::MultiIndex.from_tuples([
112
+ [:b, :three, :bar],
113
+ [:b, :two, :baz],
114
+ [:a, :two, :bar],
115
+ [:a, :one, :foo],
116
+ [:b, :one, :bar]
117
+ ])
118
+ expect(vector.sort).to eq(
119
+ DaruLite::Vector.new([-56,0,22,44,111], index: mi_asc, name: :ascending, dtype:)
120
+ )
121
+ end
122
+
123
+ it "sorts in descending" do
124
+ mi_dsc = DaruLite::MultiIndex.from_tuples([
125
+ [:b, :one, :bar],
126
+ [:a, :one, :foo],
127
+ [:a, :two, :bar],
128
+ [:b, :two, :baz],
129
+ [:b, :three, :bar]
130
+ ])
131
+ expect(vector.sort(ascending: false)).to eq(
132
+ DaruLite::Vector.new([111, 44, 22, 0, -56], index: mi_dsc, name: :descending, dtype:)
133
+ )
134
+ end
135
+
136
+ it "sorts using the supplied block" do
137
+ mi_abs = DaruLite::MultiIndex.from_tuples([
138
+ [:b, :two, :baz],
139
+ [:a, :two, :bar],
140
+ [:a, :one, :foo],
141
+ [:b, :three, :bar],
142
+ [:b, :one, :bar]
143
+ ])
144
+ expect(vector.sort { |a,b| a.abs <=> b.abs }).to eq(
145
+ DaruLite::Vector.new([0, 22, 44, -56, 111], index: mi_abs, name: :sort_abs, dtype:)
146
+ )
147
+ end
148
+ end
149
+
150
+ context DaruLite::CategoricalIndex do
151
+ let(:idx) { DaruLite::CategoricalIndex.new [:a, 1, :a, 1, :c] }
152
+ let(:dv_numeric) { DaruLite::Vector.new [4, 5, 3, 2, 1], index: idx }
153
+ let(:dv_string) { DaruLite::Vector.new ['xxxx', 'zzzzz', 'ccc', 'bb', 'a'], index: idx }
154
+ let(:dv_nil) { DaruLite::Vector.new [3, nil, 2, 1, -1], index: idx }
155
+
156
+ context "increasing order" do
157
+ context "numeric" do
158
+ subject { dv_numeric.sort }
159
+
160
+ its(:size) { is_expected.to eq 5 }
161
+ its(:to_a) { is_expected.to eq [1, 2, 3, 4, 5] }
162
+ its(:'index.to_a') { is_expected.to eq [:c, 1, :a, :a, 1] }
163
+ end
164
+
165
+ context "non-numeric" do
166
+ subject { dv_string.sort }
167
+
168
+ its(:size) { is_expected.to eq 5 }
169
+ its(:to_a) { is_expected.to eq ['a', 'bb', 'ccc', 'xxxx', 'zzzzz'] }
170
+ its(:'index.to_a') { is_expected.to eq [:c, 1, :a, :a, 1] }
171
+ end
172
+
173
+ context "block" do
174
+ subject { dv_string.sort { |a, b| a.length <=> b.length } }
175
+
176
+ its(:to_a) { is_expected.to eq ['a', 'bb', 'ccc', 'xxxx', 'zzzzz'] }
177
+ its(:'index.to_a') { is_expected.to eq [:c, 1, :a, :a, 1] }
178
+ end
179
+
180
+ context "nils" do
181
+ subject { dv_nil.sort }
182
+
183
+ its(:to_a) { is_expected.to eq [nil, -1, 1, 2, 3] }
184
+ its(:'index.to_a') { is_expected.to eq [1, :c, 1, :a, :a] }
185
+ end
186
+ end
187
+
188
+ context "decreasing order" do
189
+ context "numeric" do
190
+ subject { dv_numeric.sort(ascending: false) }
191
+
192
+ its(:size) { is_expected.to eq 5 }
193
+ its(:to_a) { is_expected.to eq [5, 4, 3, 2, 1] }
194
+ its(:'index.to_a') { is_expected.to eq [1, :a, :a, 1, :c] }
195
+ end
196
+
197
+ context "non-numeric" do
198
+ subject { dv_string.sort(ascending: false) }
199
+
200
+ its(:size) { is_expected.to eq 5 }
201
+ its(:to_a) { is_expected.to eq ['zzzzz', 'xxxx', 'ccc', 'bb', 'a'] }
202
+ its(:'index.to_a') { is_expected.to eq [1, :a, :a, 1, :c] }
203
+ end
204
+
205
+ context "block" do
206
+ subject do
207
+ dv_string.sort(ascending: false) { |a, b| a.length <=> b.length }
208
+ end
209
+
210
+ its(:to_a) { is_expected.to eq ['zzzzz', 'xxxx', 'ccc', 'bb', 'a'] }
211
+ its(:'index.to_a') { is_expected.to eq [1, :a, :a, 1, :c] }
212
+ end
213
+
214
+ context "nils" do
215
+ subject { dv_nil.sort(ascending: false) }
216
+
217
+ its(:to_a) { is_expected.to eq [3, 2, 1, -1, nil] }
218
+ its(:'index.to_a') { is_expected.to eq [:a, :a, 1, :c, 1] }
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ describe "#sort_by_index" do
225
+ let(:asc) { vector.sort_by_index }
226
+ let(:desc) { vector.sort_by_index(ascending: false) }
227
+
228
+ context 'numeric vector' do
229
+ let(:vector) { DaruLite::Vector.new [11, 13, 12], index: [23, 21, 22] }
230
+
231
+ specify { expect(asc.to_a).to eq [13, 12, 11] }
232
+ specify { expect(desc.to_a).to eq [11, 12, 13] }
233
+ end
234
+
235
+ context 'mix variable type index' do
236
+ let(:vector) { DaruLite::Vector.new [11, Float::NAN, nil], index: [21, 23, 22] }
237
+
238
+ specify { expect(asc.to_a).to eq [11, nil, Float::NAN] }
239
+ specify { expect(desc.to_a).to eq [Float::NAN, nil, 11] }
240
+ end
241
+ end
242
+ end