daru_lite 0.1.2 → 0.2.0

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/ci.yml +2 -2
  4. data/.rubocop.yml +2 -2
  5. data/benchmarks/db_loading.rb +0 -1
  6. data/daru_lite.gemspec +10 -12
  7. data/daru_lite_test-shm +0 -0
  8. data/daru_lite_test-wal +0 -0
  9. data/lib/daru_lite/accessors/array_wrapper.rb +4 -4
  10. data/lib/daru_lite/core/merge.rb +8 -8
  11. data/lib/daru_lite/data_frame/calculatable.rb +2 -2
  12. data/lib/daru_lite/data_frame/filterable.rb +4 -4
  13. data/lib/daru_lite/data_frame/i_o_able.rb +17 -14
  14. data/lib/daru_lite/data_frame/iterable.rb +11 -11
  15. data/lib/daru_lite/data_frame/queryable.rb +5 -5
  16. data/lib/daru_lite/dataframe.rb +16 -14
  17. data/lib/daru_lite/date_time/index.rb +10 -10
  18. data/lib/daru_lite/extensions/which_dsl.rb +2 -2
  19. data/lib/daru_lite/index/index.rb +4 -4
  20. data/lib/daru_lite/index/multi_index.rb +13 -4
  21. data/lib/daru_lite/io/io.rb +10 -9
  22. data/lib/daru_lite/io/sql_data_source.rb +7 -24
  23. data/lib/daru_lite/maths/statistics/dataframe.rb +2 -2
  24. data/lib/daru_lite/maths/statistics/vector.rb +16 -16
  25. data/lib/daru_lite/vector/aggregatable.rb +2 -2
  26. data/lib/daru_lite/vector/filterable.rb +2 -2
  27. data/lib/daru_lite/vector/queryable.rb +4 -4
  28. data/lib/daru_lite/vector/sortable.rb +4 -4
  29. data/lib/daru_lite/vector.rb +4 -6
  30. data/lib/daru_lite/version.rb +1 -1
  31. data/spec/data_frame/filterable_example.rb +174 -15
  32. data/spec/index/categorical_index_spec.rb +27 -8
  33. data/spec/index/index_spec.rb +16 -3
  34. data/spec/index/multi_index_spec.rb +85 -76
  35. data/spec/io/io_spec.rb +0 -16
  36. data/spec/io/sql_data_source_spec.rb +0 -8
  37. data/spec/spec_helper.rb +1 -1
  38. data/spec/support/database_helper.rb +0 -1
  39. metadata +30 -65
@@ -16,24 +16,6 @@ module DaruLite
16
16
  end
17
17
  end
18
18
 
19
- # Private adapter class for DBI::DatabaseHandle
20
- # @private
21
- class DbiAdapter < Adapter
22
- private
23
-
24
- def column_names
25
- result.column_names
26
- end
27
-
28
- def rows
29
- result.to_a.map(&:to_a)
30
- end
31
-
32
- def result
33
- @result ||= @conn.execute(@query)
34
- end
35
- end
36
-
37
19
  # Private adapter class for connections of ActiveRecord
38
20
  # @private
39
21
  class ActiveRecordConnectionAdapter < Adapter
@@ -52,7 +34,6 @@ module DaruLite
52
34
  end
53
35
  end
54
36
 
55
- private_constant :DbiAdapter
56
37
  private_constant :ActiveRecordConnectionAdapter
57
38
 
58
39
  def self.make_dataframe(db, query)
@@ -76,8 +57,6 @@ module DaruLite
76
57
  db = attempt_sqlite3_connection(db) if db.is_a?(String) && Pathname(db).exist?
77
58
 
78
59
  case db
79
- when DBI::DatabaseHandle
80
- DbiAdapter.new(db, query)
81
60
  when ActiveRecord::ConnectionAdapters::AbstractAdapter
82
61
  ActiveRecordConnectionAdapter.new(db, query)
