Module: RedAmber::VectorUpdatable

Included in:
Vector
Defined in:
lib/red_amber/vector_updatable.rb

Overview

Mix-in for class Vector Functions to make up some data (especially missing) for new data.

Instance Method Summary collapse

Instance Method Details

#cast(type) ⇒ Vector

Cast self to ‘type`.

Parameters:

  • type (symbol)

    type to cast.

Returns:

Since:

  • 0.5.0



476
477
478
# File 'lib/red_amber/vector_updatable.rb', line 476

def cast(type)
  Vector.create(data.cast(type))
end

#concatenate(other) ⇒ Vector Also known as: concat

Concatenate other array-like to self.

Examples:

Concatenate to string

string_vector

# =>
#<RedAmber::Vector(:string, size=2):0x00000000000037b4>
["A", "B"]

string_vector.concatenate([1, 2])

# =>
#<RedAmber::Vector(:string, size=4):0x0000000000003818>
["A", "B", "1", "2"]

Concatenate to integer

integer_vector

# =>
#<RedAmber::Vector(:uint8, size=2):0x000000000000382c>
[1, 2]

integer_vector.concatenate(["A", "B"])
# =>
#<RedAmber::Vector(:uint8, size=4):0x0000000000003840>
[1, 2, 65, 66]

Parameters:

  • other (Vector, Array, Arrow::Array, Arrow::ChunkedArray)

    other array-like to concatenate.

Returns:

  • (Vector)

    concatenated Vector.

Since:

  • 0.4.0



454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/red_amber/vector_updatable.rb', line 454

def concatenate(other)
  concatenated_array =
    case other
    when Vector
      data + other.data
    when Arrow::ChunkedArray
      data + other.pack
    else
      data + other
    end
  Vector.create(concatenated_array)
end

#fill_nil(value) ⇒ Vector

Note:

Use ‘fill_nil_backawrd` or `fill_nil_forward` to replace nil by adjacent values.

Replace nil to value.

Parameters:

  • value (scalar)

    the value to replace with.

Returns:

  • (Vector)

    replaced Vector

See Also:

  • #fill_nil_backward
  • #fill_nil_forward

Since:

  • 0.5.0



164
165
166
# File 'lib/red_amber/vector_updatable.rb', line 164

def fill_nil(value)
  is_nil.if_else(value, self)
end

#if_else(true_choise, false_choise) ⇒ Vector #if_else(true_choise, false_choise) ⇒ Vector

Choose values based on self.

Ternary element-wise function

Returns a Vector.

  • Self must be a boolean Vector.

  • ‘true_choice`, `false_choice` must be of the same type scalar / array / Vector.

  • ‘nil` values in self will be promoted to the output.

Overloads:

  • #if_else(true_choise, false_choise) ⇒ Vector

    replace with a scalar.

    Examples:

    Replace with scalar choices

    Vector.new(true, true, false, nil, false).if_else(1, 2)
    
    # =>
    #<RedAmber::Vector(:uint8, size=5):0x000000000000c198>
    [1, 1, 2, nil, 2]

    Parameters:

    • true_choice (scalar)

      a value to be replaced with true.

    • false_choice (scalar)

      a value to be replaced with false.

    Returns:

    • (Vector)

      replaced result.

  • #if_else(true_choise, false_choise) ⇒ Vector

    replace with a scalar.

    Examples:

    Replace with Array choices

    boolean_vector = Vector.new(true, true, false, nil, false)
    true_choise = Vector.new([1.1, 2.2, 3.3, 4.4, 5.5])
    false_choise = -true_choise
    boolean_vector.if_else(true_choise, false_choise)
    
    # =>
    #<RedAmber::Vector(:double, size=5):0x000000000000cd28>
    [1.1, 2.2, -3.3, nil, -5.5]

    Normalize negative indices to positive ones

    indices = Vector.new([1, -1, 3, -4])
    array_size = 10
    normalized_indices = (indices < 0).if_else(indices + array_size, indices)
    
    # =>
    #<RedAmber::Vector(:int16, size=4):0x000000000000f85c>
    [1, 9, 3, 6]

    Parameters:

    • true_choice (Vector, Array, Arrow::Array)

      values to be replaced with true. The size of true_choice must be same as self.

    • false_choice (Vector, Array, Arrow::Array)

      values to be replaced with false. The size of false_choice must be same as self.

    Returns:

    • (Vector)

      replaced result.

