Class: Rover::Vector

Inherits:
Object
  • Object
show all
Defined in:
lib/rover/vector.rb

Constant Summary collapse

TYPE_CAST_MAPPING =

if a user never specifies types, the defaults are bool, float, int, and object keep these simple

we could create aliases for float64, int64, uint64 if so, type should still return the simple type

{
  bool: Numo::Bit,
  float32: Numo::SFloat,
  float: Numo::DFloat,
  int8: Numo::Int8,
  int16: Numo::Int16,
  int32: Numo::Int32,
  int: Numo::Int64,
  object: Numo::RObject,
  uint8: Numo::UInt8,
  uint16: Numo::UInt16,
  uint32: Numo::UInt32,
  uint: Numo::UInt64
}

Instance Method Summary collapse

Constructor Details

#initialize(data, type: nil) ⇒ Vector

Returns a new instance of Vector.

Raises:

  • (ArgumentError)


24
25
26
27
# File 'lib/rover/vector.rb', line 24

def initialize(data, type: nil)
  @data = cast_data(data, type: type)
  raise ArgumentError, "Bad size: #{@data.shape}" unless @data.ndim == 1
end

Instance Method Details

#!Object



138
139
140
141
142
143
144
# File 'lib/rover/vector.rb', line 138

def !
  if @data.is_a?(Numo::Bit)
    Vector.new(@data.eq(0))
  else
    raise "Not implemented yet"
  end
end

#-@Object



146
147
148
# File 'lib/rover/vector.rb', line 146

def -@
  self * -1
end

#[](v) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/rover/vector.rb', line 77

def [](v)
  if v.is_a?(Vector)
    Vector.new(v.to_numo.mask(@data))
  else
    @data[v]
  end
end

#[]=(k, v) ⇒ Object



85
86
87
88
# File 'lib/rover/vector.rb', line 85

def []=(k, v)
  k = k.to_numo if k.is_a?(Vector)
  @data[k] = v
end

#absObject



178
179
180
# File 'lib/rover/vector.rb', line 178

def abs
  Vector.new(@data.abs)
end

#all?(&block) ⇒ Boolean

Returns:

  • (Boolean)


228
229
230
# File 'lib/rover/vector.rb', line 228

def all?(&block)
  @data.to_a.all?(&block)
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


232
233
234
# File 'lib/rover/vector.rb', line 232

def any?(&block)
  @data.to_a.any?(&block)
end

#clamp(min, max) ⇒ Object



155
156
157
# File 'lib/rover/vector.rb', line 155

def clamp(min, max)
  dup.clamp!(min, max)
end

#clamp!(min, max) ⇒ Object



150
151
152
153
# File 'lib/rover/vector.rb', line 150

def clamp!(min, max)
  @data = @data.clip(min, max)
  self
end

#crosstab(other) ⇒ Object



253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/rover/vector.rb', line 253

def crosstab(other)
  index = uniq.sort
  index_pos = index.to_a.map.with_index.to_h
  df = DataFrame.new({"_" => index})
  other.uniq.sort.each do |k|
    df[k] = 0
  end
  to_a.zip(other.to_a) do |v1, v2|
    df[v2][index_pos[v1]] += 1
  end
  df
end

#diffObject

keep same number of rows as original to make it easy to add to original data frame



72
73
74
75
# File 'lib/rover/vector.rb', line 72

def diff
  diff = @data.cast_to(Numo::DFloat).diff
  Vector.new(diff.insert(0, Float::NAN))
end

#each(&block) ⇒ Object



182
183
184
# File 'lib/rover/vector.rb', line 182

def each(&block)
  @data.each(&block)
end

#each_with_index(&block) ⇒ Object



186
187
188
# File 'lib/rover/vector.rb', line 186

def each_with_index(&block)
  @data.each_with_index(&block)
end

#first(n = 1) ⇒ Object



236
237
238
239
240
241
242
# File 'lib/rover/vector.rb', line 236

def first(n = 1)
  if n >= size
    Vector.new(@data)
  else
    Vector.new(@data[0...n])
  end
end

#head(n = 5) ⇒ Object



266
267
268
269
# File 'lib/rover/vector.rb', line 266

def head(n = 5)
  n += size if n < 0
  first(n)
end

#in?(values) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/rover/vector.rb', line 124

def in?(values)
  ret = Numo::Bit.new(size).fill(false)
  values.each do |v|
    comp =
      if v.is_a?(Numeric) || v.is_a?(Numo::NArray)
        @data.eq(v)
      else
        Numo::Bit.cast(@data.map { |d| d == v })
      end
    ret |= comp
  end
  Vector.new(ret)
end

#inspectObject Also known as: to_s

TODO add type and size?



291
292
293
294
295
# File 'lib/rover/vector.rb', line 291

def inspect
  elements = first(5).to_a.map(&:inspect)
  elements << "..." if size > 5
  "#<Rover::Vector [#{elements.join(", ")}]>"
end

#last(n = 1) ⇒ Object



244
245
246
# File 'lib/rover/vector.rb', line 244

def last(n = 1)
  Vector.new(@data[-n..-1])
end

#map(&block) ⇒ Object



159
160
161
162
163
# File 'lib/rover/vector.rb', line 159

def map(&block)
  mapped = @data.map(&block)
  mapped = mapped.to_a if mapped.is_a?(Numo::RObject) # re-evaluate cast
  Vector.new(mapped)
end

#maxObject



190
191
192
# File 'lib/rover/vector.rb', line 190

def max
  @data.max
end

#meanObject



198
199
200
201
202
# File 'lib/rover/vector.rb', line 198

def mean
  # currently only floats have mean in Numo
  # https://github.com/ruby-numo/numo-narray/issues/79
  @data.cast_to(Numo::DFloat).mean
end

#medianObject



204
205
206
207
208
# File 'lib/rover/vector.rb', line 204

def median
  # need to cast to get correct result
  # https://github.com/ruby-numo/numo-narray/issues/165
  @data.cast_to(Numo::DFloat).median
end

#minObject



194
195
196
# File 'lib/rover/vector.rb', line 194

def min
  @data.min
end

#missingObject



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rover/vector.rb', line 57

def missing
  bit =
    if @data.is_a?(Numo::RObject)
      Numo::Bit.cast(@data.map(&:nil?))
    elsif @data.respond_to?(:isnan)
      @data.isnan
    else
      Numo::Bit.new(size).fill(0)
    end

  Vector.new(bit)
end

#one_hot(drop: false, prefix: nil) ⇒ Object

Raises:

  • (ArgumentError)


276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/rover/vector.rb', line 276

def one_hot(drop: false, prefix: nil)
  raise ArgumentError, "All elements must be strings" unless all? { |vi| vi.is_a?(String) }

  new_vectors = {}
  # maybe sort values first
  values = uniq.to_a
  values.shift if drop
  values.each do |v2|
    # TODO use types
    new_vectors["#{prefix}#{v2}"] = (self == v2).to_numo.cast_to(Numo::Int64)
  end
  DataFrame.new(new_vectors)
end

#percentile(q) ⇒ Object



210
211
212
# File 'lib/rover/vector.rb', line 210

def percentile(q)
  @data.percentile(q)
end

#sizeObject Also known as: length, count



47
48
49
# File 'lib/rover/vector.rb', line 47

def size
  @data.size
end

#sortObject



174
175
176
# File 'lib/rover/vector.rb', line 174

def sort
  Vector.new(@data.respond_to?(:sort) ? @data.sort : @data.to_a.sort)
end

#stdObject

uses Bessel’s correction for now since that’s all Numo supports



219
220
221
# File 'lib/rover/vector.rb', line 219

def std
  @data.cast_to(Numo::DFloat).stddev
end

#sumObject



214
215
216
# File 'lib/rover/vector.rb', line 214

def sum
  @data.sum
end

#tail(n = 5) ⇒ Object



271
272
273
274
# File 'lib/rover/vector.rb', line 271

def tail(n = 5)
  n += size if n < 0
  last(n)
end

#take(n) ⇒ Object

Raises:

  • (ArgumentError)


248
249
250
251
# File 'lib/rover/vector.rb', line 248

def take(n)
  raise ArgumentError, "attempt to take negative size" if n < 0
  first(n)
end

#tallyObject



165
166
167
168
169
170
171
172
# File 'lib/rover/vector.rb', line 165

def tally
  result = Hash.new(0)
  @data.each do |v|
    result[v] += 1
  end
  result.default = nil
  result
end

#to(type) ⇒ Object



33
34
35
# File 'lib/rover/vector.rb', line 33

def to(type)
  Vector.new(self, type: type)
end

#to_aObject



41
42
43
44
45
# File 'lib/rover/vector.rb', line 41

def to_a
  a = @data.to_a
  a.map! { |v| !v.zero? } if @data.is_a?(Numo::Bit)
  a
end

#to_htmlObject

for IRuby



299
300
301
302
# File 'lib/rover/vector.rb', line 299

def to_html
  require "iruby"
  IRuby::HTML.table(to_a)
end

#to_numoObject



37
38
39
# File 'lib/rover/vector.rb', line 37

def to_numo
  @data
end

#typeObject



29
30
31
# File 'lib/rover/vector.rb', line 29

def type
  TYPE_CAST_MAPPING.find { |_, v| @data.is_a?(v) }[0]
end

#uniqObject



53
54
55
# File 'lib/rover/vector.rb', line 53

def uniq
  Vector.new(@data.to_a.uniq)
end

#varObject

uses Bessel’s correction for now since that’s all Numo supports



224
225
226
# File 'lib/rover/vector.rb', line 224

def var
  @data.cast_to(Numo::DFloat).var
end