在Ruby中如何计算95百分位数?

26

这里的问题似乎没有帮助:计算百分位数(Ruby)

我想从数字数组中计算第95个百分位数(或者任何其他想要的百分位数)。最终,这将应用于Rails中,以计算对许多记录的分布。

但是,如果我能确定如何从数字数组中准确地确定给定百分位数,我就可以从那里入手。

坦率地说,我很惊讶自己还没有找到某种宝石(gem)拥有这样的功能 - 我还没有找到。

非常感谢您的帮助。


如何计算百分位数 - http://en.wikipedia.org/wiki/Percentile - AJcodez
@B5Fan74 对于未来的问题,请注意提供确切的定义链接以及提供样本输入和期望输出会很有帮助。 - Phrogz
2
@AJcodez 你是指那篇文章,它说:“没有百分位数的标准定义...”,并且包括三种或更多种计算方法吗? - Phrogz
@Phrogz 你选择你喜欢的吧 :D - AJcodez
@B5Fan74:请看我针对 gem 的特定解决方案的回答。 :) - Dhanu Gurung
显示剩余4条评论
4个回答

41

如果您想复制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方法,该方法实际上只是特定百分位数的计算方式 - https://support.microsoft.com/en-us/office/quartile-inc-function-1bbacc80-5075-42f1-aed6-47d735c4819d


1
可能需要检查values是否包含单个值,以便在这些情况下不会出错。 在我的情况下,我将以下内容添加到第一行: return values.first if values.count == 1 - viktorsmari
请注意,自Excel 2010以来,“QUARTILE”方法已更名为“QUARTILE.INC”。 - khiav reoy

18
如果您对现有的 gem 感兴趣,那么我目前找到的最好的用于百分位函数的 gem 是 descriptive_statistics gem。 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

Gem 的好处之一在于其优雅地描述了“我想要数据的 95 百分位数”。


7

基于项目数量的百分位

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函数返回80%分位数的第一个值为60。如果您想要这个结果——如果您想要处于极限边缘的项目被包括在内——那么请将上面的.floor更改为.ceil


谢谢分享。顺便说一句,你的percentile_by_count有一个错误。[-0..-1]返回整个数组。尝试用你的解决方案计算百分位数0.999,你会看到这个问题。如果你进行这个编辑,它应该可以解决问题。(rem > 0)?sorted [-rem..-1]:[] - Amir

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])。该函数将返回数据的95%分位数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接