Class: Daru::Index

Inherits:
Object show all
Includes:
Enumerable
Defined in:
lib/daru/index/index.rb

Overview

rubocop:disable Metrics/ClassLength

Direct Known Subclasses

CategoricalIndex, DateTimeIndex, MultiIndex

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(index, opts = {}) ⇒ Index

Returns a new instance of Index.

Examples:


idx = Daru::Index.new [:one, 'one', 1, 2, :two]
=> #<Daru::Index(5): {one, one, 1, 2, two}>

# set the name

idx.name = "index_name"
=> "index_name"

idx
=> #<Daru::Index(5): index_name {one, one, 1, 2, two}>

# set the name during initialization

idx = Daru::Index.new [:one, 'one', 1, 2, :two], name: "index_name"
=> #<Daru::Index(5): index_name {one, one, 1, 2, two}>


66
67
68
69
70
71
72
# File 'lib/daru/index/index.rb', line 66

def initialize index, opts={}
  index = guess_index index
  @relation_hash = index.each_with_index.to_h.freeze
  @keys = @relation_hash.keys
  @size = @relation_hash.size
  @name = opts[:name]
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



47
48
49
# File 'lib/daru/index/index.rb', line 47

def name
  @name
end

#relation_hashObject (readonly)

Returns the value of attribute relation_hash.



46
47
48
# File 'lib/daru/index/index.rb', line 46

def relation_hash
  @relation_hash
end

#sizeObject (readonly)

Returns the value of attribute size.



46
47
48
# File 'lib/daru/index/index.rb', line 46

def size
  @size
end

Class Method Details

.__new__Object



12
# File 'lib/daru/index/index.rb', line 12

alias :__new__ :new

._load(data) ⇒ Object



253
254
255
256
257
# File 'lib/daru/index/index.rb', line 253

def self._load data
  h = Marshal.load data

  Daru::Index.new(h[:relation_hash].keys)
end

.coerce(maybe_index) ⇒ Object



35
36
37
# File 'lib/daru/index/index.rb', line 35

def self.coerce maybe_index
  maybe_index.is_a?(Index) ? maybe_index : Daru::Index.new(maybe_index)
end

.inherited(subclass) ⇒ Object



14
15
16
17
18
# File 'lib/daru/index/index.rb', line 14

def inherited subclass
  class << subclass
    alias :new :__new__
  end
end

.new(*args, &block) ⇒ Object

We over-ride the .new method so that any sort of Index can be generated from Daru::Index based on the types of arguments supplied.



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/daru/index/index.rb', line 23

def self.new *args, &block
  # FIXME: I'm not sure this clever trick really deserves our attention.
  # Most of common ruby libraries just avoid it in favor of usual
  # factor method, like `Index.create`. When `Index.new(...).class != Index`
  # it just leads to confusion and surprises. - zverok, 2016-05-18
  source = args.first

  MultiIndex.try_from_tuples(source) ||
    DateTimeIndex.try_create(source) ||
    allocate.tap { |i| i.send :initialize, *args, &block }
end

Instance Method Details

#&(other) ⇒ Object

Produce a new index from the set intersection of two indexes



199
200
201
# File 'lib/daru/index/index.rb', line 199

def & other
  Index.new(to_a & other.to_a)
end

#==(other) ⇒ Object



74
75
76
77
78
79
# File 'lib/daru/index/index.rb', line 74

def ==(other)
  return false if self.class != other.class || other.size != @size

  @relation_hash.keys == other.to_a &&
    @relation_hash.values == other.relation_hash.values
end

#[](key, *rest) ⇒ Object



81
82
83
84
85
86
87
88
89
90
# File 'lib/daru/index/index.rb', line 81

def [](key, *rest)
  case
  when key.is_a?(Range)
    by_range key
  when !rest.empty?
    by_multi_key key, *rest
  else
    by_single_key key
  end
end

#_dumpObject



249
250
251
# File 'lib/daru/index/index.rb', line 249

def _dump(*)
  Marshal.dump(relation_hash: @relation_hash)
end

#add(*indexes) ⇒ Object



245
246
247
# File 'lib/daru/index/index.rb', line 245

def add *indexes
  Daru::Index.new(to_a + indexes)
end

#at(*positions) ⇒ object

Takes positional values and returns subset of the self

capturing the indexes at mentioned positions

Examples:

idx = Daru::Index.new [:a, :b, :c]
idx.at 0, 1
# => #<Daru::Index(2): {a, b}>

Parameters:

  • positions (Array<Integer>)

    positional values

Returns:

  • (object)

    index object



145
146
147
148
149
150
151
152
153
# File 'lib/daru/index/index.rb', line 145

def at *positions
  positions = preprocess_positions(*positions)
  validate_positions(*positions)
  if positions.is_a? Integer
    key(positions)
  else
    self.class.new positions.map(&method(:key))
  end
end

#conformObject

Provide an Index for sub vector produced

Parameters:

  • * (Hash)

    a customizable set of options

Returns:

  • (Object)

    the Index object for sub vector produced



263
264
265
# File 'lib/daru/index/index.rb', line 263

def conform(*)
  self
end

#dupObject



241
242
243
# File 'lib/daru/index/index.rb', line 241

def dup
  Daru::Index.new @relation_hash.keys
end

#each(&block) ⇒ Object



39
40
41
42
43
44
# File 'lib/daru/index/index.rb', line 39

def each(&block)
  return to_enum(:each) unless block_given?

  @relation_hash.each_key(&block)
  self
end

#empty?Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/daru/index/index.rb', line 237