83
62
  else
@@ -86,11 +65,15 @@ module DaruLite
86
65
  end
87
66
 
88
67
  def attempt_sqlite3_connection(db)
89
- DBI.connect("DBI:SQLite3:#{db}")
90
- rescue SQLite3::NotADatabaseException
68
+ ActiveRecord::Base.establish_connection(
69
+ adapter: 'sqlite3',
70
+ database: db
71
+ )
72
+ ActiveRecord::Base.connection.tap(&:verify!)
73
+ rescue ActiveRecord::StatementInvalid
91
74
  raise ArgumentError, "Expected #{db} to point to a SQLite3 database"
92
75
  rescue NameError
93
- raise NameError, "In order to establish a connection to #{db}, please require 'dbi'"
76
+ raise NameError, "In order to establish a connection to #{db}, please require 'ActiveRecord'"
94
77
  end
95
78
  end
96
79
  end
@@ -165,10 +165,10 @@ module DaruLite
165
165
 
166
166
  private
167
167
 
168
- def apply_method_to_numerics(method, *args)
168
+ def apply_method_to_numerics(method, *)
169
169
  numerics = @vectors.to_a.map { |n| [n, @data[@vectors[n]]] }
170
170
  .select { |_n, v| v.numeric? }
171
- computed = numerics.map { |_n, v| v.send(method, *args) }
171
+ computed = numerics.map { |_n, v| v.send(method, *) }
172
172
 
173
173
  DaruLite::DataFrame.new(computed, index: @index, order: numerics.map(&:first), clone: false)
174
174
  end
@@ -89,8 +89,8 @@ module DaruLite
89
89
  #
90
90
  # dv.max(2) { |a,b| a.size <=> b.size }
91
91
  # #=> ["Jon Starkgaryen","Daenerys"]
92
- def max(size = nil, &block)
93
- reject_values(*DaruLite::MISSING_VALUES).to_a.max(size, &block)
92
+ def max(size = nil, &)
93
+ reject_values(*DaruLite::MISSING_VALUES).to_a.max(size, &)
94
94
  end
95
95
 
96
96
  # Returns the maximum value(s) present in the vector, with a compulsory object block.
@@ -134,8 +134,8 @@ module DaruLite
134
134
  #
135
135
  # dv.min(2) { |a,b| a.size <=> b.size }
136
136
  # #=> ["Tyrion","Daenerys"]
137
- def min(size = nil, &block)
138
- reject_values(*DaruLite::MISSING_VALUES).to_a.min(size, &block)
137
+ def min(size = nil, &)
138
+ reject_values(*DaruLite::MISSING_VALUES).to_a.min(size, &)
139
139
  end
140
140
 
141
141
  # Returns the minimum value(s) present in the vector, with a compulsory object block.
@@ -179,9 +179,9 @@ module DaruLite
179
179
  #
180
180
  # dv.max(2) { |a,b| a.size <=> b.size }
181
181
  # #=> ["Jon Starkgaryen","Daenerys"]
182
- def max(size = nil, &block)
182
+ def max(size = nil, &)
183
183
  range = size.nil? ? 0 : (0..size - 1)
184
- reject_values(*DaruLite::MISSING_VALUES).to_a.sort(&block).reverse[range]
184
+ reject_values(*DaruLite::MISSING_VALUES).to_a.sort(&).reverse[range]
185
185
  end
186
186
 
187
187
  # Returns the maximum value(s) present in the vector, with a compulsory object block.
@@ -225,9 +225,9 @@ module DaruLite
225
225
  #
226
226
  # dv.min(2) { |a,b| a.size <=> b.size }
227
227
  # #=> ["Tyrion","Daenerys"]
228
- def min(size = nil, &block)
228
+ def min(size = nil, &)
229
229
  range = size.nil? ? 0 : (0..size - 1)
