daru_lite 0.1

Sign up to get free protection for your applications and to get access to all the features.
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,1741 @@
1
+ describe DaruLite::Vector, "categorical" do
2
+ context "initialize" do
3
+ context "default parameters" do
4
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
5
+ subject { dv }
6
+
7
+ it { is_expected.to be_a DaruLite::Vector }
8
+ its(:size) { is_expected.to eq 5 }
9
+ its(:type) { is_expected.to eq :category }
10
+ its(:ordered?) { is_expected.to eq false }
11
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
12
+ its(:base_category) { is_expected.to eq :a }
13
+ its(:coding_scheme) { is_expected.to eq :dummy }
14
+ its(:index) { is_expected.to be_a DaruLite::Index }
15
+ its(:'index.to_a') { is_expected.to eq [0, 1, 2, 3, 4] }
16
+ end
17
+
18
+ context "with index" do
19
+ context "as array" do
20
+ let(:dv) do
21
+ DaruLite::Vector.new [:a, 1, :a, 1, :c],
22
+ type: :category,
23
+ index: ['a', 'b', 'c', 'd', 'e']
24
+ end
25
+ subject { dv }
26
+
27
+ its(:index) { is_expected.to be_a DaruLite::Index }
28
+ its(:'index.to_a') { is_expected.to eq ['a', 'b', 'c', 'd', 'e'] }
29
+ end
30
+
31
+ context "as range" do
32
+ let(:dv) do
33
+ DaruLite::Vector.new [:a, 1, :a, 1, :c],
34
+ type: :category,
35
+ index: 'a'..'e'
36
+ end
37
+ subject { dv }
38
+
39
+ its(:index) { is_expected.to be_a DaruLite::Index }
40
+ its(:'index.to_a') { is_expected.to eq ['a', 'b', 'c', 'd', 'e'] }
41
+ end
42
+
43
+ context "as index object" do
44
+ let(:tuples) do
45
+ [
46
+ [:one, :tin, :bar],
47
+ [:one, :pin, :bar],
48
+ [:two, :pin, :bar],
49
+ [:two, :tin, :bar],
50
+ [:thr, :pin, :foo]
51
+ ]
52
+ end
53
+ let(:idx) { DaruLite::MultiIndex.from_tuples tuples }
54
+ let(:dv) do
55
+ DaruLite::Vector.new [:a, 1, :a, 1, :c],
56
+ type: :category,
57
+ index: idx
58
+ end
59
+ subject { dv }
60
+
61
+ its(:index) { is_expected.to be_a DaruLite::MultiIndex }
62
+ its(:'index.to_a') { is_expected.to eq tuples }
63
+ end
64
+
65
+ context "invalid index" do
66
+ it { expect { DaruLite::Vector.new [1, 1, 2],
67
+ type: :category,
68
+ index: [1, 2]
69
+ }.to raise_error ArgumentError }
70
+ end
71
+ end
72
+
73
+ context '#category?' do
74
+ let(:non_cat) { DaruLite::Vector.new [1, 2, 3] }
75
+ let(:cat) { DaruLite::Vector.new [1, 2, 3], type: :category }
76
+ it { expect(non_cat.category?).to eq false }
77
+ it { expect(cat.category?).to eq true }
78
+ end
79
+
80
+ context "with categories" do
81
+ context "extra categories" do
82
+ subject { DaruLite::Vector.new [:a, 1, :a, 1, :c],
83
+ type: :category, categories: [:a, :b, :c, 1] }
84
+
85
+ it { is_expected.to be_a DaruLite::Vector }
86
+ its(:type) { is_expected.to eq :category }
87
+ its(:size) { is_expected.to eq 5 }
88
+ its(:order) { is_expected.to eq [:a, :b, :c, 1] }
89
+ its(:categories) { is_expected.to eq [:a, :b, :c, 1] }
90
+ end
91
+
92
+ context "incomplete" do
93
+ it do
94
+ expect { DaruLite::Vector.new [:a, 1, :a, 1, :c],
95
+ type: :category, categories: [:b, :c, 1] }.
96
+ to raise_error ArgumentError
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ context "#rename" do
103
+ let(:dv) { DaruLite::Vector.new [1, 2, 1], type: :category }
104
+ subject { dv.rename 'hello' }
105
+
106
+ it { is_expected.to be_a DaruLite::Vector }
107
+ its(:name) { is_expected.to eq 'hello' }
108
+ end
109
+
110
+ context '#index=' do
111
+ context DaruLite::Index do
112
+ let(:idx) { DaruLite::Index.new [1, 2, 3] }
113
+ let(:dv) { DaruLite::Vector.new ['a', 'b', 'c'], type: :category }
114
+ before { dv.index = idx }
115
+ subject { dv }
116
+
117
+ it { is_expected.to be_a DaruLite::Vector }
118
+ its(:index) { is_expected.to be_a DaruLite::Index }
119
+ its(:'index.to_a') { is_expected.to eq [1, 2, 3] }
120
+ end
121
+
122
+ context Range do
123
+ let(:dv) { DaruLite::Vector.new ['a', 'b', 'c'], type: :category }
124
+ before { dv.index = 1..3 }
125
+ subject { dv }
126
+
127
+ it { is_expected.to be_a DaruLite::Vector }
128
+ its(:index) { is_expected.to be_a DaruLite::Index }
129
+ its(:'index.to_a') { is_expected.to eq [1, 2, 3] }
130
+ end
131
+
132
+ context DaruLite::MultiIndex do
133
+ let(:idx) { DaruLite::MultiIndex.from_tuples [[:a, :one], [:a, :two], [:b, :one]] }
134
+ let(:dv) { DaruLite::Vector.new ['a', 'b', 'c'], type: :category }
135
+ before { dv.index = idx }
136
+ subject { dv }
137
+
138
+ it { is_expected.to be_a DaruLite::Vector }
139
+ its(:index) { is_expected.to be_a DaruLite::MultiIndex }
140
+ its(:'index.to_a') { is_expected.to eq [[:a, :one], [:a, :two], [:b, :one]] }
141
+ end
142
+ end
143
+
144
+ context "#cut" do
145
+ context "close at right end" do
146
+ let(:dv) { DaruLite::Vector.new [1, 2, 5, 14] }
147
+ subject { dv.cut (0..20).step(5) }
148
+
149
+ it { is_expected.to be_a DaruLite::Vector }
150
+ its(:type) { is_expected.to eq :category }
151
+ its(:size) { is_expected.to eq 4 }
152
+ its(:categories) { is_expected.to eq ['0-4', '5-9', '10-14', '15-19'] }
153
+ its(:to_a) { is_expected.to eq ['0-4', '0-4', '5-9', '10-14'] }
154
+ end
155
+
156
+ context "close at left end" do
157
+ let(:dv) { DaruLite::Vector.new [1, 2, 5, 14] }
158
+ subject { dv.cut (0..20).step(5), close_at: :left }
159
+
160
+ it { is_expected.to be_a DaruLite::Vector }
161
+ its(:type) { is_expected.to eq :category }
162
+ its(:size) { is_expected.to eq 4 }
163
+ its(:categories) { is_expected.to eq ['1-5', '6-10', '11-15', '16-20'] }
164
+ its(:to_a) { is_expected.to eq ['1-5', '1-5', '1-5', '11-15'] }
165
+ end
166
+
167
+ context "labels" do
168
+ let(:dv) { DaruLite::Vector.new [1, 2, 5, 14] }
169
+ subject { dv.cut (0..20).step(5), close_at: :left, labels: [:a, :b, :c, :d] }
170
+
171
+ it { is_expected.to be_a DaruLite::Vector }
172
+ its(:type) { is_expected.to eq :category }
173
+ its(:size) { is_expected.to eq 4 }
174
+ its(:categories) { is_expected.to eq [:a, :b, :c, :d] }
175
+ its(:to_a) { is_expected.to eq [:a, :a, :a, :c] }
176
+ end
177
+ end
178
+
179
+ context "#each" do
180
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c] }
181
+ subject { dv.each }
182
+
183
+ it { is_expected.to be_a Enumerator }
184
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
185
+ end
186
+
187
+ context "#to_a" do
188
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c] }
189
+ subject { dv.to_a }
190
+
191
+ it { is_expected.to be_a Array }
192
+ its(:size) { is_expected.to eq 5 }
193
+ it { is_expected.to eq [:a, 1, :a, 1, :c] }
194
+ end
195
+
196
+ context "#dup" do
197
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
198
+ before do
199
+ dv.categories = [:a, :b, :c, 1]
200
+ dv.name = 'daru'
201
+ dv.ordered = true
202
+ end
203
+ subject { dv.dup }
204
+
205
+ its(:type) { is_expected.to eq :category }
206
+ its(:ordered?) { is_expected.to eq true }
207
+ its(:categories) { is_expected.to eq [:a, :b, :c, 1] }
208
+ its(:name) { is_expected.to eq 'daru' }
209
+ end
210
+
211
+ context "#add_category" do
212
+ context "single category" do
213
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
214
+ subject { dv }
215
+ before { dv.add_category :b }
216
+
217
+ its(:categories) { is_expected.to eq [:a, 1, :c, :b] }
218
+ its(:order) { is_expected.to eq [:a, 1, :c, :b] }
219
+ end
220
+
221
+ context "multiple categories" do
222
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
223
+ subject { dv }
224
+ before { dv.add_category :b, :d }
225
+
226
+ its(:categories) { is_expected.to eq [:a, 1, :c, :b, :d] }
227
+ its(:order) { is_expected.to eq [:a, 1, :c, :b, :d] }
228
+ end
229
+ end
230
+
231
+ context '#remove_unused_categories' do
232
+ context 'base category not removed' do
233
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
234
+ before do
235
+ dv.categories = [:a, :b, :c, 1]
236
+ dv.base_category = 1
237
+ dv.remove_unused_categories
238
+ end
239
+ subject { dv }
240
+
241
+ its(:categories) { is_expected.to eq [:a, :c, 1] }
242
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
243
+ its(:base_category) { is_expected.to eq 1 }
244
+ end
245
+
246
+ context 'base category removed' do
247
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
248
+ before do
249
+ dv.categories = [:a, :b, :c, 1]
250
+ dv.base_category = :b
251
+ dv.remove_unused_categories
252
+ end
253
+ subject { dv }
254
+
255
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
256
+ its(:categories) { is_expected.to eq [:a, :c, 1] }
257
+ its(:base_category) { is_expected.to eq :a }
258
+ end
259
+ end
260
+
261
+ context "count" do
262
+ context "existant category" do
263
+ context "more than 0" do
264
+ subject(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
265
+
266
+ it { expect(dv.count :a).to eq 2 }
267
+ end
268
+
269
+ context "equal to 0" do
270
+ subject(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
271
+ before { dv.add_category :b }
272
+
273
+ it { expect(dv.count :b).to eq 0 }
274
+ end
275
+ end
276
+
277
+ context "non existant category" do
278
+ subject(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
279
+
280
+ it { expect { dv.count :k }.to raise_error ArgumentError }
281
+ end
282
+ end
283
+
284
+ context "#frequencies" do
285
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c],
286
+ type: :category,
287
+ name: :hello,
288
+ categories: [:a, :b, :c, :d, 1] }
289
+ context "counts" do
290
+ subject { dv.frequencies }
291
+
292
+ its(:'index.to_a') { is_expected.to eq [:a, :b, :c, :d, 1] }
293
+ its(:to_a) { is_expected.to eq [2, 0, 1, 0, 2] }
294
+ its(:name) { is_expected.to eq :hello }
295
+ end
296
+ context "percentage" do
297
+ subject { dv.frequencies :percentage }
298
+
299
+ its(:'index.to_a') { is_expected.to eq [:a, :b, :c, :d, 1] }
300
+ its(:to_a) { is_expected.to eq [40, 0, 20, 0, 40] }
301
+ end
302
+ context "fraction" do
303
+ subject { dv.frequencies :fraction }
304
+
305
+ its(:'index.to_a') { is_expected.to eq [:a, :b, :c, :d, 1] }
306
+ its(:to_a) { is_expected.to eq [0.4, 0, 0.2, 0, 0.4] }
307
+ end
308
+ context "invalid argument" do
309
+ it { expect { dv.frequencies :hash }.to raise_error ArgumentError }
310
+ end
311
+ end
312
+
313
+ context "#to_category" do
314
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], index: 1..5 }
315
+ subject { dv.to_category ordered: true, categories: [:a, :b, :c, 1] }
316
+
317
+ it { is_expected.to be_a DaruLite::Vector }
318
+ its(:size) { is_expected.to eq 5 }
319
+ its(:type) { is_expected.to eq :category }
320
+ its(:'index.to_a') { is_expected.to eq [1, 2, 3, 4, 5] }
321
+ its(:ordered?) { is_expected.to eq true }
322
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
323
+ its(:categories) { is_expected.to eq [:a, :b, :c, 1] }
324
+ end
325
+
326
+ context "#categories" do
327
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
328
+ subject { dv.categories }
329
+
330
+ it { is_expected.to be_a Array }
331
+ its(:size) { is_expected.to eq 3 }
332
+ its(:'to_a') { is_expected.to eq [:a, 1, :c] }
333
+ end
334
+
335
+ context "#categories=" do
336
+ context "extra categories" do
337
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c],
338
+ type: :category }
339
+ before { dv.categories = [:c, :b, :a, 1] }
340
+ subject { dv }
341
+
342
+ it { is_expected.to be_a DaruLite::Vector }
343
+ its(:type) { is_expected.to eq :category }
344
+ its(:categories) { is_expected.to eq [:c, :b, :a, 1] }
345
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
346
+ its(:base_category) { is_expected.to eq :a }
347
+ end
348
+
349
+ context "incomplete" do
350
+ subject { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
351
+
352
+ it do
353
+ expect { subject.categories = [:b, :c, 1] }.
354
+ to raise_error ArgumentError
355
+ end
356
+ end
357
+ end
358
+
359
+ context "#base_category" do
360
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
361
+ subject { dv }
362
+ before { dv.base_category = 1 }
363
+
364
+ its(:base_category) { is_expected.to eq 1 }
365
+ end
366
+
367
+ context "#coding_scheme" do
368
+ context "valid coding scheme" do
369
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
370
+ subject { dv }
371
+ before { dv.coding_scheme = :deviation }
372
+
373
+ its(:coding_scheme) { is_expected.to eq :deviation }
374
+ end
375
+
376
+ context "invalid coding scheme" do
377
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
378
+
379
+ it { expect { dv.coding_scheme = :foo }.to raise_error ArgumentError }
380
+ end
381
+ end
382
+
383
+ context "#rename_categories" do
384
+ context 'rename base category' do
385
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category,
386
+ categories: [:a, :x, :y, :c, :b, 1]}
387
+ subject { dv.rename_categories :a => 1, 1 => 2 }
388
+
389
+ it { is_expected.to be_a DaruLite::Vector }
390
+ its(:to_a) { is_expected.to eq [1, 2, 1, 2, :c] }
391
+ its(:categories) { is_expected.to eq [:x, :y, :c, :b, 1, 2] }
392
+ its(:base_category) { is_expected.to eq 1 }
393
+ end
394
+
395
+ context 'rename non-base category' do
396
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category,
397
+ categories: [:a, :b, :c, 1] }
398
+ subject { dv.rename_categories 1 => 2 }
399
+
400
+ it { is_expected.to be_a DaruLite::Vector }
401
+ its(:to_a) { is_expected.to eq [:a, 2, :a, 2, :c] }
402
+ its(:categories) { is_expected.to eq [:a, :b, :c, 2] }
403
+ its(:base_category) { is_expected.to eq :a }
404
+ end
405
+
406
+ context 'merge' do
407
+ let(:dv) { DaruLite::Vector.new [:a, :b, :c, :b, :e], type: :category }
408
+ before { dv.categories = [:a, :b, :c, :d, :e, :f] }
409
+ subject { dv.rename_categories :d => :a, :c => 1, :e => 1 }
410
+
411
+ it { is_expected.to be_a DaruLite::Vector }
412
+ its(:categories) { is_expected.to eq [:a, :b, :f, 1] }
413
+ its(:to_a) { is_expected.to eq [:a, :b, 1, :b, 1] }
414
+ end
415
+ end
416
+
417
+ context '#to_non_category' do
418
+ let(:dv) { DaruLite::Vector.new [1, 2, 3], type: :category,
419
+ index: [:a, :b, :c], name: :hello }
420
+ subject { dv.to_non_category }
421
+
422
+ it { is_expected.to be_a DaruLite::Vector }
423
+ its(:type) { is_expected.not_to eq :category }
424
+ its(:to_a) { is_expected.to eq [1, 2, 3] }
425
+ its(:'index.to_a') { is_expected.to eq [:a, :b, :c] }
426
+ its(:name) { is_expected.to eq :hello }
427
+ end
428
+
429
+ context '#to_category' do
430
+ let(:dv) { DaruLite::Vector.new [1, 2, 3], type: :category }
431
+ it { expect(dv.to_category).to eq dv }
432
+ end
433
+
434
+ context '#reindex!' do
435
+ context DaruLite::Index do
436
+ let(:dv) { DaruLite::Vector.new [3, 2, 1, 3, 2, 1],
437
+ index: 'a'..'f', type: :category, categories: [1, 2, 3, 4] }
438
+ before { dv.reindex! ['e', 'f', 'a', 'b', 'c', 'd'] }
439
+ subject { dv }
440
+
441
+ it { is_expected.to be_a DaruLite::Vector }
442
+ its(:categories) { is_expected.to eq [1, 2, 3, 4] }
443
+ its(:to_a) { is_expected.to eq [2, 1, 3, 2, 1, 3] }
444
+ end
445
+
446
+ context DaruLite::MultiIndex do
447
+ let(:tuples) do
448
+ [
449
+ [:a,:one,:baz],
450
+ [:a,:two,:bar],
451
+ [:a,:two,:baz],
452
+ [:b,:one,:bar],
453
+ [:b,:two,:bar],
454
+ [:b,:two,:baz]
455
+ ]
456
+ end
457
+ let(:idx) { DaruLite::MultiIndex.from_tuples tuples }
458
+ let(:dv) { DaruLite::Vector.new [3, 2, 1, 3, 2, 1],
459
+ index: idx, type: :category, categories: [1, 2, 3, 4] }
460
+ before { dv.reindex! [4, 5, 0, 1, 2, 3].map { |i| tuples[i] } }
461
+ subject { dv }
462
+
463
+ it { is_expected.to be_a DaruLite::Vector }
464
+ its(:categories) { is_expected.to eq [1, 2, 3, 4] }
465
+ its(:to_a) { is_expected.to eq [2, 1, 3, 2, 1, 3] }
466
+ its(:'index.to_a') { is_expected.to eq [4, 5, 0, 1, 2, 3]
467
+ .map { |i| tuples[i] } }
468
+ end
469
+
470
+ context 'invalid index' do
471
+ let(:dv) { DaruLite::Vector.new [1, 2, 3], type: :category }
472
+
473
+ it { expect { dv.reindex! [1, 1, 1] }.to raise_error ArgumentError }
474
+ end
475
+ end
476
+
477
+ context '#reorder!' do
478
+ context 'valid order' do
479
+ let(:dv) { DaruLite::Vector.new [3, 2, 1, 3, 2, 1], index: 'a'..'f', type: :category }
480
+ before { dv.reorder! [5, 4, 3, 2, 1, 0] }
481
+ subject { dv }
482
+
483
+ it { is_expected.to be_a DaruLite::Vector }
484
+ its(:categories) { is_expected.to eq [1, 2, 3] }
485
+ its(:to_a) { is_expected.to eq [1, 2, 3, 1, 2, 3] }
486
+ end
487
+
488
+ context 'invalid order' do
489
+ let(:dv) { DaruLite::Vector.new [1, 2, 3], type: :category }
490
+
491
+ it { expect { dv.reorder! [1, 1, 1] }.to raise_error ArgumentError }
492
+ end
493
+ end
494
+
495
+ context "#min" do
496
+ context "ordered" do
497
+ context "default ordering" do
498
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
499
+
500
+ it { expect(dv.min).to eq :a }
501
+ end
502
+
503
+ context "reorder" do
504
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
505
+ before { dv.categories = [1, :a, :c] }
506
+
507
+ it { expect(dv.min).to eq 1 }
508
+ end
509
+ end
510
+
511
+ context "unordered" do
512
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category }
513
+
514
+ it { expect { dv.min }.to raise_error ArgumentError }
515
+ end
516
+ end
517
+
518
+ context "#max" do
519
+ context "ordered" do
520
+ context "default ordering" do
521
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
522
+
523
+ it { expect(dv.max).to eq :c }
524
+ end
525
+
526
+ context "reorder" do
527
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
528
+ before { dv.categories = [1, :c, :a] }
529
+
530
+ it { expect(dv.max).to eq :a }
531
+ end
532
+ end
533
+
534
+ context "unordered" do
535
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c, :a], type: :category }
536
+
537
+ it { expect { dv.max }.to raise_error ArgumentError }
538
+ end
539
+ end
540
+
541
+ context "summary" do
542
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c, :a], type: :category }
543
+ subject { dv.describe }
544
+
545
+ it { is_expected.to be_a DaruLite::Vector }
546
+ its(:categories) { is_expected.to eq 3 }
547
+ its(:max_freq) { is_expected.to eq 3 }
548
+ its(:max_category) { is_expected.to eq :a }
549
+ its(:min_freq) { is_expected.to eq 1 }
550
+ its(:min_category) { is_expected.to eq :c }
551
+ end
552
+
553
+ context "#sort!" do
554
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
555
+ subject { dv }
556
+ before { dv.categories = [:c, :a, 1]; dv.sort! }
557
+
558
+ it { is_expected.to be_a DaruLite::Vector }
559
+ its(:size) { is_expected.to eq 5 }
560
+ its(:to_a) { is_expected.to eq [:c, :a, :a, 1, 1] }
561
+ its(:'index.to_a') { is_expected.to eq [4, 0, 2, 1, 3] }
562
+ end
563
+
564
+ context "#sort" do
565
+ context 'return sorted vector' do
566
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
567
+ subject { dv.sort }
568
+ before { dv.categories = [:c, :a, 1] }
569
+
570
+ it { is_expected.to be_a DaruLite::Vector }
571
+ its(:size) { is_expected.to eq 5 }
572
+ its(:to_a) { is_expected.to eq [:c, :a, :a, 1, 1] }
573
+ its(:'index.to_a') { is_expected.to eq [4, 0, 2, 1, 3] }
574
+ end
575
+
576
+ context 'original vector unaffected' do
577
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, ordered: true }
578
+ subject { dv }
579
+ before { dv.categories = [:c, :a, 1]; dv.sort }
580
+
581
+ it { is_expected.to be_a DaruLite::Vector }
582
+ its(:size) { is_expected.to eq 5 }
583
+ its(:to_a) { is_expected.to eq [:a, 1, :a, 1, :c] }
584
+ its(:'index.to_a') { is_expected.to eq [0, 1, 2, 3, 4] }
585
+ end
586
+ end
587
+
588
+ context "#[]" do
589
+ context DaruLite::Index do
590
+ before :each do
591
+ @dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga,
592
+ index: [:yoda, :anakin, :obi, :padme, :r2d2], type: :category
593
+ end
594
+
595
+ it "returns an element after passing an index" do
596
+ expect(@dv[:yoda]).to eq(1)
597
+ end
598
+
599
+ it "returns an element after passing a numeric index" do
600
+ expect(@dv[0]).to eq(1)
601
+ end
602
+
603
+ it "returns a vector with given indices for multiple indices" do
604
+ expect(@dv[:yoda, :anakin]).to eq(DaruLite::Vector.new([1,2], name: :yoda,
605
+ index: [:yoda, :anakin], type: :category))
606
+ end
607
+
608
+ it "returns a vector with given indices for multiple numeric indices" do
609
+ expect(@dv[0,1]).to eq(DaruLite::Vector.new([1,2], name: :yoda,
610
+ index: [:yoda, :anakin], type: :category))
611
+ end
612
+
613
+ it "returns a vector when specified symbol Range" do
614
+ expect(@dv[:yoda..:anakin]).to eq(DaruLite::Vector.new([1,2],
615
+ index: [:yoda, :anakin], name: :yoga, type: :category))
616
+ end
617
+
618
+ it "returns a vector when specified numeric Range" do
619
+ expect(@dv[3..4]).to eq(DaruLite::Vector.new([4,5], name: :yoga,
620
+ index: [:padme, :r2d2], type: :category))
621
+ end
622
+
623
+ it "returns correct results for index of multiple index" do
624
+ v = DaruLite::Vector.new([1,2,3,4], index: ['a','c',1,:a], type: :category)
625
+ expect(v['a']).to eq(1)
626
+ expect(v[:a]).to eq(4)
627
+ expect(v[1]).to eq(3)
628
+ expect(v[0]).to eq(1)
629
+ end
630
+
631
+ it "raises exception for invalid index" do
632
+ expect { @dv[:foo] }.to raise_error(IndexError)
633
+ expect { @dv[:obi, :foo] }.to raise_error(IndexError)
634
+ end
635
+
636
+ context "preserves old categories" do
637
+ let(:dv) do
638
+ DaruLite::Vector.new [:a, :a, :b, :c, :b],
639
+ type: :category,
640
+ categories: [:c, :b, :a, :e]
641
+ end
642
+ subject { dv[0, 1, 4] }
643
+
644
+ it { is_expected.to be_a DaruLite::Vector }
645
+ its(:categories) { is_expected.to eq [:c, :b, :a, :e] }
646
+ its(:to_a) { is_expected.to eq [:a, :a, :b] }
647
+ end
648
+ end
649
+
650
+ context DaruLite::MultiIndex do
651
+ before do
652
+ @tuples = [
653
+ [:a,:one,:bar],
654
+ [:a,:one,:baz],
655
+ [:a,:two,:bar],
656
+ [:a,:two,:baz],
657
+ [:b,:one,:bar],
658
+ [:b,:two,:bar],
659
+ [:b,:two,:baz],
660
+ [:b,:one,:foo],
661
+ [:c,:one,:bar],
662
+ [:c,:one,:baz],
663
+ [:c,:two,:foo],
664
+ [:c,:two,:bar],
665
+ [:d,:one,:foo]
666
+ ]
667
+ @multi_index = DaruLite::MultiIndex.from_tuples(@tuples)
668
+ @vector = DaruLite::Vector.new(
669
+ Array.new(13) { |i| i }, index: @multi_index,
670
+ name: :mi_vector, type: :category)
671
+ end
672
+
673
+ it "returns a single element when passed a row number" do
674
+ expect(@vector[1]).to eq(1)
675
+ end
676
+
677
+ it "returns a single element when passed the full tuple" do
678
+ expect(@vector[:a, :one, :baz]).to eq(1)
679
+ end
680
+
681
+ it "returns sub vector when passed first layer of tuple" do
682
+ mi = DaruLite::MultiIndex.from_tuples([
683
+ [:one,:bar],
684
+ [:one,:baz],
685
+ [:two,:bar],
686
+ [:two,:baz]])
687
+ expect(@vector[:a]).to eq(DaruLite::Vector.new([0,1,2,3], index: mi,
688
+ name: :sub_vector, type: :category))
689
+ end
690
+
691
+ it "returns sub vector when passed first and second layer of tuple" do
692
+ mi = DaruLite::MultiIndex.from_tuples([
693
+ [:foo],
694
+ [:bar]])
695
+ expect(@vector[:c,:two]).to eq(DaruLite::Vector.new([10,11], index: mi,
696
+ name: :sub_sub_vector, type: :category))
697
+ end
698
+
699
+ it "returns sub vector not a single element when passed the partial tuple" do
700
+ mi = DaruLite::MultiIndex.from_tuples([[:foo]])
701
+ expect(@vector[:d, :one]).to eq(DaruLite::Vector.new([12], index: mi,
702
+ name: :sub_sub_vector, type: :category))
703
+ end
704
+
705
+ it "returns a vector with corresponding MultiIndex when specified numeric Range" do
706
+ mi = DaruLite::MultiIndex.from_tuples([
707
+ [:a,:two,:baz],
708
+ [:b,:one,:bar],
709
+ [:b,:two,:bar],
710
+ [:b,:two,:baz],
711
+ [:b,:one,:foo],
712
+ [:c,:one,:bar],
713
+ [:c,:one,:baz]
714
+ ])
715
+ expect(@vector[3..9]).to eq(DaruLite::Vector.new([3,4,5,6,7,8,9], index: mi,
716
+ name: :slice, type: :category))
717
+ end
718
+
719
+ it "raises exception for invalid index" do
720
+ expect { @vector[:foo] }.to raise_error(IndexError)
721
+ expect { @vector[:a, :two, :foo] }.to raise_error(IndexError)
722
+ expect { @vector[:x, :one] }.to raise_error(IndexError)
723
+ end
724
+ end
725
+
726
+ context DaruLite::CategoricalIndex do
727
+ context "non-numerical index" do
728
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, :b, :a, :a, :c] }
729
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx, type: :category }
730
+
731
+ context "single category" do
732
+ context "multiple instances" do
733
+ subject { dv[:a] }
734
+
735
+ it { is_expected.to be_a DaruLite::Vector }
736
+ its(:type) { is_expected.to eq :category }
737
+ its(:size) { is_expected.to eq 3 }
738
+ its(:to_a) { is_expected.to eq ['a', 'c', 'd'] }
739
+ its(:index) { is_expected.to eq(
740
+ DaruLite::CategoricalIndex.new([:a, :a, :a])) }
741
+ end
742
+
743
+ context "single instance" do
744
+ subject { dv[:c] }
745
+
746
+ it { is_expected.to eq 'e' }
747
+ end
748
+ end
749
+
750
+ context "multiple categories" do
751
+ subject { dv[:a, :c] }
752
+
753
+ it { is_expected.to be_a DaruLite::Vector }
754
+ its(:type) { is_expected.to eq :category }
755
+ its(:size) { is_expected.to eq 4 }
756
+ its(:to_a) { is_expected.to eq ['a', 'c', 'd', 'e'] }
757
+ its(:index) { is_expected.to eq(
758
+ DaruLite::CategoricalIndex.new([:a, :a, :a, :c])) }
759
+ end
760
+
761
+ context "multiple positional indexes" do
762
+ subject { dv[0, 1, 2] }
763
+
764
+ it { is_expected.to be_a DaruLite::Vector }
765
+ its(:type) { is_expected.to eq :category }
766
+ its(:size) { is_expected.to eq 3 }
767
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
768
+ its(:index) { is_expected.to eq(
769
+ DaruLite::CategoricalIndex.new([:a, :b, :a])) }
770
+ end
771
+
772
+ context "single positional index" do
773
+ subject { dv[1] }
774
+
775
+ it { is_expected.to eq 'b' }
776
+ end
777
+
778
+ context "invalid category" do
779
+ it { expect { dv[:x] }.to raise_error IndexError }
780
+ end
781
+
782
+ context "invalid positional index" do
783
+ it { expect { dv[30] }.to raise_error IndexError }
784
+ end
785
+ end
786
+
787
+ context "numerical index" do
788
+ let (:idx) { DaruLite::CategoricalIndex.new [1, 1, 2, 2, 3] }
789
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx, type: :category }
790
+
791
+ context "single category" do
792
+ context "multiple instances" do
793
+ subject { dv[1] }
794
+
795
+ it { is_expected.to be_a DaruLite::Vector }
796
+ its(:type) { is_expected.to eq :category }
797
+ its(:size) { is_expected.to eq 2 }
798
+ its(:to_a) { is_expected.to eq ['a', 'b'] }
799
+ its(:index) { is_expected.to eq(
800
+ DaruLite::CategoricalIndex.new([1, 1])) }
801
+ end
802
+
803
+ context "single instance" do
804
+ subject { dv[3] }
805
+
806
+ it { is_expected.to eq 'e' }
807
+ end
808
+ end
809
+ end
810
+ end
811
+ end
812
+
813
+ context "#[]=" do
814
+ context DaruLite::Index do
815
+ before :each do
816
+ @dv = DaruLite::Vector.new [1,2,3,4,5], name: :yoga,
817
+ index: [:yoda, :anakin, :obi, :padme, :r2d2], type: :category
818
+ @dv.add_category 666
819
+ end
820
+
821
+ it "assigns at the specified index" do
822
+ @dv[:yoda] = 666
823
+ expect(@dv[:yoda]).to eq(666)
824
+ end
825
+
826
+ it "assigns at the specified Integer index" do
827
+ @dv[0] = 666
828
+ expect(@dv[:yoda]).to eq(666)
829
+ end
830
+
831
+ it "assigns correctly for a mixed index Vector" do
832
+ v = DaruLite::Vector.new [1,2,3,4], index: ['a',:a,0,66], type: :category
833
+ v.add_category 666
834
+ v['a'] = 666
835
+ expect(v['a']).to eq(666)
836
+
837
+ v[0] = 666
838
+ expect(v[0]).to eq(666)
839
+
840
+ v[3] = 666
841
+ expect(v[3]).to eq(666)
842
+
843
+ expect(v).to eq(DaruLite::Vector.new([666,2,666,666],
844
+ index: ['a',:a,0,66], type: :category))
845
+ end
846
+ end
847
+
848
+ context DaruLite::MultiIndex do
849
+ before :each do
850
+ @tuples = [
851
+ [:a,:one,:bar],
852
+ [:a,:one,:baz],
853
+ [:a,:two,:bar],
854
+ [:a,:two,:baz],
855
+ [:b,:one,:bar],
856
+ [:b,:two,:bar],
857
+ [:b,:two,:baz],
858
+ [:b,:one,:foo],
859
+ [:c,:one,:bar],
860
+ [:c,:one,:baz],
861
+ [:c,:two,:foo],
862
+ [:c,:two,:bar]
863
+ ]
864
+ @multi_index = DaruLite::MultiIndex.from_tuples(@tuples)
865
+ @vector = DaruLite::Vector.new Array.new(12) { |i| i }, index: @multi_index,
866
+ type: :category, name: :mi_vector
867
+ @vector.add_category 69
868
+ end
869
+
870
+ it "assigns all lower layer indices when specified a first layer index" do
871
+ @vector[:b] = 69
872
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,69,69,69,69,8,9,10,11],
873
+ index: @multi_index, name: :top_layer_assignment, type: :category
874
+ ))
875
+ end
876
+
877
+ it "assigns all lower indices when specified first and second layer index" do
878
+ @vector[:b, :one] = 69
879
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,69,5,6,69,8,9,10,11],
880
+ index: @multi_index, name: :second_layer_assignment, type: :category))
881
+ end
882
+
883
+ it "assigns just the precise value when specified complete tuple" do
884
+ @vector[:b, :one, :foo] = 69
885
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,4,5,6,69,8,9,10,11],
886
+ index: @multi_index, name: :precise_assignment, type: :category))
887
+ end
888
+
889
+ it "assigns correctly when numeric index" do
890
+ @vector[7] = 69
891
+ expect(@vector).to eq(DaruLite::Vector.new([0,1,2,3,4,5,6,69,8,9,10,11],
892
+ index: @multi_index, name: :precise_assignment, type: :category))
893
+ end
894
+
895
+ it "fails predictably on unknown index" do
896
+ expect { @vector[:d] = 69 }.to raise_error(IndexError)
897
+ expect { @vector[:b, :three] = 69 }.to raise_error(IndexError)
898
+ expect { @vector[:b, :two, :test] = 69 }.to raise_error(IndexError)
899
+ end
900
+ end
901
+
902
+ context DaruLite::CategoricalIndex do
903
+ context "non-numerical index" do
904
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, :b, :a, :a, :c] }
905
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx, type: :category }
906
+ before { dv.add_category 'x' }
907
+
908
+ context "single category" do
909
+ context "multiple instances" do
910
+ subject { dv }
911
+ before { dv[:a] = 'x' }
912
+
913
+ its(:size) { is_expected.to eq 5 }
914
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x', 'x', 'e'] }
915
+ its(:index) { is_expected.to eq idx }
916
+ end
917
+
918
+ context "single instance" do
919
+ subject { dv }
920
+ before { dv[:b] = 'x' }
921
+
922
+ its(:size) { is_expected.to eq 5 }
923
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
924
+ its(:index) { is_expected.to eq idx }
925
+ end
926
+ end
927
+
928
+ context "multiple categories" do
929
+ subject { dv }
930
+ before { dv[:a, :c] = 'x' }
931
+
932
+ its(:size) { is_expected.to eq 5 }
933
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x', 'x', 'x'] }
934
+ its(:index) { is_expected.to eq idx }
935
+ end
936
+
937
+ context "multiple positional indexes" do
938
+ subject { dv }
939
+ before { dv[0, 1, 2] = 'x' }
940
+
941
+ its(:size) { is_expected.to eq 5 }
942
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'd', 'e'] }
943
+ its(:index) { is_expected.to eq idx }
944
+ end
945
+
946
+ context "single positional index" do
947
+ subject { dv }
948
+ before { dv[1] = 'x' }
949
+
950
+ its(:size) { is_expected.to eq 5 }
951
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
952
+ its(:index) { is_expected.to eq idx }
953
+ end
954
+
955
+ context "invalid category" do
956
+ it { expect { dv[:x] = 'x' }.to raise_error IndexError }
957
+ end
958
+
959
+ context "invalid positional index" do
960
+ it { expect { dv[30] = 'x'}.to raise_error IndexError }
961
+ end
962
+ end
963
+
964
+ context "numerical index" do
965
+ let (:idx) { DaruLite::CategoricalIndex.new [1, 1, 2, 2, 3] }
966
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx, type: :category }
967
+ before { dv.add_category 'x' }
968
+
969
+ context "single category" do
970
+ subject { dv }
971
+ before { dv[1] = 'x' }
972
+
973
+ its(:size) { is_expected.to eq 5 }
974
+ its(:to_a) { is_expected.to eq ['x', 'x', 'c', 'd', 'e'] }
975
+ its(:index) { is_expected.to eq idx }
976
+ end
977
+
978
+ context "multiple categories" do
979
+ subject { dv }
980
+ before { dv[1, 2] = 'x' }
981
+
982
+ its(:size) { is_expected.to eq 5 }
983
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'x', 'e'] }
984
+ its(:index) { is_expected.to eq idx }
985
+ end
986
+ end
987
+ end
988
+ end
989
+
990
+ context "#at" do
991
+ context DaruLite::Index do
992
+ let (:idx) { DaruLite::Index.new [1, 0, :c] }
993
+ let (:dv) { DaruLite::Vector.new ['a', 'b', 'c'], index: idx, type: :category }
994
+
995
+ context "single position" do
996
+ it { expect(dv.at 1).to eq 'b' }
997
+ end
998
+
999
+ context "multiple positions" do
1000
+ subject { dv.at 0, 2 }
1001
+
1002
+ it { is_expected.to be_a DaruLite::Vector }
1003
+ its(:type) { is_expected.to eq :category }
1004
+ its(:size) { is_expected.to eq 2 }
1005
+ its(:to_a) { is_expected.to eq ['a', 'c'] }
1006
+ its(:'index.to_a') { is_expected.to eq [1, :c] }
1007
+ end
1008
+
1009
+ context "invalid position" do
1010
+ it { expect { dv.at 3 }.to raise_error IndexError }
1011
+ end
1012
+
1013
+ context "invalid positions" do
1014
+ it { expect { dv.at 2, 3 }.to raise_error IndexError }
1015
+ end
1016
+
1017
+ context "range" do
1018
+ subject { dv.at 0..1 }
1019
+
1020
+ it { is_expected.to be_a DaruLite::Vector }
1021
+ its(:type) { is_expected.to eq :category }
1022
+ its(:size) { is_expected.to eq 2 }
1023
+ its(:to_a) { is_expected.to eq ['a', 'b'] }
1024
+ its(:'index.to_a') { is_expected.to eq [1, 0] }
1025
+ end
1026
+
1027
+ context "range with negative end" do
1028
+ subject { dv.at 0..-2 }
1029
+
1030
+ it { is_expected.to be_a DaruLite::Vector }
1031
+ its(:type) { is_expected.to eq :category }
1032
+ its(:size) { is_expected.to eq 2 }
1033
+ its(:to_a) { is_expected.to eq ['a', 'b'] }
1034
+ its(:'index.to_a') { is_expected.to eq [1, 0] }
1035
+ end
1036
+
1037
+ context "range with single element" do
1038
+ subject { dv.at 0..0 }
1039
+
1040
+ it { is_expected.to be_a DaruLite::Vector }
1041
+ its(:type) { is_expected.to eq :category }
1042
+ its(:size) { is_expected.to eq 1 }
1043
+ its(:to_a) { is_expected.to eq ['a'] }
1044
+ its(:'index.to_a') { is_expected.to eq [1] }
1045
+ end
1046
+
1047
+ context "preserves old categories" do
1048
+ let(:dv) do
1049
+ DaruLite::Vector.new [:a, :a, :b, :c, :b],
1050
+ type: :category,
1051
+ categories: [:c, :b, :a, :e]
1052
+ end
1053
+ subject { dv.at 0, 1, 4 }
1054
+
1055
+ it { is_expected.to be_a DaruLite::Vector }
1056
+ its(:categories) { is_expected.to eq [:c, :b, :a, :e] }
1057
+ its(:to_a) { is_expected.to eq [:a, :a, :b] }
1058
+ end
1059
+ end
1060
+
1061
+ context DaruLite::MultiIndex do
1062
+ let (:idx) do
1063
+ DaruLite::MultiIndex.from_tuples [
1064
+ [:a,:one,:bar],
1065
+ [:a,:one,:baz],
1066
+ [:b,:two,:bar],
1067
+ [:a,:two,:baz],
1068
+ ]
1069
+ end
1070
+ let (:dv) { DaruLite::Vector.new 1..4, index: idx, type: :category }
1071
+
1072
+ context "single position" do
1073
+ it { expect(dv.at 1).to eq 2 }
1074
+ end
1075
+
1076
+ context "multiple positions" do
1077
+ subject { dv.at 2, 3 }
1078
+
1079
+ it { is_expected.to be_a DaruLite::Vector }
1080
+ its(:type) { is_expected.to eq :category }
1081
+ its(:size) { is_expected.to eq 2 }
1082
+ its(:to_a) { is_expected.to eq [3, 4] }
1083
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar],
1084
+ [:a, :two, :baz]] }
1085
+ end
1086
+
1087
+ context "invalid position" do
1088
+ it { expect { dv.at 4 }.to raise_error IndexError }
1089
+ end
1090
+
1091
+ context "invalid positions" do
1092
+ it { expect { dv.at 2, 4 }.to raise_error IndexError }
1093
+ end
1094
+
1095
+ context "range" do
1096
+ subject { dv.at 2..3 }
1097
+
1098
+ it { is_expected.to be_a DaruLite::Vector }
1099
+ its(:type) { is_expected.to eq :category }
1100
+ its(:size) { is_expected.to eq 2 }
1101
+ its(:to_a) { is_expected.to eq [3, 4] }
1102
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar],
1103
+ [:a, :two, :baz]] }
1104
+ end
1105
+
1106
+ context "range with negative end" do
1107
+ subject { dv.at 2..-1 }
1108
+
1109
+ it { is_expected.to be_a DaruLite::Vector }
1110
+ its(:type) { is_expected.to eq :category }
1111
+ its(:size) { is_expected.to eq 2 }
1112
+ its(:to_a) { is_expected.to eq [3, 4] }
1113
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar],
1114
+ [:a, :two, :baz]] }
1115
+ end
1116
+
1117
+ context "range with single element" do
1118
+ subject { dv.at 2..2 }
1119
+
1120
+ it { is_expected.to be_a DaruLite::Vector }
1121
+ its(:type) { is_expected.to eq :category }
1122
+ its(:size) { is_expected.to eq 1 }
1123
+ its(:to_a) { is_expected.to eq [3] }
1124
+ its(:'index.to_a') { is_expected.to eq [[:b, :two, :bar]] }
1125
+ end
1126
+ end
1127
+
1128
+ context DaruLite::CategoricalIndex do
1129
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, 1, 1, :a, :c] }
1130
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx, type: :category }
1131
+
1132
+ context "multiple positional indexes" do
1133
+ subject { dv.at 0, 1, 2 }
1134
+
1135
+ it { is_expected.to be_a DaruLite::Vector }
1136
+ its(:type) { is_expected.to eq :category }
1137
+ its(:size) { is_expected.to eq 3 }
1138
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
1139
+ its(:index) { is_expected.to eq(
1140
+ DaruLite::CategoricalIndex.new([:a, 1, 1])) }
1141
+ end
1142
+
1143
+ context "single positional index" do
1144
+ subject { dv.at 1 }
1145
+
1146
+ it { is_expected.to eq 'b' }
1147
+ end
1148
+
1149
+ context "invalid position" do
1150
+ it { expect { dv.at 5 }.to raise_error IndexError }
1151
+ end
1152
+
1153
+ context "invalid positions" do
1154
+ it { expect { dv.at 2, 5 }.to raise_error IndexError }
1155
+ end
1156
+
1157
+ context "range" do
1158
+ subject { dv.at 0..2 }
1159
+
1160
+ it { is_expected.to be_a DaruLite::Vector }
1161
+ its(:type) { is_expected.to eq :category }
1162
+ its(:size) { is_expected.to eq 3 }
1163
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
1164
+ its(:index) { is_expected.to eq(
1165
+ DaruLite::CategoricalIndex.new([:a, 1, 1])) }
1166
+ end
1167
+
1168
+ context "range with negative end" do
1169
+ subject { dv.at 0..-3 }
1170
+
1171
+ it { is_expected.to be_a DaruLite::Vector }
1172
+ its(:type) { is_expected.to eq :category }
1173
+ its(:size) { is_expected.to eq 3 }
1174
+ its(:to_a) { is_expected.to eq ['a', 'b', 'c'] }
1175
+ its(:index) { is_expected.to eq(
1176
+ DaruLite::CategoricalIndex.new([:a, 1, 1])) }
1177
+ end
1178
+
1179
+ context "range with single element" do
1180
+ subject { dv.at 0..0 }
1181
+
1182
+ it { is_expected.to be_a DaruLite::Vector }
1183
+ its(:type) { is_expected.to eq :category }
1184
+ its(:size) { is_expected.to eq 1 }
1185
+ its(:to_a) { is_expected.to eq ['a'] }
1186
+ its(:index) { is_expected.to eq(
1187
+ DaruLite::CategoricalIndex.new([:a])) }
1188
+ end
1189
+ end
1190
+ end
1191
+
1192
+ context "#set_at" do
1193
+ context DaruLite::Index do
1194
+ let (:idx) { DaruLite::Index.new [1, 0, :c] }
1195
+ let (:dv) { DaruLite::Vector.new ['a', 'b', 'c'], index: idx, type: :category }
1196
+ before { dv.add_category 'x' }
1197
+
1198
+ context "single position" do
1199
+ subject { dv }
1200
+ before { dv.set_at [1], 'x' }
1201
+
1202
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c'] }
1203
+ end
1204
+
1205
+ context "multiple positions" do
1206
+ subject { dv }
1207
+ before { dv.set_at [0, 2], 'x' }
1208
+
1209
+ its(:to_a) { is_expected.to eq ['x', 'b', 'x'] }
1210
+ end
1211
+
1212
+ context "invalid position" do
1213
+ it { expect { dv.set_at [3], 'x' }.to raise_error IndexError }
1214
+ end
1215
+
1216
+ context "invalid positions" do
1217
+ it { expect { dv.set_at [2, 3], 'x' }.to raise_error IndexError }
1218
+ end
1219
+ end
1220
+
1221
+ context DaruLite::MultiIndex do
1222
+ let(:idx) do
1223
+ DaruLite::MultiIndex.from_tuples [
1224
+ [:a,:one,:bar],
1225
+ [:a,:one,:baz],
1226
+ [:b,:two,:bar],
1227
+ [:a,:two,:baz],
1228
+ ]
1229
+ end
1230
+ let(:dv) { DaruLite::Vector.new 1..4, index: idx, type: :category }
1231
+ before { dv.add_category 'x' }
1232
+
1233
+ context "single position" do
1234
+ subject { dv }
1235
+ before { dv.set_at [1], 'x' }
1236
+
1237
+ its(:to_a) { is_expected.to eq [1, 'x', 3, 4] }
1238
+ end
1239
+
1240
+ context "multiple positions" do
1241
+ subject { dv }
1242
+ before { dv.set_at [2, 3], 'x' }
1243
+
1244
+ its(:to_a) { is_expected.to eq [1, 2, 'x', 'x'] }
1245
+ end
1246
+
1247
+ context "invalid position" do
1248
+ it { expect { dv.set_at [4], 'x' }.to raise_error IndexError }
1249
+ end
1250
+
1251
+ context "invalid positions" do
1252
+ it { expect { dv.set_at [2, 4], 'x' }.to raise_error IndexError }
1253
+ end
1254
+ end
1255
+
1256
+ context DaruLite::CategoricalIndex do
1257
+ let (:idx) { DaruLite::CategoricalIndex.new [:a, 1, 1, :a, :c] }
1258
+ let (:dv) { DaruLite::Vector.new 'a'..'e', index: idx, type: :category }
1259
+ before { dv.add_category 'x' }
1260
+
1261
+ context "multiple positional indexes" do
1262
+ subject { dv }
1263
+ before { dv.set_at [0, 1, 2], 'x' }
1264
+
1265
+ its(:to_a) { is_expected.to eq ['x', 'x', 'x', 'd', 'e'] }
1266
+ end
1267
+
1268
+ context "single positional index" do
1269
+ subject { dv }
1270
+ before { dv.set_at [1], 'x' }
1271
+
1272
+ its(:to_a) { is_expected.to eq ['a', 'x', 'c', 'd', 'e'] }
1273
+ end
1274
+
1275
+ context "invalid position" do
1276
+ it { expect { dv.set_at [5], 'x' }.to raise_error IndexError }
1277
+ end
1278
+
1279
+ context "invalid positions" do
1280
+ it { expect { dv.set_at [2, 5], 'x' }.to raise_error IndexError }
1281
+ end
1282
+ end
1283
+ end
1284
+
1285
+ context "#contrast_code" do
1286
+ context "dummy coding" do
1287
+ context "default base category" do
1288
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1289
+ subject { dv.contrast_code }
1290
+
1291
+ it { is_expected.to be_a DaruLite::DataFrame }
1292
+ its(:shape) { is_expected.to eq [5, 2] }
1293
+ its(:'abc_1.to_a') { is_expected.to eq [0, 1, 0, 1, 0] }
1294
+ its(:'abc_c.to_a') { is_expected.to eq [0, 0, 0, 0, 1] }
1295
+ end
1296
+
1297
+ context "manual base category" do
1298
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1299
+ before { dv.base_category = :c }
1300
+ subject { dv.contrast_code }
1301
+
1302
+ it { is_expected.to be_a DaruLite::DataFrame }
1303
+ its(:shape) { is_expected.to eq [5, 2] }
1304
+ its(:'abc_a.to_a') { is_expected.to eq [1, 0, 1, 0, 0] }
1305
+ its(:'abc_1.to_a') { is_expected.to eq [0, 1, 0, 1, 0] }
1306
+ end
1307
+ end
1308
+
1309
+ context "simple coding" do
1310
+ context "default base category" do
1311
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1312
+ subject { dv.contrast_code }
1313
+ before { dv.coding_scheme = :simple }
1314
+
1315
+ it { is_expected.to be_a DaruLite::DataFrame }
1316
+ its(:shape) { is_expected.to eq [5, 2] }
1317
+ its(:'abc_1.to_a') { is_expected.to eq [-1/3.0, 2/3.0, -1/3.0, 2/3.0, -1/3.0] }
1318
+ its(:'abc_c.to_a') { is_expected.to eq [-1/3.0, -1/3.0, -1/3.0, -1/3.0, 2/3.0] }
1319
+ end
1320
+
1321
+ context "manual base category" do
1322
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1323
+ subject { dv.contrast_code }
1324
+ before do
1325
+ dv.coding_scheme = :simple
1326
+ dv.base_category = :c
1327
+ end
1328
+
1329
+ it { is_expected.to be_a DaruLite::DataFrame }
1330
+ its(:shape) { is_expected.to eq [5, 2] }
1331
+ its(:'abc_a.to_a') { is_expected.to eq [2/3.0, -1/3.0, 2/3.0, -1/3.0, -1/3.0] }
1332
+ its(:'abc_1.to_a') { is_expected.to eq [-1/3.0, 2/3.0, -1/3.0, 2/3.0, -1/3.0] }
1333
+ end
1334
+ end
1335
+
1336
+ context "helmert coding" do
1337
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1338
+ subject { dv.contrast_code }
1339
+ before { dv.coding_scheme = :helmert }
1340
+
1341
+ it { is_expected.to be_a DaruLite::DataFrame }
1342
+ its(:shape) { is_expected.to eq [5, 2] }
1343
+ its(:'abc_a.to_a') { is_expected.to eq [2/3.0, -1/3.0, 2/3.0, -1/3.0, -1/3.0] }
1344
+ its(:'abc_1.to_a') { is_expected.to eq [0, 1/2.0, 0, 1/2.0, -1/2.0] }
1345
+ end
1346
+
1347
+ context "deviation coding" do
1348
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1349
+ subject { dv.contrast_code }
1350
+ before { dv.coding_scheme = :deviation }
1351
+
1352
+ it { is_expected.to be_a DaruLite::DataFrame }
1353
+ its(:shape) { is_expected.to eq [5, 2] }
1354
+ its(:'abc_a.to_a') { is_expected.to eq [1, 0, 1, 0, -1] }
1355
+ its(:'abc_1.to_a') { is_expected.to eq [0, 1, 0, 1, -1] }
1356
+ end
1357
+
1358
+ context "user-defined coding" do
1359
+ let(:df) do
1360
+ DaruLite::DataFrame.new({
1361
+ rank_level1: [1, -2, -3],
1362
+ rank_level2: [-4, 2, -1],
1363
+ rank_level3: [-3, -1, 5]
1364
+ }, index: ['I', 'II', 'III'])
1365
+ end
1366
+ let(:dv) { DaruLite::Vector.new ['III', 'II', 'I', 'II', 'II'],
1367
+ name: :rank, type: :category }
1368
+ subject { dv.contrast_code user_defined: df }
1369
+
1370
+ it { is_expected.to be_a DaruLite::DataFrame }
1371
+ its(:shape) { is_expected.to eq [5, 3] }
1372
+ its(:'rank_level1.to_a') { is_expected.to eq [-3, -2, 1, -2, -2] }
1373
+ its(:'rank_level2.to_a') { is_expected.to eq [-1, 2, -4, 2, 2] }
1374
+ its(:'rank_level3.to_a') { is_expected.to eq [5, -1, -3, -1, -1] }
1375
+ end
1376
+
1377
+ context 'naming' do
1378
+ context "string" do
1379
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: 'abc' }
1380
+ subject { dv.contrast_code }
1381
+
1382
+ it { is_expected.to be_a DaruLite::DataFrame }
1383
+ its(:'vectors.to_a') { is_expected.to eq ['abc_1', 'abc_c'] }
1384
+ end
1385
+
1386
+ context "symbol" do
1387
+ let(:dv) { DaruLite::Vector.new [:a, 1, :a, 1, :c], type: :category, name: :abc }
1388
+ subject { dv.contrast_code }
1389
+
1390
+ it { is_expected.to be_a DaruLite::DataFrame }
1391
+ its(:'vectors.to_a') { is_expected.to eq [:abc_1, :abc_c] }
1392
+ end
1393
+ end
1394
+ end
1395
+
1396
+ context '#reject_values'do
1397
+ let(:dv) { DaruLite::Vector.new [1, nil, 3, :a, Float::NAN, nil, Float::NAN, 1],
1398
+ index: 11..18, type: :category }
1399
+ context 'reject only nils' do
1400
+ subject { dv.reject_values nil }
1401
+
1402
+ it { is_expected.to be_a DaruLite::Vector }
1403
+ its(:type) { is_expected.to eq :category }
1404
+ its(:to_a) { is_expected.to eq [1, 3, :a, Float::NAN, Float::NAN, 1] }
1405
+ its(:'index.to_a') { is_expected.to eq [11, 13, 14, 15, 17, 18] }
1406
+ end
1407
+
1408
+ context 'reject only float::NAN' do
1409
+ subject { dv.reject_values Float::NAN }
1410
+
1411
+ it { is_expected.to be_a DaruLite::Vector }
1412
+ its(:type) { is_expected.to eq :category }
1413
+ its(:to_a) { is_expected.to eq [1, nil, 3, :a, nil, 1] }
1414
+ its(:'index.to_a') { is_expected.to eq [11, 12, 13, 14, 16, 18] }
1415
+ end
1416
+
1417
+ context 'reject both nil and float::NAN' do
1418
+ subject { dv.reject_values nil, Float::NAN }
1419
+
1420
+ it { is_expected.to be_a DaruLite::Vector }
1421
+ its(:type) { is_expected.to eq :category }
1422
+ its(:to_a) { is_expected.to eq [1, 3, :a, 1] }
1423
+ its(:'index.to_a') { is_expected.to eq [11, 13, 14, 18] }
1424
+ end
1425
+
1426
+ context 'reject any other value' do
1427
+ subject { dv.reject_values 1, 3, 20 }
1428
+
1429
+ it { is_expected.to be_a DaruLite::Vector }
1430
+ its(:type) { is_expected.to eq :category }
1431
+ its(:to_a) { is_expected.to eq [nil, :a, Float::NAN, nil, Float::NAN] }
1432
+ its(:'index.to_a') { is_expected.to eq [12, 14, 15, 16, 17] }
1433
+ end
1434
+
1435
+ context 'when resultant vector has only one value' do
1436
+ subject { dv.reject_values 1, :a, nil, Float::NAN }
1437
+
1438
+ it { is_expected.to be_a DaruLite::Vector }
1439
+ its(:to_a) { is_expected.to eq [3] }
1440
+ its(:'index.to_a') { is_expected.to eq [13] }
1441
+ end
1442
+
1443
+ context 'when resultant vector has no value' do
1444
+ subject { dv.reject_values 1, 3, :a, nil, Float::NAN, 5 }
1445
+
1446
+ it { is_expected.to be_a DaruLite::Vector }
1447
+ its(:to_a) { is_expected.to eq [] }
1448
+ its(:'index.to_a') { is_expected.to eq [] }
1449
+ end
1450
+ end
1451
+
1452
+ context '#include_values?' do
1453
+ context 'only nils' do
1454
+ context 'true' do
1455
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, :a, 'Unknown', nil],
1456
+ type: :category }
1457
+ it { expect(dv.include_values? nil).to eq true }
1458
+ end
1459
+
1460
+ context 'false' do
1461
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, :a, 'Unknown'],
1462
+ type: :category }
1463
+ it { expect(dv.include_values? nil).to eq false }
1464
+ end
1465
+ end
1466
+
1467
+ context 'only Float::NAN' do
1468
+ context 'true' do
1469
+ let(:dv) { DaruLite::Vector.new [1, nil, 2, 3, Float::NAN],
1470
+ type: :category}
1471
+ it { expect(dv.include_values? Float::NAN).to eq true }
1472
+ end
1473
+
1474
+ context 'false' do
1475
+ let(:dv) { DaruLite::Vector.new [1, nil, 2, 3],
1476
+ type: :category }
1477
+ it { expect(dv.include_values? Float::NAN).to eq false }
1478
+ end
1479
+ end
1480
+
1481
+ context 'both nil and Float::NAN' do
1482
+ context 'true with only nil' do
1483
+ let(:dv) { DaruLite::Vector.new [1, Float::NAN, 2, 3],
1484
+ type: :category}
1485
+ it { expect(dv.include_values? nil, Float::NAN).to eq true }
1486
+ end
1487
+
1488
+ context 'true with only Float::NAN' do
1489
+ let(:dv) { DaruLite::Vector.new [1, nil, 2, 3],
1490
+ type: :category}
1491
+ it { expect(dv.include_values? nil, Float::NAN).to eq true }
1492
+ end
1493
+
1494
+ context 'false' do
1495
+ let(:dv) { DaruLite::Vector.new [1, 2, 3],
1496
+ type: :category}
1497
+ it { expect(dv.include_values? nil, Float::NAN).to eq false }
1498
+ end
1499
+ end
1500
+
1501
+ context 'any other value' do
1502
+ context 'true' do
1503
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, 4, nil],
1504
+ type: :category }
1505
+ it { expect(dv.include_values? 1, 2, 3, 5).to eq true }
1506
+ end
1507
+
1508
+ context 'false' do
1509
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, 4, nil],
1510
+ type: :category }
1511
+ it { expect(dv.include_values? 5, 6).to eq false }
1512
+ end
1513
+ end
1514
+ end
1515
+
1516
+ context '#count_values' do
1517
+ let(:dv) { DaruLite::Vector.new [1, 2, 3, 1, 2, nil, nil], type: :category }
1518
+ it { expect(dv.count_values 1, 2).to eq 4 }
1519
+ it { expect(dv.count_values nil).to eq 2 }
1520
+ it { expect(dv.count_values 3, Float::NAN).to eq 1 }
1521
+ it { expect(dv.count_values 4).to eq 0 }
1522
+ end
1523
+
1524
+ context '#indexes' do
1525
+ context DaruLite::Index do
1526
+ let(:dv) { DaruLite::Vector.new [1, 2, 1, 2, 3, nil, nil, Float::NAN],
1527
+ index: 11..18, type: :category }
1528
+
1529
+ subject { dv.indexes 1, 2, nil, Float::NAN }
1530
+ it { is_expected.to be_a Array }
1531
+ it { is_expected.to eq [11, 12, 13, 14, 16, 17, 18] }
1532
+ end
1533
+
1534
+ context DaruLite::MultiIndex do
1535
+ let(:mi) do
1536
+ DaruLite::MultiIndex.from_tuples([
1537
+ ['M', 2000],
1538
+ ['M', 2001],
1539
+ ['M', 2002],
1540
+ ['M', 2003],
1541
+ ['F', 2000],
1542
+ ['F', 2001],
1543
+ ['F', 2002],
1544
+ ['F', 2003]
1545
+ ])
1546
+ end
1547
+ let(:dv) { DaruLite::Vector.new [1, 2, 1, 2, 3, nil, nil, Float::NAN],
1548
+ index: mi, type: :category }
1549
+
1550
+ subject { dv.indexes 1, 2, Float::NAN }
1551
+ it { is_expected.to be_a Array }
1552
+ it { is_expected.to eq(
1553
+ [
1554
+ ['M', 2000],
1555
+ ['M', 2001],
1556
+ ['M', 2002],
1557
+ ['M', 2003],
1558
+ ['F', 2003]
1559
+ ]) }
1560
+ end
1561
+ end
1562
+
1563
+ context '#replace_values' do
1564
+ subject do
1565
+ DaruLite::Vector.new(
1566
+ [1, 2, 1, 4, nil, Float::NAN, nil, Float::NAN],
1567
+ index: 11..18, type: :category
1568
+ )
1569
+ end
1570
+
1571
+ context 'replace nils and NaNs' do
1572
+ before { subject.replace_values [nil, Float::NAN], 10 }
1573
+ its(:type) { is_expected.to eq :category }
1574
+ its(:to_a) { is_expected.to eq [1, 2, 1, 4, 10, 10, 10, 10] }
1575
+ end
1576
+
1577
+ context 'replace arbitrary values' do
1578
+ before { subject.replace_values [1, 2], 10 }
1579
+ its(:type) { is_expected.to eq :category }
1580
+ its(:to_a) { is_expected.to eq(
1581
+ [10, 10, 10, 4, nil, Float::NAN, nil, Float::NAN]) }
1582
+ end
1583
+
1584
+ context 'works for single value' do
1585
+ before { subject.replace_values nil, 10 }
1586
+ its(:type) { is_expected.to eq :category }
1587
+ its(:to_a) { is_expected.to eq(
1588
+ [1, 2, 1, 4, 10, Float::NAN, 10, Float::NAN]) }
1589
+ end
1590
+ end
1591
+ end
1592
+
1593
+ describe DaruLite::DataFrame, "categorical" do
1594
+ context "#to_category" do
1595
+ let(:df) do
1596
+ DaruLite::DataFrame.new({
1597
+ a: [1, 2, 3, 4, 5],
1598
+ b: ['first', 'second', 'first', 'second', 'third'],
1599
+ c: ['a', 'b', 'a', 'b', nil]
1600
+ })
1601
+ end
1602
+ before { df.to_category :b, :c }
1603
+ subject { df }
1604
+
1605
+ it { is_expected.to be_a DaruLite::DataFrame }
1606
+ its(:'b.type') { is_expected.to eq :category }
1607
+ its(:'c.type') { is_expected.to eq :category }
1608
+ its(:'a.count') { is_expected.to eq 5 }
1609
+ its(:'c.count') { is_expected.to eq 5 }
1610
+ it { expect(df.c.count('a')).to eq 2 }
1611
+ it { expect(df.c.count(nil)).to eq 1 }
1612
+ end
1613
+
1614
+ context "#interact_code" do
1615
+ context "two vectors" do
1616
+ let(:df) do
1617
+ DaruLite::DataFrame.new({
1618
+ a: [1, 2, 3, 4, 5],
1619
+ b: ['first', 'second', 'first', 'second', 'third'],
1620
+ c: ['a', 'b', 'a', 'b', 'c']
1621
+ })
1622
+ end
1623
+ before do
1624
+ df.to_category :b, :c
1625
+ df[:b].categories = ['first', 'second', 'third']
1626
+ df[:c].categories = ['a', 'b', 'c']
1627
+ end
1628
+
1629
+ context "both full" do
1630
+ subject { df.interact_code [:b, :c], [true, true] }
1631
+
1632
+ it { is_expected.to be_a DaruLite::DataFrame }
1633
+ its(:shape) { is_expected.to eq [5, 9] }
1634
+ it { expect(subject['b_first:c_a'].to_a).to eq [1, 0, 1, 0, 0] }
1635
+ it { expect(subject['b_first:c_b'].to_a).to eq [0, 0, 0, 0, 0] }
1636
+ it { expect(subject['b_first:c_c'].to_a).to eq [0, 0, 0, 0, 0] }
1637
+ it { expect(subject['b_second:c_a'].to_a).to eq [0, 0, 0, 0, 0] }
1638
+ it { expect(subject['b_second:c_b'].to_a).to eq [0, 1, 0, 1, 0] }
1639
+ it { expect(subject['b_second:c_c'].to_a).to eq [0, 0, 0, 0, 0] }
1640
+ it { expect(subject['b_third:c_a'].to_a).to eq [0, 0, 0, 0, 0] }
1641
+ it { expect(subject['b_third:c_b'].to_a).to eq [0, 0, 0, 0, 0] }
1642
+ it { expect(subject['b_third:c_c'].to_a).to eq [0, 0, 0, 0, 1] }
1643
+ end
1644
+
1645
+ context "one full" do
1646
+ subject { df.interact_code [:b, :c], [true, false] }
1647
+
1648
+ it { is_expected.to be_a DaruLite::DataFrame }
1649
+ its(:shape) { is_expected.to eq [5, 6] }
1650
+ it { expect(subject['b_first:c_b'].to_a).to eq [0, 0, 0, 0, 0] }
1651
+ it { expect(subject['b_first:c_c'].to_a).to eq [0, 0, 0, 0, 0] }
1652
+ it { expect(subject['b_second:c_b'].to_a).to eq [0, 1, 0, 1, 0] }
1653
+ it { expect(subject['b_second:c_c'].to_a).to eq [0, 0, 0, 0, 0] }
1654
+ it { expect(subject['b_third:c_b'].to_a).to eq [0, 0, 0, 0, 0] }
1655
+ it { expect(subject['b_third:c_c'].to_a).to eq [0, 0, 0, 0, 1] }
1656
+ end
1657
+
1658
+ context "none full" do
1659
+ subject { df.interact_code [:b, :c], [false, false] }
1660
+
1661
+ it { is_expected.to be_a DaruLite::DataFrame }
1662
+ its(:shape) { is_expected.to eq [5, 4] }
1663
+ it { expect(subject['b_second:c_b'].to_a).to eq [0, 1, 0, 1, 0] }
1664
+ it { expect(subject['b_second:c_c'].to_a).to eq [0, 0, 0, 0, 0] }
1665
+ it { expect(subject['b_third:c_b'].to_a).to eq [0, 0, 0, 0, 0] }
1666
+ it { expect(subject['b_third:c_c'].to_a).to eq [0, 0, 0, 0, 1] }
1667
+ end
1668
+ end
1669
+
1670
+ context "more than two vectors" do
1671
+ let(:df) do
1672
+ DaruLite::DataFrame.new({
1673
+ a: [1, 1, 2],
1674
+ b: [2, 2, 3],
1675
+ c: [3, 3, 4]
1676
+ })
1677
+ end
1678
+ before { df.to_category :a, :b, :c }
1679
+ subject { df.interact_code [:a, :b, :c], [false, false, true] }
1680
+
1681
+ it { is_expected.to be_a DaruLite::DataFrame }
1682
+ its(:shape) { is_expected.to eq [3, 2] }
1683
+ it { expect(subject['a_2:b_3:c_3'].to_a).to eq [0, 0, 0] }
1684
+ it { expect(subject['a_2:b_3:c_4'].to_a).to eq [0, 0, 1] }
1685
+ end
1686
+ end
1687
+
1688
+ context "#sort!" do
1689
+ let(:df) do
1690
+ DaruLite::DataFrame.new({
1691
+ a: [1, 2, 1, 4, 5],
1692
+ b: ['II', 'I', 'III', 'II', 'I'],
1693
+ })
1694
+ end
1695
+ before do
1696
+ df[:b] = df[:b].to_category ordereed: true, categories: ['I', 'II', 'III']
1697
+ df.sort! [:a, :b]
1698
+ end
1699
+ subject { df }
1700
+
1701
+ its(:shape) { is_expected.to eq [5, 2] }
1702
+ its(:'a.to_a') { is_expected.to eq [1, 1, 2, 4, 5] }
1703
+ its(:'b.to_a') { is_expected.to eq ['II', 'III', 'I', 'II', 'I'] }
1704
+ end
1705
+
1706
+ context "#split_by_category" do
1707
+ let(:df) do
1708
+ DaruLite::DataFrame.new({
1709
+ a: [1, 2, 3, 4, 5, 6, 7],
1710
+ b: [3, 2, 2, 35, 3, 2, 5],
1711
+ cat: [:I, :II, :I, :III, :I, :III, :II]
1712
+ })
1713
+ end
1714
+ let(:df1) do
1715
+ DaruLite::DataFrame.new({
1716
+ a: [1, 3, 5],
1717
+ b: [3, 2, 3]
1718
+ }, name: :I, index: [0, 2, 4])
1719
+ end
1720
+ let(:df2) do
1721
+ DaruLite::DataFrame.new({
1722
+ a: [2, 7],
1723
+ b: [2, 5]
1724
+ }, name: :II, index: [1, 6])
1725
+ end
1726
+ let(:df3) do
1727
+ DaruLite::DataFrame.new({
1728
+ a: [4, 6],
1729
+ b: [35, 2]
1730
+ }, name: :III, index: [3, 5])
1731
+ end
1732
+ before { df.to_category :cat }
1733
+ subject { df.split_by_category :cat }
1734
+
1735
+ it { is_expected.to be_a Array }
1736
+ its(:size) { is_expected.to eq 3 }
1737
+ its(:first) { is_expected.to eq df1 }
1738
+ it { expect(subject[1]).to eq df2 }
1739
+ its(:last) { is_expected.to eq df3 }
1740
+ end
1741
+ end