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_all?, #_nuggets_original_any?, #_nuggets_original_max, #_nuggets_original_max_by, #_nuggets_original_min, #_nuggets_original_min_by, #_nuggets_original_minmax, #_nuggets_original_minmax_by, #agrep, #all?, #any?, #max, #max_by, #min, #min_by, #minmax, #minmax_by

Constructor Details

#initialize(*ys) ⇒ IncrementalLinearRegression



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

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

Instance Method Details

#<<(y) ⇒ Object



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

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

#add(*ys) ⇒ Object



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

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

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



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

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

#clearObject



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

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

#eachObject



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

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

#interceptObject



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

def intercept
  at(0)
end

#push(x, y) ⇒ Object



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

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



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

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

#to_a(range = nil) ⇒ Object



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

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

#to_sObject



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

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