230
- reject_values(*DaruLite::MISSING_VALUES).to_a.sort(&block)[range]
230
+ reject_values(*DaruLite::MISSING_VALUES).to_a.sort(&)[range]
231
231
  end
232
232
 
233
233
  # Returns the minimum value(s) present in the vector, with a compulsory object block.
@@ -276,8 +276,8 @@ module DaruLite
276
276
  #
277
277
  # dv.index_of_max(2) { |a,b| a.size <=> b.size }
278
278
  # #=> [:j, :d]
279
- def index_of_max(size = nil, &block)
280
- vals = max(size, &block)
279
+ def index_of_max(size = nil, &)
280
+ vals = max(size, &)
281
281
  dv = reject_values(*DaruLite::MISSING_VALUES)
282
282
  vals.is_a?(Array) ? (vals.map { |x| dv.index_of(x) }) : dv.index_of(vals)
283
283
  end
@@ -299,8 +299,8 @@ module DaruLite
299
299
  #
300
300
  # dv.index_of_max_by(2) { |i| i.size }
301
301
  # #=> [:j, :d]
302
- def index_of_max_by(size = nil, &block)
303
- vals = max_by(size, &block)
302
+ def index_of_max_by(size = nil, &)
303
+ vals = max_by(size, &)
304
304
  dv = reject_values(*DaruLite::MISSING_VALUES)
305
305
  vals.is_a?(Array) ? (vals.map { |x| dv.index_of(x) }) : dv.index_of(vals)
306
306
  end
@@ -325,8 +325,8 @@ module DaruLite
325
325
  #
326
326
  # dv.index_of_min(2) { |a,b| a.size <=> b.size }
327
327
  # #=> [:t, :d]
328
- def index_of_min(size = nil, &block)
329
- vals = min(size, &block)
328
+ def index_of_min(size = nil, &)
329
+ vals = min(size, &)
330
330
  dv = reject_values(*DaruLite::MISSING_VALUES)
331
331
  vals.is_a?(Array) ? (vals.map { |x| dv.index_of(x) }) : dv.index_of(vals)
332
332
  end
@@ -348,8 +348,8 @@ module DaruLite
348
348
  #
349
349
  # dv.index_of_min(2) { |i| i.size }
350
350
  # #=> [:t, :d]
351
- def index_of_min_by(size = nil, &block)
352
- vals = min_by(size, &block)
351
+ def index_of_min_by(size = nil, &)
352
+ vals = min_by(size, &)
353
353
  dv = reject_values(*DaruLite::MISSING_VALUES)
354
354
  vals.is_a?(Array) ? (vals.map { |x| dv.index_of(x) }) : dv.index_of(vals)
355
355
  end
@@ -1,8 +1,8 @@
1
1
  module DaruLite
2
2
  class Vector
3
3
  module Aggregatable
4
- def group_by(*args)
5
- to_df.group_by(*args)
4
+ def group_by(*)
5
+ to_df.group_by(*)
6
6
  end
7
7
  end
8
8
  end
@@ -58,8 +58,8 @@ module DaruLite
58
58
  # # 0 3 days
59
59
  # # 1 35 days
60
60
  # # 2 14 days
61
- def apply_where(bool_array, &block)
62
- DaruLite::Core::Query.vector_apply_where self, bool_array, &block
61
+ def apply_where(bool_array, &)
62
+ DaruLite::Core::Query.vector_apply_where(self, bool_array, &)
63
63
  end
64
64
 
65
65
  # Keep only unique elements of the vector alongwith their indexes.
@@ -17,12 +17,12 @@ module DaruLite
17
17
  values.any? { |v| include_with_nan? @data, v }
18
18
  end
19
19
 
20
- def any?(&block)
21
- @data.data.any?(&block)
20
+ def any?(&)
21
+ @data.data.any?(&)
22
22
  end
23
23
 
