My code is based on the methods described here and here.
def fraction?(number)
number - number.truncate
end
def percentile(param_array, percentage)
another_array = param_array.to_a.sort
r = percentage.to_f * (param_array.size.to_f - 1) + 1
if r <= 1 then return another_array[0]
elsif r >= another_array.size then return another_array[another_array.size - 1]
end
ir = r.truncate
another_array[ir] + fraction?((another_array[ir].to_f - another_array[ir - 1].to_f).abs)
end
Example usage:
test_array = [95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.061, 95.1591, 95.1195,
95.1065, 95.0925, 95.199, 95.1682]
test_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
test_values.each do |value|
puts value.to_s + ": " + percentile(test_array, value).to_s
end
Output:
0.0: 95.061
0.1: 95.1205
0.2: 95.1325
0.3: 95.1689
0.4: 95.1692
0.5: 95.1615
0.6: 95.1773
0.7: 95.1862
0.8: 95.2102
0.9: 95.1981
1.0: 95.199
The problem here is that the 80th percentile is higher than the 90th and the 100th. However, as far as I can tell my implementation is as described, and it returns the right answer for the example given (0.9).
Is there an error in my code I'm not seeing? Or is there a better way to do this?