Raises:



221
222
223
224
225
226
227
228
# File 'lib/red_amber/vector_updatable.rb', line 221

def if_else(true_choice, false_choice)
  true_choice = true_choice.data if true_choice.is_a? Vector
  false_choice = false_choice.data if false_choice.is_a? Vector
  raise VectorTypeError, 'Reciever must be a boolean' unless boolean?

  datum = find(:if_else).execute([data, true_choice, false_choice])
  Vector.create(datum.value)
end

#list_flattenObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Flatten list Vector for rows.



359
360
361
# File 'lib/red_amber/vector_updatable.rb', line 359

def list_flatten
  Vector.create find(:list_flatten).execute([data]).value
end

#list_separateObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Separate list Vector by columns.



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/red_amber/vector_updatable.rb', line 339

def list_separate
  len = list_sizes.data
  min, max = Arrow::Function.find(:min_max).execute([len]).value.value.map(&:value)

  result = []
  (0...min).each do |i|
    result << Vector.create(find(:list_element).execute([data, i]).value)
  end
  return result if min == max

  (min...max).each do |i|
    result << Vector.new(data.map { |e| e&.[](i) })
  end
  result
end

#list_sizesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return element size Array for list Vector.



331
332
333
# File 'lib/red_amber/vector_updatable.rb', line 331

def list_sizes
  Vector.create find(:list_value_length).execute([data]).value
end

#merge(other, sep: ' ') ⇒ Vector

Merge String or other string Vector to self.

Self must be a string Vector.

Parameters:

  • other (String, Vector)

    merger from right. It will be broadcasted if it is a scalar String.

  • sep (String) (defaults to: ' ')

    separator.

Returns:



396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# File 'lib/red_amber/vector_updatable.rb', line 396

def merge(other, sep: ' ')
  if empty? || !string?
    raise VectorTypeError,
          "self is not a string Vector: #{self}"
  end
  unless sep.is_a?(String)
    raise VectorArgumentError, "separator is not a String: #{sep}"
  end

  other_array =
    case other
    in String => s
      [s] * size
    in (Vector | Arrow::Array | Arrow::ChunkedArray) => x if x.string?
      x.to_a
    else
      raise VectorArgumentError,
            "other is not a String or a string Vector: #{self}"
    end

  list = Arrow::Array.new(to_a.zip(other_array))
  datum = find(:binary_join).execute([list, sep])
  Vector.create(datum.value)
end

#primitive_invertVector

Another #invert which is same behavior as Ruby’s invert.

![true, false, nil] #=> [false, true, true]

Examples:

vector = Vector.new([true, true, false, nil])

# =>
#<RedAmber::Vector(:boolean, size=4):0x000000000000fa8c>
[true, true, false, nil]

# nil is converted to nil by Vector#invert.
vector.invert
# or
!vector

#<RedAmber::Vector(:boolean, size=4):0x000000000000faa0>
[false, false, true, nil]

# On the other hand,
# Vector#primitive_invert follows Ruby's BasicObject#!'s behavior.
vector.primitive_invert

# =>
#<RedAmber::Vector(:boolean, size=4):0x000000000000fab4>
[false, false, true, true]

Returns:

  • (Vector)

    follows Ruby’s BasicObject#!‘s behavior.

Raises:



258
259
260
261
262
# File 'lib/red_amber/vector_updatable.rb', line 258

def primitive_invert
  raise VectorTypeError, "Not a boolean Vector: #{self}" unless boolean?

  is_nil.if_else(false, self).invert
end

#replace(booleans, replacer_by_scalar) ⇒ Vector #replace(indices, replacer_by_scalar) ⇒ Vector #replace(booleans, replacer_array) ⇒ Vector #replace(indices, replacer_array) ⇒ Vector

Replace data in self by position specifier and replacer.

  • Scalar value may be broadcasted.

  • Returned value type may be automatically up-casted by replacer.

Overloads:

  • #replace(booleans, replacer_by_scalar) ⇒ Vector

    Replace the value where true in boolean specifier to scalar replacer.

    Examples:

    Replace with boolean specifier and scalar replacer

    Vector.new([1, 2, 3]).replace([true, false, true], 0)
    
    # =>
    #<RedAmber::Vector(:uint8, size=3):0x000000000001ee10>
    [0, 2, 0]

    Type of result is up-casted by replacer.

    ector.new([1, 2, 3]).replace([true, false, true], -1.0)
    
    # =>
    #<RedAmber::Vector(:double, size=3):0x0000000000025d78>
    [-1.0, 2.0, -1.0]

    Position of nil in booleans is replaced with nil

    Vector.new([1, 2, 3]).replace([true, false, nil], -1)
    
    # =>
    #<RedAmber::Vector(:int8, size=3):0x00000000000304d0>
    [-1, 2, nil]

    Replace ‘NA’ to nil

    vector = Vector.new(['A', 'B', 'NA'])
    vector.replace(vector == 'NA', nil)
    
    # =>
    #<RedAmber::Vector(:string, size=3):0x000000000000f8ac>
    ["A", "B", nil]

    Parameters:

    • booleans (Array, Vector, Arrow::Array)

      boolean position specifier to specify the position to be replaced by true.

    • replacer_by_scalar (Scalar)

      new data to replace for.

    Returns:

    • (Vector)

      a new replaced Vector. If specifier has no true, returns self.

  • #replace(indices, replacer_by_scalar) ⇒ Vector

    Replace the value at the index specifier to scalar replacer.

    Examples:

    Replace with index specifier and scalar replacer

    Vector.new([1, 2, 3]).replace([0, 2], 0)
    
    # =>
    #<RedAmber::Vector(:uint8, size=3):0x000000000000c15c>
    [0, 2, 0]

    Parameters:

    • indices (Array, Vector, Arrow::Array)

      index specifier to specify the position to be replaced.

    • replacer_by_scalar (Scalar)

      new data to replace for.

    Returns:

    • (Vector)

      a new replaced Vector. If specifier is empty, returns self.

  • #replace(booleans, replacer_array) ⇒ Vector

    Replace the value where true in boolean specifier to replacer array.

    Examples:

    Replace with boolean specifier and replacer array

    vector = Vector.new([1, 2, 3])
    booleans = [true, false, true]
    replacer = [4, 5]
    vector.replace(booleans, replacer)
    
    # =>
    #<RedAmber::Vector(:uint8, size=3):0x000000000001ee10>
    [4, 2, 5]

    Parameters:

    • booleans (Array, Vector, Arrow::Array)

      boolean position specifier to specify the position to be replaced by true.

    • replacer_array (Vector, Array, Arrow::Array)

      new data to replace for. The number of true in booleans must be equal to the length of replacer array.

    Returns:

    • (Vector)

      a new replaced Vector. If specifier has no true, returns self.

  • #replace(indices, replacer_array) ⇒ Vector

    Replace the value at the index specifier to replacer array.

    Examples:

    Replace with index specifier and replacer array

    vector = Vector.new([1, 2, 3])
    indices = [0, 2]
    replacer = [4, 5]
    vector.replace(indices, replacer)
    
    # =>
    #<RedAmber::Vector(:uint8, size=3):0x000000000001ee10>
    [4, 2, 5]

    Parameters:

    • indices (Array, Vector, Arrow::Array)

      index specifier to specify the position to be replaced.

    • replacer_array (Vector, Array, Arrow::Array)

      new data to replace for. The length of index specifier must be equal to the length of replacer array.

    Returns:

    • (Vector)

      a new replaced Vector. If specifier is empty, returns self.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/red_amber/vector_updatable.rb', line 116