24
- def all?(&block)
25
- @data.data.all?(&block)
24
+ def all?(&)
25
+ @data.data.all?(&)
26
26
  end
27
27
 
28
28
  # Returns an array of either none or integer values, indicating the
@@ -17,10 +17,10 @@ module DaruLite
17
17
  # v = DaruLite::Vector.new ["My first guitar", "jazz", "guitar"]
18
18
  # # Say you want to sort these strings by length.
19
19
  # v.sort(ascending: false) { |a,b| a.length <=> b.length }
20
- def sort(opts = {}, &block)
20
+ def sort(opts = {}, &)
21
21
  opts = { ascending: true }.merge(opts)
22
22
 
23
- vector_index = resort_index(@data.each_with_index, opts, &block)
23
+ vector_index = resort_index(@data.each_with_index, opts, &)
24
24
  vector, index = vector_index.transpose
25
25
 
26
26
  index = @index.reorder index
@@ -68,8 +68,8 @@ module DaruLite
68
68
  # Just sort the data and get an Array in return using Enumerable#sort.
69
69
  # Non-destructive.
70
70
  # :nocov:
71
- def sorted_data(&block)
72
- @data.to_a.sort(&block)
71
+ def sorted_data(&)
72
+ @data.to_a.sort(&)
73
73
  end
74
74
  # :nocov:
75
75
 
@@ -413,7 +413,7 @@ module DaruLite
413
413
 
414
414
  "#<#{self.class}(#{size})#{':category' if category?}>\n" +
415
415
  Formatters::Table.format(
416
- to_a.lazy.map { |v| [v] },
416
+ to_a.lazy.zip,
417
417
  headers: @name && [@name],
418
418
  row_headers: row_headers,
419
419
  threshold: threshold,
@@ -508,7 +508,7 @@ module DaruLite
508
508
  DaruLite::DataFrame.new ps
509
509
  end
510
510
 
511
- DATE_REGEXP = /^(\d{2}-\d{2}-\d{4}|\d{4}-\d{2}-\d{2})$/.freeze
511
+ DATE_REGEXP = /^(\d{2}-\d{2}-\d{4}|\d{4}-\d{2}-\d{2})$/
512
512
 
513
513
  # Returns the database type for the vector, according to its content
514
514
  def db_type
@@ -563,10 +563,8 @@ module DaruLite
563
563
  dv
564
564
  end
565
565
 
566
- def method_missing(name, *args, &block)
567
- # FIXME: it is shamefully fragile. Should be either made stronger
568
- # (string/symbol dychotomy, informative errors) or removed totally. - zverok
569
- if name =~ /(.+)=/
566
+ def method_missing(name, *args, &)
567
+ if name =~ /^([^=]+)=/
570
568
  self[Regexp.last_match(1).to_sym] = args[0]
571
569
  elsif has_index?(name)
572
570
  self[name]
@@ -1,3 +1,3 @@
1
1
  module DaruLite
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -128,8 +128,6 @@ shared_examples_for 'a filterable DataFrame' do
128
128
  end
129
129
 
130
130
  describe "#keep_row_if" do
131
- subject { df.keep_row_if { |row| row[:a] % 10 == 0 } }
132
-
133
131
  let(:index) { [:one, :two, :three, :four, :five] }
134
132
  let(:order) { [:a, :b, :c] }
135
133
  let(:df) do
@@ -143,33 +141,194 @@ shared_examples_for 'a filterable DataFrame' do
143
141
  )
144
142
  end
145
143
 
146
- context DaruLite::Index do
144
+ shared_examples_for '#keep_row_if' do
145
+ before { subject }
146
+
147
147
  it "keeps row if block evaluates to true" do
148
- subject
149
- expect(df).to eq(
148
+ expect(df).to eq(expected_df)
149
+ end
150
+
151
+ it 'returns correct index' do
152
+ expect(df.index).to eq(expected_index)
153
+ end
154
+
155
+ it "all vectors have the same index" do
156
+ expect(df.map(&:index)).to all(eq(expected_index))
157
+ end
158
+ end
159
+
160
+ context 'a single row is removed' do
161
+ context DaruLite::Index do
162
+ subject { df.keep_row_if { |row| row.name != :four } }
163
+
164
+ let(:expected_index) { DaruLite::Index.new([:one, :two, :three, :five]) }
165
+ let(:expected_df) do
150
166
  DaruLite::DataFrame.new(
151
- { b: [10, 12, 20], a: [50, 30, 30], c: [10, 20, 30] },
167
+ { b: [10, 12, 20, 30], a: [50, 30, 30, 5], c: [10, 20, 30, 50] },
152
168
  order:,
153
- index: index[..2]
169
+ index: expected_index
154
170
  )
155
- )
171
+ end
172
+
173
+ it_behaves_like '#keep_row_if'
174
+ end
175
+
176
+ context DaruLite::CategoricalIndex do
177
+ subject { df.keep_row_if { |row| row.name != :a } }
178
+
179
+ let (:index) { DaruLite::CategoricalIndex.new([:a, 1, 1, :a, :c]) }
180
+ let(:expected_index) { DaruLite::CategoricalIndex.new([1, 1, :c]) }
181
+ let(:expected_df) do
182
+ DaruLite::DataFrame.new(
183
+ {
184
+ b: [12, 20, 30],
185
+ a: [30, 30, 5],
186
+ c: [20, 30, 50]
187
+ },
188
+ order:,
189
+ index: expected_index
190
+ )
191
+ end
192
+
193
+ it_behaves_like '#keep_row_if'
194
+ end
195
+
196
+ context DaruLite::MultiIndex do
197
+ subject { df.keep_row_if { |row| !row.name.include?('two') } }
198
+
199
+ let(:index) do
200
+ DaruLite::MultiIndex.from_tuples([[:a, :one], [:a, :two], [:b, :one], [:b, :two], [:c, :one]])
201
+ end
202
+ let(:expected_index) do
203
+ DaruLite::MultiIndex.from_tuples([[:a, :one], [:b, :one], [:c, :one]])
204
+ end
205
+ let(:expected_df) do
206
+ DaruLite::DataFrame.new(
207
+ {
208
+ b: [10, 20, 30],
209
+ a: [50, 30, 5],
210
+ c: [10, 30, 50]
211
+ },
212
+ order:,
213
+ index: expected_index
214
+ )
215
+ end
216
+
217
+ it_behaves_like '#keep_row_if'
156
218
  end
157
219
  end
158
220
 
159
- context DaruLite::CategoricalIndex do
160
- let (:index) { DaruLite::CategoricalIndex.new([:a, 1, 1, :a, :c]) }
221
+ context 'several rows are removed' do
222
+ subject { df.keep_row_if { |row| row[:a] % 10 == 0 } }
161
223
 
