Class: Daru::MultiIndex
- Inherits:
-
Index
show all
- Defined in:
- lib/daru/index/multi_index.rb
Overview
rubocop:disable Metrics/ClassLength
Instance Attribute Summary collapse
Attributes inherited from Index
#name, #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 mulit_index.name = [”, ‘level1_name1’, ‘level2_name’]
79
80
81
82
83
84
85
86
87
88
89
90
|
# File 'lib/daru/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/index/multi_index.rb', line 11
def labels
@labels
end
|
Class Method Details
.from_arrays(arrays) ⇒ Object
105
106
107
108
109
110
111
112
113
114
|
# File 'lib/daru/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/index/multi_index.rb', line 116
def self.from_tuples tuples
from_arrays tuples.transpose
end
|
.try_from_tuples(tuples) ⇒ Object
120
121
122
123
124
125
126
|
# File 'lib/daru/index/multi_index.rb', line 120
def self.try_from_tuples tuples
if tuples.respond_to?(:first) && tuples.first.is_a?(Array)
from_tuples(tuples)
else
nil
end
end
|
Instance Method Details
299
300
301
|
# File 'lib/daru/index/multi_index.rb', line 299
def & other
MultiIndex.from_tuples(to_a & other.to_a)
end
|
#==(other) ⇒ Object
322
323
324
325
326
|
# File 'lib/daru/index/multi_index.rb', line 322
def == other
self.class == other.class &&
labels == other.labels &&
levels == other.levels
end
|
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# File 'lib/daru/index/multi_index.rb', line 128
def [] *key
key.flatten!
case
when key[0].is_a?(Range)
retrieve_from_range(key[0])
when 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
198
199
200
|
# File 'lib/daru/index/multi_index.rb', line 198
def add *indexes
Daru::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
188
189
190
191
192
193
194
195
196
|
# File 'lib/daru/index/multi_index.rb', line 188
def at *positions
positions = preprocess_positions(*positions)
validate_positions(*positions)
if positions.is_a? Integer
key(positions)
else
Daru::MultiIndex.from_tuples positions.map(&method(:key))
end
end
|
#coerce_index ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
261
262
|
# File 'lib/daru/index/multi_index.rb', line 250
def coerce_index
if @levels.size == 1
elements = to_a.flatten
if elements.uniq.length == elements.length
Daru::Index.new(elements)
else
Daru::CategoricalIndex.new(elements)
end
else
self
end
end
|
Provide a MultiIndex for sub vector produced
350
351
352
353
|
# File 'lib/daru/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
291
292
293
|
# File 'lib/daru/index/multi_index.rb', line 291
def drop_left_level by=1
MultiIndex.from_arrays to_a.transpose[by..-1]
end
|
287
288
289
|
# File 'lib/daru/index/multi_index.rb', line 287
def dup
MultiIndex.new levels: levels.dup, labels: labels.dup, name: (@name.nil? ? nil : @name.dup)
end
|
#each(&block) ⇒ Object
3
4
5
|
# File 'lib/daru/index/multi_index.rb', line 3
def each(&block)
to_a.each(&block)
end
|
#empty? ⇒ Boolean
303
304
305
|
# File 'lib/daru/index/multi_index.rb', line 303
def empty?
@labels.flatten.empty? && @levels.all?(&:empty?)
end
|
#include?(tuple) ⇒ Boolean
307
308
309
310
311
312
|
# File 'lib/daru/index/multi_index.rb', line 307
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/index/multi_index.rb', line 336
def inspect threshold=20
"#<Daru::MultiIndex(#{size}x#{width})>\n" +
Formatters::Table.format([], headers: @name, row_headers: sparse_tuples, threshold: threshold)
end
|
#key(index) ⇒ Object
279
280
281
282
283
284
285
|
# File 'lib/daru/index/multi_index.rb', line 279
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/index/multi_index.rb', line 13
def levels
@levels.map(&:keys)
end
|
#map(&block) ⇒ Object
7
8
9
|
# File 'lib/daru/index/multi_index.rb', line 7
def map(&block)
to_a.map(&block)
end
|
#name=(names) ⇒ Object
92
93
94
95
|
# File 'lib/daru/index/multi_index.rb', line 92
def name=(names)
validate_name names, @labels
@name = names
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
160
161
162
163
164
165
166
167
168
|
# File 'lib/daru/index/multi_index.rb', line 160
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
242
243
244
245
246
247
248
|
# File 'lib/daru/index/multi_index.rb', line 242
def remove_layer layer_index
@levels.delete_at(layer_index)
@labels.delete_at(layer_index)
@name.delete_at(layer_index) unless @name.nil?
coerce_index
end
|
#reorder(new_order) ⇒ Object
202
203
204
205
|
# File 'lib/daru/index/multi_index.rb', line 202
def reorder(new_order)
from = to_a
self.class.from_tuples(new_order.map { |i| from[i] })
end
|
314
315
316
|
# File 'lib/daru/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
361
362
363
364
365
366
367
|
# File 'lib/daru/index/multi_index.rb', line 361
def sparse_tuples
tuples = to_a
[tuples.first] + each_cons(2).map { |prev, cur|
left = cur.zip(prev).drop_while { |c, p| c == p }
[nil] * (cur.size - left.size) + left.map(&:first)
}
end
|
#subset(*indexes) ⇒ Object
170
171
172
173
174
175
176
|
# File 'lib/daru/index/multi_index.rb', line 170
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/index/multi_index.rb', line 328
def to_a
(0...size).map { |e| key(e) }
end
|
341
342
343
344
|
# File 'lib/daru/index/multi_index.rb', line 341
def to_html
path = File.expand_path('../../iruby/templates/multi_index.html.erb', __FILE__)
ERB.new(File.read(path).strip).result(binding)
end
|
#try_retrieve_from_integer(int) ⇒ Object
207
208
209
|
# File 'lib/daru/index/multi_index.rb', line 207
def try_retrieve_from_integer int
@levels[0].key?(int) ? retrieve_from_tuples([int]) : int
end
|
#valid?(*indexes) ⇒ Boolean
144
145
146
147
148
149
150
|
# File 'lib/daru/index/multi_index.rb', line 144
def valid? *indexes
pos(*indexes)
return true
rescue IndexError
return false
end
|
332
333
334
|
# File 'lib/daru/index/multi_index.rb', line 332
def values
Array.new(size) { |i| i }
end
|
318
319
320
|
# File 'lib/daru/index/multi_index.rb', line 318
def width
@levels.size
end
|
295
296
297
|
# File 'lib/daru/index/multi_index.rb', line 295
def | other
MultiIndex.from_tuples(to_a | other.to_a)
end
|