diff --git a/README.md b/README.md index ba45b45..473623c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ To implement ### Regressions ### -- Linear regression +- Linear regression - Multiple linear regression - Pearson's correlation - Spearman correlation diff --git a/lib/stats.rb b/lib/stats.rb index 9114695..ea65b22 100644 --- a/lib/stats.rb +++ b/lib/stats.rb @@ -5,3 +5,4 @@ require 'stats/distribution' require 'stats/significance' require 'stats/assumption' +require 'stats/regression' diff --git a/lib/stats/regression.rb b/lib/stats/regression.rb new file mode 100644 index 0000000..a25ab52 --- /dev/null +++ b/lib/stats/regression.rb @@ -0,0 +1,26 @@ +module Stats + module Regression + class << self + + # Performs linear regression on the supplied data using least + # squares fit. + # + # Returns the results as Hash with keys 'gradient' and 'intercept' which + # map to the gradient and intercept respectively. + def linear_regression(x, y) + return nil if x.length < 2 || y.length < 2 || x.length != y.length + sum_x = x.reduce(&:+) + sum_y = y.reduce(&:+) + sum_xy = x.zip(y).map { |x1, y1| x1 * y1 }.reduce(&:+) + sum_x_squared = x.map { |x1| x1 * x1 }.reduce(&:+) + + gradient = (sum_xy - (sum_x * sum_y).to_f / x.length).to_f / (sum_x_squared - sum_x * sum_x / x.length) + intercept = (sum_y - gradient * sum_x).to_f / x.length + + ['gradient' => gradient, 'intercept' => intercept] + end + end + end +end + + diff --git a/spec/regression_spec.rb b/spec/regression_spec.rb new file mode 100644 index 0000000..3d6c20f --- /dev/null +++ b/spec/regression_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +module Stats + describe Regression do + it "performs linear regression using least squares fit" do + x = [] + y = [1, 2, 3, 4, 5] + Regression.linear_regression(x, y).should == nil + + x = [1, 2, 3, 4, 5] + y = [] + Regression.linear_regression(x, y).should == nil + + x = [1] + y = [1] + Regression.linear_regression(x, y).should == nil + + x = [1, 2, 3, 4, 5] + y = [1, 2, 3, 4, 5, 6] + Regression.linear_regression(x, y).should == nil + + x = [2, 4, 6, 8] + y = [2, 5, 5, 8] + Regression.linear_regression(x, y).should == ['gradient' => 0.9, 'intercept' => 0.5] + + x = [1, 2, 3, 4, 5] + y = [2, 4, 6, 8, 10] + Regression.linear_regression(x, y).should == ['gradient' => 2, 'intercept' => 0] + + x = [0, 1, 2, 3, 4] + y = [3, 6, 7, 8, 11] + Regression.linear_regression(x, y).should == ['gradient' => 1.8, 'intercept' => 3.4] + end + end +end +