162
- it "keeps row if block evaluates to true" do
163
- subject
164
- expect(df).to eq(
224
+ context DaruLite::Index do
225
+ let(:expected_index) { DaruLite::Index.new([:one, :two, :three]) }
226
+ let(:expected_df) do
227
+ DaruLite::DataFrame.new(
228
+ { b: [10, 12, 20], a: [50, 30, 30], c: [10, 20, 30] },
229
+ order:,
230
+ index: expected_index
231
+ )
232
+ end
233
+
234
+ it_behaves_like '#keep_row_if'
235
+ end
236
+
237
+ context DaruLite::CategoricalIndex do
238
+ let (:index) { DaruLite::CategoricalIndex.new([:a, 1, 1, :a, :c]) }
239
+ let(:expected_index) { DaruLite::CategoricalIndex.new([:a, 1, 1]) }
240
+ let(:expected_df) do
165
241
  DaruLite::DataFrame.new(
166
242
  { b: [10, 12, 20], a: [50, 30, 30], c: [10, 20, 30] },
167
243
  order:,
168
- index: DaruLite::CategoricalIndex.new([:a, 1, 1])
244
+ index: expected_index
169
245
  )
170
- )
246
+ end
247
+
248
+ it_behaves_like '#keep_row_if'
249
+ end
250
+
251
+ context DaruLite::MultiIndex do
252
+ let(:index) { DaruLite::MultiIndex.from_tuples([[:a, :one], [:a, :two], [:b, :one], [:b, :two], [:c, :one]]) }
253
+ let(:expected_index) do
254
+ DaruLite::MultiIndex.from_tuples([[:a, :one], [:a, :two], [:b, :one]])
255
+ end
256
+ let(:expected_df) do
257
+ DaruLite::DataFrame.new(
258
+ { b: [10, 12, 20], a: [50, 30, 30], c: [10, 20, 30] },
259
+ order:,
260
+ index: expected_index
261
+ )
262
+ end
263
+
264
+ it_behaves_like '#keep_row_if'
171
265
  end
172
266
  end
267
+
268
+ # context DaruLite::MultiIndex do
269
+ # subject { df.keep_row_if { |row| row.name != 'No answer' } }
270
+
271
+ # let(:df) do
272
+ # order = DaruLite::MultiIndex.from_tuples(
273
+ # [
274
+ # [:a, :total],
275
+ # [:a, "Male"],
276
+ # [:a, "Female"],
277
+ # [:a, "Prefer not to answer"],
278
+ # [:a, "No answer"],
279
+ # [:b, :total],
280
+ # [:b, "Male"],
281
+ # [:b, "Female"],
282
+ # [:b, "Prefer not to answer"],
283
+ # [:b, "No answer"],
284
+ # [:c, :total],
285
+ # [:c, "Male"],
286
+ # [:c, "Female"],
287
+ # [:c, "Prefer not to answer"],
288
+ # [:c, "No answer"]
289
+ # ]
290
+ # )
291
+ # index = [
292
+ # :base,
293
+ # "Single Malt Whisky",
294
+ # "Blended/ Other Whisky",
295
+ # "Vodka",
296
+ # "Cognac",
297
+ # "Brandy",
298
+ # "Rum",
299
+ # "Gin",
300
+ # "Tequila",
301
+ # "No answer",
302
+ # "NET"
303
+ # ]
304
+ # DaruLite::DataFrame.new(
305
+ # [
306
+ # [0.0, nil, nil, nil, nil, nil, nil, nil, nil],
307
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
308
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
309
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
310
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
311
+ # [Float::NAN, nil, nil, nil, nil, nil, nil, nil, nil],
312
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
313
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
314
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
315
+ # [nil, nil, nil, nil, nil, nil, nil, nil, nil],
316
+ # [0, nil, nil, nil, nil, nil, nil, nil, nil],
317
+ # [0, nil, nil, nil, nil, nil, nil, nil, nil],
318
+ # [0, nil, nil, nil, nil, nil, nil, nil, nil],
319
+ # [0, nil, nil, nil, nil, nil, nil, nil, nil],
320
+ # [0, nil, nil, nil, nil, nil, nil, nil, nil],
321
+ # ],
322
+ # index:,
323
+ # order:
324
+ # )
325
+ # end
326
+
327
+ # it "all vectors have the same index" do
328
+ # subject
329
+ # expect(df.map(&:index)).to all(eq(df.index))
330
+ # end
331
+ # end
173
332
  end
174
333
 
175
334
  describe "#keep_vector_if" do
@@ -1,36 +1,47 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe DaruLite::CategoricalIndex do
4
+ let(:index) { described_class.new(keys) }
5
+ let(:keys) { [:a, :b, :a, :a, :c] }
6
+
7
+ describe "#to_a" do
8
+ subject { index.to_a }
9
+
10
+ it { is_expected.to eq(keys) }
11
+
12
+ it 'the returns array is not a variable of the index' do
13
+ expect { subject << 'four' }.not_to change { index.to_a }
14
+ end
15
+ end
16
+
4
17
  context "#pos" do
