Skip to content

Instantly share code, notes, and snippets.

@bhb
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bhb/c8edde45a0be12617956 to your computer and use it in GitHub Desktop.
Save bhb/c8edde45a0be12617956 to your computer and use it in GitHub Desktop.
Compute stats for array of numbers
def percentile(arr, pcent)
sorted = arr.sort
# http://en.wikipedia.org/wiki/Percentile#Linear_interpolation_between_closest_ranks
percent_ranks = (1..arr.length).map { |i| (100.0 / sorted.length) * ( i - 0.5) }
if pcent < percent_ranks.first
sorted[0]
elsif pcent > percent_ranks.last
sorted.last
else
idx = percent_ranks.find_index { |rank| rank == pcent }
return sorted[idx] if idx != nil
idx = rank_at = nil
percent_ranks.each_with_index do |rank, i|
if rank < pcent && pcent < percent_ranks[i+1]
idx = i
rank_at = rank
end
end
sorted[idx] + (arr.length * (pcent-rank_at).to_f/100 * (sorted[idx+1] - sorted[idx]))
end
end
def stats(arr)
arr = arr.clone.extend(Stats)
lowest = arr.min
highest = arr.max
total = arr.inject(:+)
len = arr.length
average = total.to_f / len # to_f so we don't get an integer result
sorted = arr.sort
variance = (arr.inject(0) {|accum, i| accum + (i-average)**2 }.to_f/(len))
std_dev = Math.sqrt(variance)
median = len % 2 == 1 ? sorted[len/2] : (sorted[len/2 - 1] + sorted[len/2]).to_f / 2
{
:min => lowest,
:max => highest,
:avg => average,
:std_dev => std_dev,
:med => median,
:pct_50 => percentile(arr, 50),
:pct_90 => percentile(arr, 90)
}.tap do |stats|
if (stats[:med]-stats[:pct_50]).abs > 0.000001
raise "med was #{stats[:med].inspect} but 50% percenile was #{stats[:pct_50].inspect} for #{arr.inspect}}"
end
end
end
module Stats
def sum
self.inject(0){|accum, i| accum + i }
end
def mean
self.sum/self.length.to_f
end
def sample_variance
m = self.mean
sum = self.inject(0){|accum, i| accum +(i-m)**2 }
sum/(self.length - 1).to_f
end
def standard_deviation
return Math.sqrt(self.sample_variance)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment