Class: Daru::Vector

Inherits:
Object
  • Object
show all
Includes:
Maths::Arithmetic::Vector, Maths::Statistics::Vector, Plotting::Vector, Enumerable
Defined in:
lib/daru/vector.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Plotting::Vector

#plot

Methods included from Maths::Statistics::Vector

#average_deviation_population, #coefficient_of_variation, #count, #frequencies, #has_missing_data?, #kurtosis, #max, #mean, #median, #median_absolute_deviation, #min, #mode, #percentile, #product, #proportion, #proportions, #range, #ranked, #recode!, #skew, #standard_deviation_population, #standard_deviation_sample, #standard_error, #sum, #sum_of_squared_deviation, #sum_of_squares, #variance_population, #variance_sample

Methods included from Maths::Arithmetic::Vector

#%, #*, #**, #+, #-, #/, #exp, #round, #sqrt

Constructor Details

#initialize(source, opts = {}) ⇒ Vector

Create a Vector object.

Arguments

numeric index will be created if not supplied in the options. Specifying more index elements than actual values in source will insert nil into the surplus index elements. When a Hash is specified, the keys of the Hash are taken as the index elements and the corresponding values as the values that populate the vector.

Options

  • :name - Name of the vector

  • :index - Index of the vector

Usage

vecarr = Daru::Vector.new [1,2,3,4], index: [:a, :e, :i, :o]
vechsh = Daru::Vector.new({a: 1, e: 2, i: 3, o: 4})

Parameters:

  • source (Array, Hash)
    • Supply elements in the form of an Array or a Hash. If Array, a



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/daru/vector.rb', line 57

def initialize source, opts={}
  index = nil
  if source.is_a?(Hash)
    index  = source.keys
    source = source.values
  else
    index  = opts[:index]
    source = source || []
  end
  name   = opts[:name]
  @dtype = opts[:dtype] || Array

  set_name name

  @vector = 
  case
  when @dtype == Array
    Daru::Accessors::ArrayWrapper.new source.dup, self
  when @dtype == NMatrix
    Daru::Accessors::NMatrixWrapper.new source.dup, self
  when @dtype == MDArray
    Daru::Accessors::MDArrayWrapper.new source.dup
  when @dtype == Range, Matrix
    Daru::Accessors::ArrayWrapper.new source.to_a.dup, self
  end

  if index.nil?
    @index = Daru::Index.new @vector.size  
  else
    @index = index.to_index
  end
  # TODO: Will need work for NMatrix/MDArray
  if @index.size > @vector.size
    self.coerce Array # NM with nils seg faults
    (@index.size - @vector.size).times { @vector << nil }
  elsif @index.size < @vector.size
    raise IndexError, "Expected index size >= vector size"
  end

  set_size
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



333
334
335
336
337
338
339
340
341
# File 'lib/daru/vector.rb', line 333

def method_missing(name, *args, &block)
  if name.match(/(.+)\=/)
    self[name] = args[0]
  elsif has_index?(name)
    self[name]
  else
    super(name, *args, &block)
  end
end

Instance Attribute Details

#dtypeObject (readonly)

Returns the value of attribute dtype.



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

def dtype
  @dtype
end

#indexObject (readonly)

Returns the value of attribute index.



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

def index
  @index
end

#nameObject (readonly)

Returns the value of attribute name.



32
33
34
# File 'lib/daru/vector.rb', line 32

def name
  @name
end

#sizeObject (readonly)

Returns the value of attribute size.



34
35
36
# File 'lib/daru/vector.rb', line 34

def size
  @size
end

Instance Method Details

#<<(element) ⇒ Object



153
154
155
# File 'lib/daru/vector.rb', line 153

def << element
  concat element
end

#==(other) ⇒ Object

Two vectors are equal if the have the exact same index values corresponding with the exact same elements. Name is ignored.



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/daru/vector.rb', line 141

def == other
  case other
  when Daru::Vector
    @index == other.index and @size == other.size and
    @index.all? do |index|
      self[index] == other[index]
    end
  else
    # TODO: Compare against some other obj (string, number, etc.)
  end
end

#[](index, *indexes) ⇒ Object

Get one or more elements with specified index.

Usage

v[:one, :two] # => Daru::Vector with indexes :one and :two
v[:one]       # => Single element


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/daru/vector.rb', line 104

def [](index, *indexes)
  if indexes.empty?
    case index
    when Range
      # range into vector
      # 
    else
      if @index.include? index
        @vector[@index[index]]
      elsif index.is_a?(Numeric)
        @vector[index]
      else
        return nil
      end
    end
  else
    indexes.unshift index

    Daru::Vector.new indexes.map { |index| @vector[@index[index]] },name: @name, 
      index: indexes
  end
end

#[]=(index, value) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/daru/vector.rb', line 127

def []=(index, value)
  @vector = @vector.coerce(Array) if value.nil?

  if @index.include? index
    @vector[@index[index]] = value
  else
    @vector[index] = value
  end

  set_size
end

#coerce(dtype) ⇒ Object



185
186
187
188
189
190
191
192
193
194
# File 'lib/daru/vector.rb', line 185

def coerce dtype
  begin
    @vector = @vector.coerce @dtype
    @dtype  = dtype
  rescue StandardError => e
    puts "Cannot convert to #{dtype} because of data type mismatch. #{e}"
  end

  self
end

#concat(element, index = nil) ⇒ Object

Append an element to the vector by specifying the element and index

Raises:

  • (IndexError)


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/daru/vector.rb', line 166

