Class: Rover::Vector
- Inherits:
-
Object
- Object
- Rover::Vector
- Defined in:
- lib/rover/vector.rb
Constant Summary collapse
- TYPE_CAST_MAPPING =
if a user never specifies types, the defaults are bool, float64, int64, and object
{ bool: Numo::Bit, float32: Numo::SFloat, float64: Numo::DFloat, int8: Numo::Int8, int16: Numo::Int16, int32: Numo::Int32, int64: Numo::Int64, object: Numo::RObject, uint8: Numo::UInt8, uint16: Numo::UInt16, uint32: Numo::UInt32, uint64: Numo::UInt64, # legacy - must come last float: Numo::DFloat, int: Numo::Int64, uint: Numo::UInt64 }
- NOT_SET =
Object.new
- INTEGER_TYPES =
private
[:int8, :int16, :int32, :int64, :uint8, :uint16, :uint32, :uint64]
Instance Method Summary collapse
- #! ⇒ Object
- #-@ ⇒ Object
- #[](v) ⇒ Object
- #[]=(k, v) ⇒ Object
- #abs ⇒ Object
- #all? ⇒ Boolean
- #any? ⇒ Boolean
- #ceil(ndigits = 0) ⇒ Object
- #clamp(min, max) ⇒ Object
- #clamp!(min, max) ⇒ Object
- #crosstab(other) ⇒ Object
-
#diff ⇒ Object
keep same number of rows as original to make it easy to add to original data frame.
- #each(&block) ⇒ Object
- #each_with_index(&block) ⇒ Object
- #empty? ⇒ Boolean
- #first(n = NOT_SET) ⇒ Object
- #floor(ndigits = 0) ⇒ Object
- #frexp ⇒ Object
- #head(n = 5) ⇒ Object
- #hypot(y) ⇒ Object
- #in?(values) ⇒ Boolean
- #include?(value) ⇒ Boolean
-
#initialize(data, type: nil) ⇒ Vector
constructor
A new instance of Vector.
-
#inspect ⇒ Object
(also: #to_s)
TODO add type and size?.
- #last(n = NOT_SET) ⇒ Object
- #ldexp(exponent) ⇒ Object
- #ln ⇒ Object
- #log(base = NOT_SET) ⇒ Object
- #map(&block) ⇒ Object
- #map!(&block) ⇒ Object
- #max ⇒ Object
- #mean ⇒ Object
- #median ⇒ Object
- #min ⇒ Object
- #missing ⇒ Object
- #numeric? ⇒ Boolean
- #one_hot(drop: false, prefix: nil) ⇒ Object
- #percentile(q) ⇒ Object
- #reject(&block) ⇒ Object
- #round(ndigits = 0) ⇒ Object
- #select(&block) ⇒ Object
- #size ⇒ Object (also: #length, #count)
- #sort ⇒ Object
-
#std ⇒ Object
uses Bessel's correction for now since that's all Numo supports.
- #sum ⇒ Object
- #tail(n = 5) ⇒ Object
- #take(n) ⇒ Object
-
#tally ⇒ Object
use Ruby tally for performance.
- #to(type) ⇒ Object
- #to!(type) ⇒ Object
- #to_a ⇒ Object
-
#to_html ⇒ Object
for IRuby.
- #to_numo ⇒ Object
- #type ⇒ Object
- #uniq ⇒ Object
-
#var ⇒ Object
uses Bessel's correction for now since that's all Numo supports.
- #zip(other, &block) ⇒ Object
Constructor Details
#initialize(data, type: nil) ⇒ Vector
Returns a new instance of Vector.
29 30 31 32 |
# File 'lib/rover/vector.rb', line 29 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
161 162 163 164 165 166 167 |
# File 'lib/rover/vector.rb', line 161 def ! if @data.is_a?(Numo::Bit) Vector.new(@data.eq(0)) else raise "Not implemented yet" end end |
#-@ ⇒ Object
169 170 171 |
# File 'lib/rover/vector.rb', line 169 def -@ self * -1 end |
#[](v) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rover/vector.rb', line 91 def [](v) if v.is_a?(Vector) case v.type when :bool Vector.new(v.to_numo.mask(@data)) when *INTEGER_TYPES Vector.new(@data[v.to_numo]) else raise ArgumentError, "Unsupported selector" end elsif v.is_a?(Numeric) @data[v] else Vector.new(@data[v]) end end |
#[]=(k, v) ⇒ Object
108 109 110 111 |
# File 'lib/rover/vector.rb', line 108 def []=(k, v) k = k.to_numo if k.is_a?(Vector) @data[k] = v end |
#all? ⇒ Boolean
318 319 320 |
# File 'lib/rover/vector.rb', line 318 def all?(...) to_a.all?(...) end |
#any? ⇒ Boolean
322 323 324 |
# File 'lib/rover/vector.rb', line 322 def any?(...) to_a.any?(...) end |
#ceil(ndigits = 0) ⇒ Object
223 224 225 226 227 228 229 |
# File 'lib/rover/vector.rb', line 223 def ceil(ndigits = 0) if ndigits == 0 Vector.new(@data.ceil) else Vector.new(@data.map { |v| v.ceil(ndigits) }) end end |
#clamp(min, max) ⇒ Object
178 179 180 |
# File 'lib/rover/vector.rb', line 178 def clamp(min, max) dup.clamp!(min, max) end |
#clamp!(min, max) ⇒ Object
173 174 175 176 |
# File 'lib/rover/vector.rb', line 173 def clamp!(min, max) @data = @data.clip(min, max) self end |
#crosstab(other) ⇒ Object
363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/rover/vector.rb', line 363 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 |
#diff ⇒ Object
keep same number of rows as original to make it easy to add to original data frame
86 87 88 89 |
# File 'lib/rover/vector.rb', line 86 def diff diff = @data.cast_to(Numo::DFloat).diff Vector.new(diff.insert(0, Float::NAN)) end |
#each(&block) ⇒ Object
273 274 275 |
# File 'lib/rover/vector.rb', line 273 def each(&block) @data.each(&block) end |
#each_with_index(&block) ⇒ Object
277 278 279 |
# File 'lib/rover/vector.rb', line 277 def each_with_index(&block) @data.each_with_index(&block) end |
#empty? ⇒ Boolean
326 327 328 |
# File 'lib/rover/vector.rb', line 326 def empty? size == 0 end |
#first(n = NOT_SET) ⇒ Object
338 339 340 341 342 343 344 345 346 |
# File 'lib/rover/vector.rb', line 338 def first(n = NOT_SET) if n == NOT_SET @data[0] elsif n >= size Vector.new(@data) else Vector.new(@data[0...n]) end end |
#floor(ndigits = 0) ⇒ Object
231 232 233 234 235 236 237 |
# File 'lib/rover/vector.rb', line 231 def floor(ndigits = 0) if ndigits == 0 Vector.new(@data.floor) else Vector.new(@data.map { |v| v.floor(ndigits) }) end end |
#frexp ⇒ Object
263 264 265 266 |
# File 'lib/rover/vector.rb', line 263 def frexp fraction, exponent = Numo::NMath.frexp(@data) [Vector.new(fraction), Vector.new(exponent)] end |
#head(n = 5) ⇒ Object
376 377 378 379 |
# File 'lib/rover/vector.rb', line 376 def head(n = 5) n += size if n < 0 first(n) end |
#hypot(y) ⇒ Object
258 259 260 261 |
# File 'lib/rover/vector.rb', line 258 def hypot(y) y = y.to_numo if y.is_a?(Rover::Vector) Vector.new(Numo::NMath.hypot(@data, y)) end |
#in?(values) ⇒ Boolean
147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/rover/vector.rb', line 147 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 |
#include?(value) ⇒ Boolean
330 331 332 |
# File 'lib/rover/vector.rb', line 330 def include?(value) to_a.include?(value) end |
#inspect ⇒ Object Also known as: to_s
TODO add type and size?
401 402 403 404 405 |
# File 'lib/rover/vector.rb', line 401 def inspect elements = first(5).to_a.map(&:inspect) elements << "..." if size > 5 "#<Rover::Vector [#{elements.join(", ")}]>" end |
#last(n = NOT_SET) ⇒ Object
348 349 350 351 352 353 354 355 356 |
# File 'lib/rover/vector.rb', line 348 def last(n = NOT_SET) if n == NOT_SET @data[-1] elsif n >= size Vector.new(@data) else Vector.new(@data[-n..-1]) end end |
#ldexp(exponent) ⇒ Object
268 269 270 271 |
# File 'lib/rover/vector.rb', line 268 def ldexp(exponent) exponent = exponent.to_numo if exponent.is_a?(Rover::Vector) Vector.new(Numo::NMath.ldexp(@data, exponent)) end |
#ln ⇒ Object
254 255 256 |
# File 'lib/rover/vector.rb', line 254 def ln log end |
#log(base = NOT_SET) ⇒ Object
245 246 247 248 249 250 251 252 |
# File 'lib/rover/vector.rb', line 245 def log(base = NOT_SET) if base == NOT_SET Vector.new(Numo::NMath.log(@data)) else type = self.type == :float32 ? :float32 : :float64 Vector.new(@data.to_a.map { |v| Math.log(v, base) }, type: type) end end |
#map(&block) ⇒ Object
182 183 184 185 186 187 |
# File 'lib/rover/vector.rb', line 182 def map(&block) # convert to Ruby first to cast properly # https://github.com/ruby-numo/numo-narray/issues/181 # numo-narray-alt has same behavior Vector.new(@data.to_a.map(&block)) end |
#map!(&block) ⇒ Object
189 190 191 192 |
# File 'lib/rover/vector.rb', line 189 def map!(&block) @data = cast_data(@data.to_a.map(&block)) self end |
#max ⇒ Object
281 282 283 |
# File 'lib/rover/vector.rb', line 281 def max @data.max end |
#mean ⇒ Object
289 290 291 |
# File 'lib/rover/vector.rb', line 289 def mean @data.mean end |
#median ⇒ Object
293 294 295 296 297 298 |
# File 'lib/rover/vector.rb', line 293 def median # need to cast to get correct result # https://github.com/ruby-numo/numo-narray/issues/165 # numo-narray-alt has same behavior @data.cast_to(Numo::DFloat).median end |
#min ⇒ Object
285 286 287 |
# File 'lib/rover/vector.rb', line 285 def min @data.min end |
#missing ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/rover/vector.rb', line 71 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 |
#numeric? ⇒ Boolean
57 58 59 |
# File 'lib/rover/vector.rb', line 57 def numeric? ![:object, :bool].include?(type) end |
#one_hot(drop: false, prefix: nil) ⇒ Object
386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/rover/vector.rb', line 386 def one_hot(drop: false, prefix: nil) raise ArgumentError, "All elements must be strings" unless all?(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
300 301 302 |
# File 'lib/rover/vector.rb', line 300 def percentile(q) @data.percentile(q) end |
#reject(&block) ⇒ Object
198 199 200 |
# File 'lib/rover/vector.rb', line 198 def reject(&block) Vector.new(@data.to_a.reject(&block)) end |
#round(ndigits = 0) ⇒ Object
215 216 217 218 219 220 221 |
# File 'lib/rover/vector.rb', line 215 def round(ndigits = 0) if ndigits == 0 Vector.new(@data.round) else Vector.new(@data.map { |v| v.round(ndigits) }) end end |
#select(&block) ⇒ Object
194 195 196 |
# File 'lib/rover/vector.rb', line 194 def select(&block) Vector.new(@data.to_a.select(&block)) end |
#size ⇒ Object Also known as: length, count
61 62 63 |
# File 'lib/rover/vector.rb', line 61 def size @data.size end |
#sort ⇒ Object
207 208 209 |
# File 'lib/rover/vector.rb', line 207 def sort Vector.new(@data.respond_to?(:sort) ? @data.sort : @data.to_a.sort) end |
#std ⇒ Object
uses Bessel's correction for now since that's all Numo supports
309 310 311 |
# File 'lib/rover/vector.rb', line 309 def std @data.cast_to(Numo::DFloat).stddev end |
#sum ⇒ Object
304 305 306 |
# File 'lib/rover/vector.rb', line 304 def sum @data.sum end |
#tail(n = 5) ⇒ Object
381 382 383 384 |
# File 'lib/rover/vector.rb', line 381 def tail(n = 5) n += size if n < 0 last(n) end |
#take(n) ⇒ Object
358 359 360 361 |
# File 'lib/rover/vector.rb', line 358 def take(n) raise ArgumentError, "attempt to take negative size" if n < 0 first(n) end |
#tally ⇒ Object
use Ruby tally for performance
203 204 205 |
# File 'lib/rover/vector.rb', line 203 def tally @data.to_a.tally end |
#to(type) ⇒ Object
38 39 40 |
# File 'lib/rover/vector.rb', line 38 def to(type) dup.to!(type) end |
#to!(type) ⇒ Object
42 43 44 45 |
# File 'lib/rover/vector.rb', line 42 def to!(type) @data = cast_data(@data, type: type) self end |
#to_a ⇒ Object
51 52 53 54 55 |
# File 'lib/rover/vector.rb', line 51 def to_a a = @data.to_a a.map! { |v| !v.zero? } if @data.is_a?(Numo::Bit) a end |
#to_html ⇒ Object
for IRuby
409 410 411 412 413 414 415 416 417 418 |
# File 'lib/rover/vector.rb', line 409 def to_html require "iruby" if size > 7 # pass 8 rows so maxrows is applied IRuby::HTML.table(first(4).to_a + last(4).to_a, maxrows: 7) else IRuby::HTML.table(to_a) end end |
#to_numo ⇒ Object
47 48 49 |
# File 'lib/rover/vector.rb', line 47 def to_numo @data end |
#type ⇒ Object
34 35 36 |
# File 'lib/rover/vector.rb', line 34 def type TYPE_CAST_MAPPING.find { |_, v| @data.is_a?(v) }[0] end |
#var ⇒ Object
uses Bessel's correction for now since that's all Numo supports
314 315 316 |
# File 'lib/rover/vector.rb', line 314 def var @data.cast_to(Numo::DFloat).var end |
#zip(other, &block) ⇒ Object
334 335 336 |
# File 'lib/rover/vector.rb', line 334 def zip(other, &block) to_a.zip(other.to_a, &block) end |