I wrote a zscore algorithm in Ruby that runs fine, but is incredibly slow when I have 8000+ entries to score. Can anyone help me figure out a way to improve my code, please?
module Enumerable
def mean
reduce(:+).to_f / length
end
def sample_variance
sum = inject(0){ |acc, i| acc + (i - mean)**2 }
1 / length.to_f * sum
end
def standard_deviation
Math.sqrt(sample_variance)
end
def zscore
if standard_deviation.zero?
Array.new(length, 0)
else
collect { |v| (v - mean) / standard_deviation }
end
end
end
The float is giving every score an accuracy of up to 17 decimal places. Would making it only 8 decimal places speed things up?
EDIT: Here is an updated version of the algorithm given the advice received in this thread.
class Array
def mean(len=self.length)
reduce(:+).to_f / len
end
def sample_variance
len = length
m = mean(len)
sum = reduce { |acc, i| acc + (i - m)**2 }
sum.to_f / len
end
def standard_deviation
Math.sqrt(sample_variance)
end
def zscore
stdev = standard_deviation
m = mean
stdev.zero? ? Array.new(length, 0) : collect { |v| (v - m) / stdev }
end
end
sum / (length + 1.0)
. \$\endgroup\$sum/(length + 1.0)
for sample variance? Thanks! Also, this is a population variance as I am running it on all records. \$\endgroup\$sum.to_f / len
reads better than1 / len.to_f * sum
. \$\endgroup\$