def empty?
  @relation_hash.empty?
end

#include?(index) ⇒ Boolean

Returns:

  • (Boolean)


212
213
214
# File 'lib/daru/index/index.rb', line 212

def include? index
  @relation_hash.key? index
end

#inspect(threshold = 20) ⇒ Object



155
156
157
158
159
160
161
162
# File 'lib/daru/index/index.rb', line 155

def inspect threshold=20
  name_part = @name ? "#{@name} " : ''
  if size <= threshold
    "#<#{self.class}(#{size}): #{name_part}{#{to_a.join(', ')}}>"
  else
    "#<#{self.class}(#{size}): #{name_part}{#{to_a.first(threshold).join(', ')} ... #{to_a.last}}>"
  end
end

#is_values(*indexes) ⇒ Daru::Vector

Note:

Do not use it to check for Float::NAN as Float::NAN == Float::NAN is false

Return vector of booleans with value at ith position is either true or false depending upon whether index value at position i is equal to any of the values passed in the argument or not

Examples:

dv = Daru::Index.new [1, 2, 3, :one, 'one']
dv.is_values 1, 'one'
# => #<Daru::Vector(5)>
#     0  true
#     1  false
#     2  false
#     3  false
#     4  true

Parameters:

  • indexes (Array)

    values to equate with

Returns:



232
233
234
235
# File 'lib/daru/index/index.rb', line 232

def is_values(*indexes) # rubocop:disable Style/PredicateName
  bool_array = @relation_hash.keys.map { |r| indexes.include?(r) }
  Daru::Vector.new(bool_array)
end

#key(value) ⇒ Object



207
208
209
210
# File 'lib/daru/index/index.rb', line 207

def key(value)
  return nil unless value.is_a?(Numeric)
  @keys[value]
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

Examples:

x = Daru::Index.new [:a, :b, :c]
x.pos :a, 1
# => [0, 1]

Parameters:

  • indexes (Array<object>)

    indexes or positions



112
113
114
115
116
117
118
119
120
# File 'lib/daru/index/index.rb', line 112

def pos *indexes
  indexes = preprocess_range(indexes.first) if indexes.first.is_a? Range

  if indexes.size == 1
    numeric_pos indexes.first
  else
    indexes.map { |index| numeric_pos index }
  end
end

#reorder(new_order) ⇒ Object



267
268
269
270
# File 'lib/daru/index/index.rb', line 267

def reorder(new_order)
  from = to_a
  self.class.new(new_order.map { |i| from[i] })
end

#slice(*args) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/daru/index/index.rb', line 164

def slice *args
  start = args[0]
  en = args[1]

  start_idx = @relation_hash[start]
  en_idx    = @relation_hash[en]

  if start_idx.nil?
    nil
  elsif en_idx.nil?
    Array(start_idx..size-1)
  else
    Array(start_idx..en_idx)
  end
end

#sort(opts = {}) ⇒ Index

Sorts a ‘Index`, according to its values. Defaults to ascending order sorting.

Examples:

di = Daru::Index.new [100, 99, 101, 1, 2]
# Say you want to sort in descending order
di.sort(ascending: false) #=> Daru::Index.new [101, 100, 99, 2, 1]
# Say you want to sort in ascending order
di.sort #=> Daru::Index.new [1, 2, 99, 100, 101]

Parameters:

  • opts (Hash) (defaults to: {})

    the options for sort method.

Options Hash (opts):

  • :ascending (Boolean)

    False, to get descending order.

Returns:

  • (Index)

    sorted ‘Index` according to its values.



286
287
288
289
290
291
292
293
294
295
# File 'lib/daru/index/index.rb', line 286

def sort opts={}
  opts = {ascending: true}.merge(opts)
  if opts[:ascending]
    new_index, = @relation_hash.sort.transpose
  else
    new_index, = @relation_hash.sort.reverse.transpose
  end

  self.class.new(new_index)
end

#subset(*indexes) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/daru/index/index.rb', line 122

def subset *indexes
  if indexes.first.is_a? Range
    start = indexes.first.begin
    en = indexes.first.end

    subset_slice start, en
  elsif include? indexes.first
    # Assume 'indexes' contain indexes not positions
    Daru::Index.new indexes
  else
    # Assume 'indexes' contain positions not indexes
    Daru::Index.new(indexes.map { |k| key k })
  end
end

#subset_slice(*args) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/daru/index/index.rb', line 180

def subset_slice *args
  start = args[0]
  en = args[1]

  if start.is_a?(Integer) && en.is_a?(Integer)
    Index.new @keys[start..en]
  else
    start_idx = @relation_hash[start]
    en_idx    = @relation_hash[en]
    Index.new @keys[start_idx..en_idx]
  end
end

#to_aObject



203
204
205
# File 'lib/daru/index/index.rb', line 203

def to_a
  @relation_hash.keys
end

#valid?(*indexes) ⇒ true, false

Returns true if all arguments are either a valid category or position

Examples:

idx.valid? :a, 2
# => true
idx.valid? 3
# => false

Parameters:

  • indexes (Array<object>)

    categories or positions

Returns:

  • (true, false)


100
101
102
# File 'lib/daru/index/index.rb', line 100

def valid? *indexes
  indexes.all? { |i| to_a.include?(i) || (i.is_a?(Numeric) && i < size) }
end

#|(other) ⇒ Object

Produce new index from the set union of two indexes.



194
195
196
# File 'lib/daru/index/index.rb', line 194

def |(other)
  Index.new(to_a | other.to_a)
end