Class: Nuggets::Array::RegressionMixin::IncrementalLinearRegression

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/nuggets/array/regression_mixin.rb

Overview

Inspired by Incremental Simple Linear Regression in Ruby.

Use #push to add a single {x,y} pair, #add to add a list of y values, and #<< to add a single y value. Whenever a single y value is added, it’s associated with an x value of its position (rank) in the data series.

Call #to_a (or any Enumerable method) to work with the regression points.

Instance Method Summary collapse

Methods included from Enumerable

#_nuggets_original_max, #_nuggets_original_max_by, #_nuggets_original_min, #_nuggets_original_min_by, #_nuggets_original_minmax, #_nuggets_original_minmax_by, #agrep, #max, #max_by, #min, #min_by, #minmax, #minmax_by

Constructor Details

#initialize(*ys) ⇒ IncrementalLinearRegression

Returns a new instance of IncrementalLinearRegression.



80
81
82
83
# File 'lib/nuggets/array/regression_mixin.rb', line 80

def initialize(*ys)
  clear
  add(*ys)
end

Instance Method Details

#<<(y) ⇒ Object



107
108
109
# File 'lib/nuggets/array/regression_mixin.rb', line 107

def <<(y)
  push(@cnt + 1, y)
end

#add(*ys) ⇒ Object



102
103
104
105
# File 'lib/nuggets/array/regression_mixin.rb', line 102

def add(*ys)
  ys.each { |y| self << y }
  self
end

#at(x) ⇒ Object Also known as: []



119
120
121
# File 'lib/nuggets/array/regression_mixin.rb', line 119

def at(x)
  @y + slope * (x - @x)
end

#clearObject



85
86
87
88
89
# File 'lib/nuggets/array/regression_mixin.rb', line 85

def clear
  @x = @y = @xx = @xy = 0.0
  @cnt, @slope = 0, nil
  self
end

#eachObject



125
126
127
128
# File 'lib/nuggets/array/regression_mixin.rb', line 125

def each
  @cnt.times { |i| yield [x = i + 1, at(x)] }
  self
end

#interceptObject



115
116
117
# File 'lib/nuggets/array/regression_mixin.rb', line 115

def intercept
  at(0)
end

#push(x, y) ⇒ Object



91
92
93
94
95
96
97
98
99
100
# File 'lib/nuggets/array/regression_mixin.rb', line 91

def push(x, y)
  cnt, @slope = @cnt += 1, nil

  @x  += (x     - @x)  / cnt
  @y  += (y     - @y)  / cnt
  @xx += (x * x - @xx) / cnt
  @xy += (x * y - @xy) / cnt

  self
end

#slopeObject



111
112
113
# File 'lib/nuggets/array/regression_mixin.rb', line 111

def slope
  @slope ||= @cnt < 2 ? 0 : (@xy - @x * @y) / (@xx - @x * @x)
end

#to_a(range = nil) ⇒ Object



130
131
132
# File 'lib/nuggets/array/regression_mixin.rb', line 130

def to_a(range = nil)
  range ? range.map { |x| [x, at(x)] } : super()
end

#to_sObject



134
135
136
137
138
139
140
141
142
143
# File 'lib/nuggets/array/regression_mixin.rb', line 134

def to_s
  s, i = slope, intercept

  y = s == 0 ? i : begin
    x = s.abs == 1 ? "#{'-' if s < 0}x" : "#{s} * x"
    i == 0 ? x : "#{x} #{i < 0 ? '-' : '+'} #{i.abs}"
  end

  "y := #{y}".gsub(/\.0\b/, '')
end