计算Ruby中的第95百分位数?

时间:2012-08-02 19:57:52

标签: ruby ruby-on-rails-3 algorithm math

此处的问题似乎没有帮助:Calculating Percentiles (Ruby)

我想从一组数字中计算出第95百分位数(或者实际上,任何其他所需的百分位数)。最终,这将在Rails中应用,以计算大量记录的分布。

但是,如果我可以确定如何从一组数字中准确地确定给定的百分位数,我可以从那里开始。

坦率地说,我很惊讶我找不到某种具有这种功能的宝石 - 我还没有找到它。

非常感谢帮助。

4 个答案:

答案 0 :(得分:24)

如果要复制Excel PERCENTILE功能,请尝试以下操作:

def percentile(values, percentile)
    values_sorted = values.sort
    k = (percentile*(values_sorted.length-1)+1).floor - 1
    f = (percentile*(values_sorted.length-1)+1).modulo(1)

    return values_sorted[k] + (f * (values_sorted[k+1] - values_sorted[k]))
end

values = [1, 2, 3, 4]
p = 0.95
puts percentile(values, p)
#=> 3.85

该公式基于QUARTILE方法,该方法实际上只是一个特定的百分位数 - http://support.microsoft.com/default.aspx?scid=kb;en-us;Q103493

答案 1 :(得分:9)

如果您对现有的宝石感兴趣,那么descriptive_statistics宝石是迄今为止percentile函数找到的最佳宝石。

IRB会议

> require 'descriptive_statistics'
=> true
irb(main):009:0> data = [1, 2, 3, 4]
=> [1, 2, 3, 4]
irb(main):010:0> data.percentile(95)
=> 3.8499999999999996
irb(main):011:0> data.percentile(95).round(2)
=> 3.85

宝石的很大一部分是它描述“我想要95%的数据”的优雅方式。

答案 2 :(得分:6)

基于项目数

的百分位数
a = [1,2,3,4,5,6,10,11,12,13,14,15,20,30,40,50,60,61,91,99,120]

def percentile_by_count(array,percentile)
  count = (array.length * (1.0-percentile)).floor
  array.sort[-count..-1]
end

# 80th percentile (21 items*80% == 16.8 items are below; pick the top 4)
p percentile_by_count(a,0.8) #=> [61, 91, 99, 120]

基于值范围

的百分位数
def percentile_by_value(array,percentile)
  min, max = array.minmax
  range = max - min
  min_value = (max-min)*percentile + min
  array.select{ |v| v >= min_value }
end

# 80th percentile (119 * 80% = 95.2; pick values above this)
p percentile_by_value(a,0.8) #=> [99, 120]

有趣的是,Excel的PERCENTILE函数返回60作为第80个百分点的第一个值。如果您想要这个结果 - 如果您希望包含一个落在限制尖端的项目 - 那么请将上面的.floor更改为.ceil

答案 3 :(得分:0)

这是我在自己的统计库中开发的方法:

def quantiles(data, probs=[0.25, 0.50, 0.75])
  values = data.sort

  probs.map do |prob|
    h = 1 + (values.count - 1) * prob
    mod = h % 1
    (1 - mod) * values[h.floor - 1] + (mod) * values[h.ceil - 1]
  end
end

如果只需要一个分位数,请执行quantiles(data, [0.95])

相关问题