5
18
  context "when the category is non-numeric" do
6
- let(:idx) { described_class.new [:a, :b, :a, :a, :c] }
7
-
8
19
  context "single category" do
9
- subject { idx.pos :a }
20
+ subject { index.pos :a }
10
21
 
11
22
  it { is_expected.to eq [0, 2, 3] }
12
23
  end
13
24
 
14
25
  context "multiple categories" do
15
- subject { idx.pos :a, :c }
26
+ subject { index.pos :a, :c }
16
27
 
17
28
  it { is_expected.to eq [0, 2, 3, 4] }
18
29
  end
19
30
 
20
31
  context "invalid category" do
21
- it { expect { idx.pos :e }.to raise_error IndexError }
32
+ it { expect { index.pos :e }.to raise_error IndexError }
22
33
  end
23
34
 
24
35
  context "positional index" do
25
- it { expect(idx.pos 0).to eq 0 }
36
+ it { expect(index.pos 0).to eq 0 }
26
37
  end
27
38
 
28
39
  context "invalid positional index" do
29
- it { expect { idx.pos 5 }.to raise_error IndexError }
40
+ it { expect { index.pos 5 }.to raise_error IndexError }
30
41
  end
31
42
 
32
43
  context "multiple positional indexes" do
33
- subject { idx.pos 0, 1, 2 }
44
+ subject { index.pos 0, 1, 2 }
34
45
 
35
46
  it { is_expected.to be_a Array }
36
47
  its(:size) { is_expected.to eq 3 }
@@ -167,4 +178,12 @@ describe DaruLite::CategoricalIndex do
167
178
  it { expect(idx.valid? :a, 1, 5).to eq false }
168
179
  end
169
180
  end
181
+
182
+ describe '#delete_at' do
183
+ subject { index.delete_at(3) }
184
+
185
+ let(:index) { described_class.new([:a, 1, :a, 1, 'c']) }
186
+
187
+ it { is_expected.to eq(described_class.new([:a, 1, :a, 'c'])) }
188
+ end
170
189
  end
@@ -1,6 +1,9 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe DaruLite::Index do
4
+ let(:index) { described_class.new(keys) }
5
+ let(:keys) { ['one', 'two', 'three'] }
6
+
4
7
  context ".new" do
5
8
  it "creates an Index object if Index-like data is supplied" do
6
9
  i = DaruLite::Index.new [:one, 'one', 1, 2, :two]
@@ -147,6 +150,16 @@ describe DaruLite::Index do
147
150
  end
148
151
  end
149
152
 
153
+ describe "#to_a" do
154
+ subject { index.to_a }
155
+
156
+ it { is_expected.to eq(keys) }
157
+
158
+ it 'the returns array is not a variable of the index' do
159
+ expect { subject << 'four' }.not_to change { index.to_a }
160
+ end
161
+ end
162
+
150
163
  context "#&" do
151
164
  before :each do
152
165
  @left = DaruLite::Index.new [:miles, :geddy, :eric]
@@ -390,11 +403,11 @@ describe DaruLite::Index do
390
403
  end
391
404
 
392
405
  describe '#delete_at' do
393
- subject { idx.delete_at(1)}
406
+ subject { index.delete_at(1) }
394
407
 
395
- let(:idx) { DaruLite::Index.new([:a, :b, 1, 2]) }
408
+ let(:index) { described_class.new([:a, :b, 1, 2]) }
396
409
 
397
- it { is_expected.to eq DaruLite::Index.new([:a, 1, 2]) }
410
+ it { is_expected.to eq(described_class.new([:a, 1, 2])) }
398
411
  end
399
412
 
400
413
  context '#to_df' do