Class: DaruLite::MultiIndex
- Inherits:
-
Index
show all
- Defined in:
- lib/daru_lite/index/multi_index.rb
Overview
rubocop:disable Metrics/ClassLength
Instance Attribute Summary collapse
Attributes inherited from Index
#relation_hash
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from Index
__new__, #_dump, _load, coerce, inherited, #is_values, new, #slice, #sort, #subset_slice
Constructor Details
#initialize(opts = {}) ⇒ MultiIndex
names and levels should be of same size. If size of Array ‘name` is less or greater than size of array `levels` then it raises `SizeError`. If user don’t want to put name for particular level then user must put empty string in that index of Array ‘name`. For example there is multi_index of 3 levels and user don’t want to name level 0, then do multi_index.name = [”, ‘level1_name1’, ‘level2_name’]
79
80
81
82
83
84
85
86
87
88
89
90
|
# File 'lib/daru_lite/index/multi_index.rb', line 79
def initialize(opts = {})
labels = opts[:labels]
levels = opts[:levels]
raise ArgumentError, 'Must specify both labels and levels' unless labels && levels
raise ArgumentError, 'Labels and levels should be same size' if labels.size != levels.size
raise ArgumentError, 'Incorrect labels and levels' if incorrect_fields?(labels, levels)
@labels = labels
@levels = levels.map { |e| e.map.with_index.to_h }
self.name = opts[:name] unless opts[:name].nil?
end
|
Instance Attribute Details
Returns the value of attribute labels.
11
12
13
|
# File 'lib/daru_lite/index/multi_index.rb', line 11
def labels
@labels
end
|
Returns the value of attribute name.
11
12
13
|
# File 'lib/daru_lite/index/multi_index.rb', line 11
def name
@name
end
|
Class Method Details
.from_arrays(arrays) ⇒ Object
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/daru_lite/index/multi_index.rb', line 105
def self.from_arrays(arrays)
levels = arrays.map { |e| e.uniq.sort_by(&:to_s) }
labels = arrays.each_with_index.map do |arry, level_index|
level = levels[level_index]
arry.map { |lvl| level.index(lvl) }
end
MultiIndex.new labels: labels, levels: levels
end
|
.from_tuples(tuples) ⇒ Object
116
117
118
|
# File 'lib/daru_lite/index/multi_index.rb', line 116
def self.from_tuples(tuples)
from_arrays tuples.transpose
end
|
.try_from_tuples(tuples) ⇒ Object
120
121
122
|
# File 'lib/daru_lite/index/multi_index.rb', line 120
def self.try_from_tuples(tuples)
from_tuples(tuples) if tuples.respond_to?(:first) && tuples.first.is_a?(Array)
end
|
Instance Method Details
298
299
300
|
# File 'lib/daru_lite/index/multi_index.rb', line 298
def &(other)
MultiIndex.from_tuples(to_a & other.to_a)
end
|
#==(other) ⇒ Object
322
323
324
325
326
|
# File 'lib/daru_lite/index/multi_index.rb', line 322
def ==(other)
self.class == other.class &&
labels == other.labels &&
levels == other.levels
end
|
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
# File 'lib/daru_lite/index/multi_index.rb', line 124
def [](*key)
key.flatten!
if key[0].is_a?(Range)
retrieve_from_range(key[0])
elsif key[0].is_a?(Integer) && key.size == 1
try_retrieve_from_integer(key[0])
else
begin
retrieve_from_tuples key
rescue NoMethodError
raise IndexError, "Specified index #{key.inspect} do not exist"
end
end
end
|
#add(*indexes) ⇒ Object
195
196
197
|
# File 'lib/daru_lite/index/multi_index.rb', line 195
def add(*indexes)
DaruLite::MultiIndex.from_tuples(to_a + [indexes])
end
|
#at(*positions) ⇒ object
Takes positional values and returns subset of the self
capturing the indexes at mentioned positions
185
186
187
188
189
190
191
192
193
|
# File 'lib/daru_lite/index/multi_index.rb', line 185
def at(*positions)
positions = preprocess_positions(*positions)
validate_positions(*positions)
if positions.is_a? Integer
key(positions)
else
DaruLite::MultiIndex.from_tuples(positions.map { |v| key(v) })
end
end
|
#coerce_index ⇒ Object
249
250
251
252
253
254
255
256
257
258
259
260
261
|
# File 'lib/daru_lite/index/multi_index.rb', line 249
def coerce_index
if @levels.size == 1
elements = to_a.flatten
if elements.uniq.length == elements.length
DaruLite::Index.new(elements)
else
DaruLite::CategoricalIndex.new(elements)
end
else
self
end
end
|
Provide a MultiIndex for sub vector produced
350
351
352
353
354
|
# File 'lib/daru_lite/index/multi_index.rb', line 350
def conform(input_indexes)
return self if input_indexes[0].is_a? Range
drop_left_level input_indexes.size
end
|
#drop_left_level(by = 1) ⇒ Object
290
291
292
|
# File 'lib/daru_lite/index/multi_index.rb', line 290
def drop_left_level(by = 1)
MultiIndex.from_arrays to_a.transpose[by..]
end
|
286
287
288
|
# File 'lib/daru_lite/index/multi_index.rb', line 286
def dup
MultiIndex.new levels: levels.dup, labels: labels.dup, name: @name&.dup
end
|
#each(&block) ⇒ Object
3
4
5
|
# File 'lib/daru_lite/index/multi_index.rb', line 3
def each(&block)
to_a.each(&block)
end
|
#empty? ⇒ Boolean
302
303
304
|
# File 'lib/daru_lite/index/multi_index.rb', line 302
def empty?
@labels.flatten.empty? && @levels.all?(&:empty?)
end
|
#include?(tuple) ⇒ Boolean
306
307
308
309
310
311
312
|
# File 'lib/daru_lite/index/multi_index.rb', line 306
def include?(tuple)
return false unless tuple.is_a? Enumerable
@labels[0...tuple.flatten.size]
.transpose
.include?(tuple.flatten.each_with_index.map { |e, i| @levels[i][e] })
end
|
#inspect(threshold = 20) ⇒ Object
336
337
338
339
|
# File 'lib/daru_lite/index/multi_index.rb', line 336
def inspect(threshold = 20)
"#<DaruLite::MultiIndex(#{size}x#{width})>\n" +
Formatters::Table.format([], headers: @name, row_headers: sparse_tuples, threshold: threshold)
end
|
#key(index) ⇒ Object
278
279
280
281
282
283
284
|
# File 'lib/daru_lite/index/multi_index.rb', line 278
def key(index)
raise ArgumentError, "Key #{index} is too large" if index >= @labels[0].size
@labels
.each_with_index
.map { |label, i| @levels[i].keys[label[index]] }
end
|
13
14
15
|
# File 'lib/daru_lite/index/multi_index.rb', line 13
def levels
@levels.map(&:keys)
end
|
#map(&block) ⇒ Object
7
8
9
|
# File 'lib/daru_lite/index/multi_index.rb', line 7
def map(&block)
to_a.map(&block)
end
|
#pos(*indexes) ⇒ Object
Note:
If the arugent is both a valid index and a valid position, it will treated as valid index
Returns positions given indexes or positions
155
156
157
158
159
160
161
162
163
164
165
|
# File 'lib/daru_lite/index/multi_index.rb', line 155
def pos(*indexes)
if indexes.first.is_a? Integer
return indexes.first if indexes.size == 1
return indexes
end
res = self[indexes]
return res if res.is_a? Integer
res.map { |i| self[i] }
end
|
#remove_layer(layer_index) ⇒ Object
241
242
243
244
245
246
247
|
# File 'lib/daru_lite/index/multi_index.rb', line 241
def remove_layer(layer_index)
@levels.delete_at(layer_index)
@labels.delete_at(layer_index)
@name&.delete_at(layer_index)
coerce_index
end
|
#reorder(new_order) ⇒ Object
199
200
201
202
|
# File 'lib/daru_lite/index/multi_index.rb', line 199
def reorder(new_order)
from = to_a
MultiIndex.from_tuples(new_order.map { |i| from[i] })
end
|
314
315
316
|
# File 'lib/daru_lite/index/multi_index.rb', line 314
def size
@labels[0].size
end
|
#sparse_tuples ⇒ Object
Return tuples with nils in place of repeating values, like this:
- :a , :bar, :one
- nil, nil , :two
- nil, :foo, :one
362
363
364
365
366
367
368
|
# File 'lib/daru_lite/index/multi_index.rb', line 362
def sparse_tuples
tuples = to_a
[tuples.first] + each_cons(2).map do |prev, cur|
left = cur.zip(prev).drop_while { |c, p| c == p }
Array.new(cur.size - left.size) + left.map(&:first)
end
end
|
#subset(*indexes) ⇒ Object
167
168
169
170
171
172
173
|
# File 'lib/daru_lite/index/multi_index.rb', line 167
def subset(*indexes)
if indexes.first.is_a? Integer
MultiIndex.from_tuples(indexes.map { |index| key(index) })
else
self[indexes].conform indexes
end
end
|
328
329
330
|
# File 'lib/daru_lite/index/multi_index.rb', line 328
def to_a
(0...size).map { |e| key(e) }
end
|
370
371
372
|
# File 'lib/daru_lite/index/multi_index.rb', line 370
def to_df
DaruLite::DataFrame.new(@name.zip(to_a.transpose).to_h)
end
|
341
342
343
344
|
# File 'lib/daru_lite/index/multi_index.rb', line 341
def to_html
path = File.expand_path('../iruby/templates/multi_index.html.erb', __dir__)
ERB.new(File.read(path).strip).result(binding)
end
|
#try_retrieve_from_integer(int) ⇒ Object
204
205
206
|
# File 'lib/daru_lite/index/multi_index.rb', line 204
def try_retrieve_from_integer(int)
@levels[0].key?(int) ? retrieve_from_tuples([int]) : int
end
|
#valid?(*indexes) ⇒ Boolean
139
140
141
142
143
144
145
|
# File 'lib/daru_lite/index/multi_index.rb', line 139
def valid?(*indexes)
pos(*indexes)
true
rescue IndexError
false
end
|
332
333
334
|
# File 'lib/daru_lite/index/multi_index.rb', line 332
def values
Array.new(size) { |i| i }
end
|
318
319
320
|
# File 'lib/daru_lite/index/multi_index.rb', line 318
def width
@levels.size
end
|
294
295
296
|
# File 'lib/daru_lite/index/multi_index.rb', line 294
def |(other)
MultiIndex.from_tuples(to_a | other.to_a)
end
|