Class: DaruLite::CategoricalIndex
- Defined in:
- lib/daru_lite/index/categorical_index.rb
Constant Summary collapse
- UNSUPPORTED_RANGE_MSG =
'CategoricalIndex does not support label-range slicing: ' \ 'categories are unordered and may repeat'.freeze
Instance Attribute Summary
Attributes inherited from Index
Instance Method Summary collapse
-
#==(other) ⇒ true, false
Compares two index object.
-
#[](*keys) ⇒ Integer, ...
Returns the position(s) of the given category/categories or position(s).
-
#add(*indexes) ⇒ DaruLite::CategoricalIndex
Add specified index values to the index object.
-
#at(*positions) ⇒ object
Takes positional values and returns subset of the self capturing the categories at mentioned positions.
-
#categories ⇒ Object
Returns array of categories.
-
#dup ⇒ DaruLite::CategoricalIndex
Duplicates the index object and return it.
-
#each ⇒ Enumerator
Returns enumerator enumerating all index values in the order they occur.
-
#empty? ⇒ true, false
Returns true if index object is storing no category.
-
#include?(index) ⇒ true, false
Returns true index or category is valid.
-
#index_from_pos(pos) ⇒ object
Returns index value from position.
-
#initialize(indexes) ⇒ DaruLite::CategoricalIndex
constructor
Create a categorical index object.
-
#key(value) ⇒ object?
Returns the category located at a positional value.
-
#pos(*indexes) ⇒ Object
Returns positions given categories or positions.
-
#size ⇒ Integer
Returns size of the index object.
-
#slice ⇒ Object
Label-range slicing is not supported: categories are unordered and may repeat, so a range of positions between two labels is ambiguous.
-
#subset(*indexes) ⇒ DaruLite::CategoricalIndex
Return subset given categories or positions.
-
#subset_slice ⇒ Object
Label-range slicing is not supported: categories are unordered and may repeat, so a range of positions between two labels is ambiguous.
-
#to_a ⇒ Array
Returns all the index values.
-
#to_h ⇒ Hash
Returns hash table mapping category to positions at which they occur.
Methods inherited from Index
#&, __new__, #_dump, _load, coerce, #conform, #delete_at, inherited, #inspect, #is_values, new, #reorder, #sort, #to_df, #valid?, #|
Constructor Details
#initialize(indexes) ⇒ DaruLite::CategoricalIndex
Create a categorical index object.
13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/daru_lite/index/categorical_index.rb', line 13 def initialize(indexes) # Create a hash to map each category to positional indexes categories = indexes.each_with_index.group_by(&:first) @cat_hash = categories.transform_values { |group| group.map(&:last) } # Map each category to a unique integer for effective storage in @array map_cat_int = categories.keys.each_with_index.to_h # To link every instance to its category, # it stores integer for every instance representing its category @array = map_cat_int.values_at(*indexes) end |
Instance Method Details
#==(other) ⇒ true, false
Compares two index object. Returns true if every instance of category occur at the same position
154 155 156 157 158 |
# File 'lib/daru_lite/index/categorical_index.rb', line 154 def ==(other) self.class == other.class && size == other.size && to_h == other.to_h end |
#[](*keys) ⇒ Integer, ...
Returns the position(s) of the given category/categories or position(s). Mirrors Index#[] but resolves against the categorical structure (@cat_hash / @array) instead of @relation_hash, which CategoricalIndex never populates.
86 87 88 89 90 |
# File 'lib/daru_lite/index/categorical_index.rb', line 86 def [](*keys) pos(*keys) rescue IndexError nil end |
#add(*indexes) ⇒ DaruLite::CategoricalIndex
Add specified index values to the index object
240 241 242 |
# File 'lib/daru_lite/index/categorical_index.rb', line 240 def add(*indexes) DaruLite::CategoricalIndex.new(to_a + indexes) end |
#at(*positions) ⇒ object
Takes positional values and returns subset of the self capturing the categories at mentioned positions
223 224 225 226 227 228 229 230 231 |
# File 'lib/daru_lite/index/categorical_index.rb', line 223 def at(*positions) positions = preprocess_positions(*positions) validate_positions(*positions) if positions.is_a? Integer index_from_pos(positions) else DaruLite::CategoricalIndex.new(positions.map { |p| index_from_pos(p) }) end end |
#categories ⇒ Object
Returns array of categories
45 46 47 |
# File 'lib/daru_lite/index/categorical_index.rb', line 45 def categories @cat_hash.keys end |
#dup ⇒ DaruLite::CategoricalIndex
Duplicates the index object and return it
28 29 30 31 |
# File 'lib/daru_lite/index/categorical_index.rb', line 28 def dup # Improve it by intializing index by hash DaruLite::CategoricalIndex.new to_a end |
#each ⇒ Enumerator
Returns enumerator enumerating all index values in the order they occur
138 139 140 141 142 143 |
# File 'lib/daru_lite/index/categorical_index.rb', line 138 def each return enum_for(:each) unless block_given? @array.each { |pos| yield cat_from_int pos } self end |
#empty? ⇒ true, false
Returns true if index object is storing no category
196 197 198 |
# File 'lib/daru_lite/index/categorical_index.rb', line 196 def empty? @array.empty? end |
#include?(index) ⇒ true, false
Returns true index or category is valid
36 37 38 |
# File 'lib/daru_lite/index/categorical_index.rb', line 36 def include?(index) @cat_hash.include? index end |
#index_from_pos(pos) ⇒ object
Returns index value from position
128 129 130 |
# File 'lib/daru_lite/index/categorical_index.rb', line 128 def index_from_pos(pos) cat_from_int @array[pos] end |
#key(value) ⇒ object?
Returns the category located at a positional value. Mirrors Index#key but reads the categorical structure instead of @keys, which CategoricalIndex never populates.
101 102 103 104 105 |
# File 'lib/daru_lite/index/categorical_index.rb', line 101 def key(value) return nil unless value.is_a?(Numeric) to_a[value] end |
#pos(*indexes) ⇒ Object
If the argument does not a valid category it treats it as position value and return it as it is.
Returns positions given categories or positions
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/daru_lite/index/categorical_index.rb', line 57 def pos(*indexes) if indexes.size == 1 && indexes.first.is_a?(Range) && !include?(indexes.first) return pos_from_range(indexes.first) end positions = indexes.map do |index| if include? index @cat_hash[index] elsif index.is_a?(Numeric) && index < @array.size index else raise IndexError, "#{index.inspect} is neither a valid category nor a valid position" end end positions.flatten! positions.size == 1 ? positions.first : positions.sort end |
#size ⇒ Integer
Returns size of the index object
185 186 187 |
# File 'lib/daru_lite/index/categorical_index.rb', line 185 def size @array.size end |
#slice ⇒ Object
Label-range slicing is not supported: categories are unordered and may repeat, so a range of positions between two labels is ambiguous.
110 111 112 |
# File 'lib/daru_lite/index/categorical_index.rb', line 110 def slice(*) raise ArgumentError, UNSUPPORTED_RANGE_MSG end |
#subset(*indexes) ⇒ DaruLite::CategoricalIndex
Return subset given categories or positions
208 209 210 211 212 213 |
# File 'lib/daru_lite/index/categorical_index.rb', line 208 def subset(*indexes) positions = pos(*indexes) new_index = positions.map { |pos| index_from_pos pos } DaruLite::CategoricalIndex.new new_index.flatten end |
#subset_slice ⇒ Object
Label-range slicing is not supported: categories are unordered and may repeat, so a range of positions between two labels is ambiguous.
117 118 119 |
# File 'lib/daru_lite/index/categorical_index.rb', line 117 def subset_slice(*) raise ArgumentError, UNSUPPORTED_RANGE_MSG end |
#to_a ⇒ Array
Returns all the index values
165 166 167 |
# File 'lib/daru_lite/index/categorical_index.rb', line 165 def to_a each.to_a end |
#to_h ⇒ Hash
Returns hash table mapping category to positions at which they occur
175 176 177 |
# File 'lib/daru_lite/index/categorical_index.rb', line 175 def to_h @cat_hash end |