lib/darkext/statistics.rb in darkhelmet-darkext-0.10.0 vs lib/darkext/statistics.rb in darkhelmet-darkext-0.11.0

- old
+ new

@@ -5,31 +5,34 @@ require 'darkext/symbol' class Array # Finds the mean of the array def mean + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.sum / self.size.to_f end alias :average :mean alias :ave :mean def harmonic_mean + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.size.to_f / self.map { |i| 1 / i.to_f }.sum end alias :h_mean :harmonic_mean def geometric_mean + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.product.root(self.size) end alias :g_mean :geometric_mean # Finds the median of the array def median - return nil if self.size.zero? + raise ArgumentError.new('Array size must be > 0') if self.size.zero? case self.size % 2 when 0 - return self.sort[self.size / (2 - 1), 2].mean + return self.sort[(self.size / 2) - 1, 2].mean when 1 return self.sort[self.size / 2] end end @@ -41,34 +44,40 @@ end end # Finds the mode of the array def mode + raise ArgumentError.new('Array size must be > 0') if self.size.zero? map = self.histogram max = map.values.max map.keys.select { |x| map[x] == max } end # Variance def population_variance + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.sum_of_squares.to_f / (self.size).to_f end def sample_variance + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.sum_of_squares.to_f / (self.size - 1).to_f end # Standard deviation def population_deviation + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.population_variance.abs.sqrt end def sample_deviation + raise ArgumentError.new('Array size must be > 0') if self.size.zero? self.sample_variance.abs.sqrt end def geometric_deviation + raise ArgumentError.new('Array size must be > 0') if self.size.zero? gmean = self.g_mean Math.exp((self.map { |x| (x.ln - gmean.ln).square }.sum.to_f / self.size.to_f).sqrt) end alias :gstddev :geometric_deviation @@ -77,11 +86,14 @@ (1..n).collect { self[rand(self.size)] } end # Generates a confidence interval def ci(opts = { }) + raise ArgumentError.new('Array size must be > 0') if self.size.zero? opts.with_defaults!({ :percent => 0.95, :rho => 1, :type => :center }) + percent = opts[:percent] + rho = opts[:rho] m = self.mean ret = Array.new div = (opts[:type] == :center ? 2 : 1) i = ((Darkext::Statistics::zscore((1 - percent) / div) * rho) / self.size.sqrt).abs @@ -108,10 +120,11 @@ rho = self.sample_deviation.to_f self.map! { |v| (v.to_f - m) / rho } end def sum_of_squares + raise ArgumentError.new('Array size must be > 0') if self.size.zero? m = self.mean self.map { |v| v - m }.squares.sum end # Normalize the array @@ -171,13 +184,14 @@ # * SST (:ss_t) # * R^2 (:r_2) # * R (:r) # * unbiased estimator (:estimator) # * the equation as a lambda (:equation) - # Raises an argument error if the arguments are not the same size + # Raises an argument error if the arguments are not the same size or either is zero def self.least_squares(xs,ys) - raise ArgumentError("Arguments must be of equal size") if xs.size != ys.size + raise ArgumentError.new('Arrays must have size > 0') if xs.size.zero? || ys.size.zero? + raise ArgumentError.new('Arrays must be of equal size') if xs.size != ys.size n = xs.size b_1 = (xs.zip(ys).map(&:product).sum - ((ys.sum * xs.sum)/n))/(xs.map(&:square).sum - (xs.sum.square/n)) b_0 = ys.mean - b_1 * xs.mean equation = lambda { |x| b_0 + b_1 * x } predicted = xs.map(&equation) @@ -185,20 +199,22 @@ ss_e = residuals.map(&:square).sum ss_t = ys.sum_of_squares estimator = ss_e/(n - 2) r_2 = 1 - (ss_e/ss_t) r = r_2.sqrt - reg = {:n => n, + reg = { + :n => n, :b_1 => b_1, :b_0 => b_0, :predicted => predicted, :residuals => residuals, :ss_e => ss_e, :ss_t => ss_t, :estimator => estimator, :equation => equation, :r_2 => r_2, - :r => r} + :r => r + } return reg end end end end