def concat element, index=nil
  raise IndexError, "Expected new unique index" if @index.include? index

  if index.nil? and @index.index_class == Integer
    @index = Daru::Index.new @size+1
    index  = @size
  else
    begin
      @index = @index.re_index(@index + index)
    rescue Exception => e
      raise e, "Expected valid index."
    end
  end

  @vector[@index[index]] = element

  set_size
end

#daru_vector(*name) ⇒ Object Also known as: dv



327
328
329
# File 'lib/daru/vector.rb', line 327

def daru_vector *name
  self
end

#delete(element) ⇒ Object

Delete an element by value



197
198
199
# File 'lib/daru/vector.rb', line 197

def delete element
  self.delete_at index_of(element)      
end

#delete_at(index) ⇒ Object

Delete element by index



202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/daru/vector.rb', line 202

def delete_at index
  idx = named_index_for index
  @vector.delete_at @index[idx]

  if @index.index_class == Integer
    @index = Daru::Index.new @size-1
  else
    @index = (@index.to_a - [idx]).to_index
  end

  set_size
end

#dupObject

Duplicate elements and indexes



323
324
325
# File 'lib/daru/vector.rb', line 323

def dup 
  Daru::Vector.new @vector.dup, name: @name, index: @index.dup
end

#each(&block) ⇒ Object



16
17
18
# File 'lib/daru/vector.rb', line 16

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

#has_index?(index) ⇒ Boolean

Returns true if an index exists

Returns:

  • (Boolean)


242
243
244
# File 'lib/daru/vector.rb', line 242

def has_index? index
  @index.include? index
end

#index_of(element) ⇒ Object

Get index of element



216
217
218
# File 'lib/daru/vector.rb', line 216

def index_of element
  @index.key @vector.index(element)
end

#inspect(spacing = 10, threshold = 15) ⇒ Object

Over rides original inspect for pretty printing in irb



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/daru/vector.rb', line 286

def inspect spacing=10, threshold=15
  longest = [@name.to_s.size,
             @index.to_a.map(&:to_s).map(&:size).max, 
             @vector    .map(&:to_s).map(&:size).max,
             'nil'.size].max

  content   = ""
  longest   = spacing if longest > spacing
  name      = @name || 'nil'
  formatter = "\n%#{longest}.#{longest}s %#{longest}.#{longest}s"
  content  += "\n#<" + self.class.to_s + ":" + self.object_id.to_s + " @name = " + name.to_s + " @size = " + size.to_s + " >"

  content += sprintf formatter, "", name
  @index.each_with_index do |index, num|
    content += sprintf formatter, index.to_s, (self[index] || 'nil').to_s
    if num > threshold
      content += sprintf formatter, '...', '...'
      break
    end
  end
  content += "\n"

  content
end

#is_valid?(value) ⇒ Boolean

end end

Returns:

  • (Boolean)


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

def is_valid? value
  !self[index_of(value)].nil?
end

#map(&block) ⇒ Object Also known as: recode



26
27
28
# File 'lib/daru/vector.rb', line 26

def map(&block)
  Daru::Vector.new @vector.map(&block), name: @name, index: @index, dtype: @dtype
end

#map!(&block) ⇒ Object



20
21
22
23
24
# File 'lib/daru/vector.rb', line 20

def map!(&block)
  @vector.map!(&block)

  self
end

#push(element) ⇒ Object



157
158
159
# File 'lib/daru/vector.rb', line 157

def push element
  concat element  
end

#re_index(new_index) ⇒ Object



161
162
163
# File 'lib/daru/vector.rb', line 161

def re_index new_index
  
end

#rename(new_name) ⇒ Object

Give the vector a new name



318
319
320
# File 'lib/daru/vector.rb', line 318

def rename new_name
  @name = new_name.to_sym
end

#to_aObject

Return an array



255
256
257
# File 'lib/daru/vector.rb', line 255

def to_a
  @vector.to_a
end

#to_hashObject

Convert to hash. Hash keys are indexes and values are the correspoding elements



247
248
249
250
251
252
# File 'lib/daru/vector.rb', line 247

def to_hash
  @index.inject({}) do |hsh, index|
    hsh[index] = self[index]
    hsh
  end
end

#to_html(threshold = 30) ⇒ Object

Convert to html for iruby



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/daru/vector.rb', line 265

def to_html threshold=30
  name = @name || 'nil'
  html = '<table>' + '<tr><th> </th><th>' + name.to_s + '</th></tr>'
  @index.each_with_index do |index, num|
    html += '<tr><td>' + index.to_s + '</td>' + '<td>' + self[index].to_s + '</td></tr>'

    if num > threshold
      html += '<tr><td>...</td><td>...</td></tr>'
      break
    end
  end
  html += '</table>'

  html
end

#to_json(*args) ⇒ Object

Convert the hash from to_hash to json



260
261
262
# File 'lib/daru/vector.rb', line 260

def to_json *args 
  self.to_hash.to_json
end

#to_sObject



281
282
283
# File 'lib/daru/vector.rb', line 281

def to_s
  to_html
end

#uniqObject

Keep only unique elements of the vector alongwith their indexes.



221
222
223
224
225
226
227
228
229
# File 'lib/daru/vector.rb', line 221

def uniq
  uniq_vector = @vector.uniq
  new_index   = uniq_vector.inject([]) do |acc, element|  
    acc << index_of(element) 
    acc
  end

  Daru::Vector.new uniq_vector, name: @name, index: new_index, dtype: @dtype
end