def replace(specifier, replacer)
  vector = Vector.new(parse_args(Array(specifier), size))
  return self if vector.empty? || empty?

  booleans =
    if vector.boolean?
      vector
    elsif vector.numeric?
      Vector.new(indices).is_in(vector)
    else
      raise VectorArgumentError, "Invalid data type #{specifier}"
    end
  return self if booleans.sum.zero?

  replacer_array =
    case replacer
    in []
      return self
    in nil | [nil]
      return replace_to_nil(booleans.data)
    in Arrow::Array
      replacer
    in Vector
      replacer.data
    in Array
      Arrow::Array.new(replacer)
    else # Broadcast scalar to Array
      Arrow::Array.new(Array(replacer) * booleans.to_a.count(true))
    end
  if booleans.sum != replacer_array.length
    raise VectorArgumentError, 'Replacements size unmatch'
  end

  replace_with(booleans.data, replacer_array)
end

#shift(amount = 1, fill: nil) ⇒ Vector

Shift elements in self.

Parameters:

  • amount (Integer) (defaults to: 1)

    amount of shift. Positive value will shift right, negative will shift left.

  • fill (Object) (defaults to: nil)

    complementary element to fill the new seat.

Returns:

  • (Vector)

    shifted Vector.

Raises:



273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/red_amber/vector_updatable.rb', line 273

def shift(amount = 1, fill: nil)
  raise VectorArgumentError, 'Shift amount is too large' if amount.abs >= size

  if amount.positive?
    filler = [fill] * amount
    Vector.new(filler.concat(Array(self[0...-amount])))
  elsif amount.negative?
    filler = [fill] * -amount
    Vector.new(Array(self[-amount...]).concat(filler))
  else # amount == 0
    self
  end
end

#split(sep = nil, limit = 0) ⇒ Object

Note:

if sep is not specified, use Arrow’s ascii_split_whitespace. It will separate string by ascii whitespaces.

Note:

if sep specified, sep and limit will passed to String#split.

Split string Vector by each element with separator and returns list Array.



369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'lib/red_amber/vector_updatable.rb', line 369

def split(sep = nil, limit = 0)
  if empty? || !string?
    raise VectorTypeError, "self is not a valid string Vector: #{self}"
  end
  if self[0].nil? && uniq.to_a == [nil] # Avoid heavy check to be activated always.
    raise VectorTypeError, 'self contains only nil'
  end

  list =
    if sep
      Arrow::Array.new(to_a.map { |e| e&.split(sep, limit) })
    else
      find(:ascii_split_whitespace).execute([data]).value
    end
  Vector.create(list)
end

#split_to_columns(sep = nil, limit = 0) ⇒ Array<Vector>

Note:

nil will separated as nil’s at same row. ex) ‘nil => [nil, nil]`

Split string Vector and returns Array of columns.

Parameters:

  • sep (nil, String, Regexp) (defaults to: nil)

    separator. If separator is nil (or no argeument given), the column will be splitted by Arrow’s split function using any ASCII whitespace. Otherwise, sep will passed to String#split.

  • limit (Integer) (defaults to: 0)

    maximum number to limit separation. Passed to String#split.

Returns:

  • (Array<Vector>)

    an Array of Vectors.



302
303
304
305
# File 'lib/red_amber/vector_updatable.rb', line 302

def split_to_columns(sep = nil, limit = 0)
  l = split(sep, limit)
  l.list_separate
end

#split_to_rows(sep = nil, limit = 0) ⇒ Vector

Note:

nil will separated as nil’s at same row. ex) ‘nil => [nil, nil]`

Split string Vector and flatten into rows.

Parameters:

  • sep (nil, String, Regexp) (defaults to: nil)

    separater. If separator is nil (or no argeument given), the column will be splitted by Arrow’s split function using any ASCII whitespace. Otherwise, sep will passed to String#split.

  • limit (Integer) (defaults to: 0)

    maximum number to limit separation. Passed to String#split.

Returns:

  • (Vector)

    a flatten Vector.



322
323
324
325
# File 'lib/red_amber/vector_updatable.rb', line 322

def split_to_rows(sep = nil, limit = 0)
  l = split(sep, limit)
  l.list_flatten
end