找到一个值的百分位数

8
我有一个值数组,例如[1,2,3,4,5],需要找到每个值的百分位数。我期望的输出是[0,25,50,75,100]
我在numpy中搜索了一个可以得到所需结果的API,发现np.percentile却相反。给定一个百分位数,它会使用输入列表作为分布来查找一个值。
是否有API或方法可以实现这一点?谢谢

3
你的数值似乎有误。难道不应该是 [20.0, 40.0, 60.0, 80.0, 100.0] 吗? - Jean-François Fabre
1
那么,就像这样,但是对于每个值都要这样做吗?https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.percentileofscore.html - Caramiriel
@Jean-FrançoisFabre 零百分位应该是1,因为它是列表中的最小值,对吧?而且 np.percentile(range(1,6),0) 返回了 1 - Clock Slave
@Jean-FrançoisFabre使用了@Caramiriel提供的函数,stats.percentileofscore([1, 2, 3, 4, 5], 3)返回60.0,但是np.percentile(range(1,6), 60.0)返回3.4。为什么会有这种差异? - Clock Slave
1
np.percentile(range(0,6), 60.0) 返回3。你的1值不被视为原点,0是原点。或者函数发生了移位。我不是一个numpy专家。scipy和numpy可能使用不同的定义/实现百分位数的方法。如果该函数不能满足您的要求,那就不要使用它。 - Jean-François Fabre
@Jean-FrançoisFabre。好的,谢谢,明白了。 - Clock Slave
6个回答

7
要在给定数据集中获取一个值的百分位数,请使用 scipy 的 percentileofscore
from scipy.stats import percentileofscore

dataset = [1,2,3,4,5]

percentile_of_3 = percentileofscore(dataset, 3)
print(percentile_of_3)

[Output] 60.0

这个输出意味着数据集中小于等于3的值占了60%。 percentileofscore函数的 "kind" 参数可以用来指定百分位数的截止点是否包含在内。例如:

percentile_of_3 = percentileofscore(dataset, 3, kind='strict')
print(percentile_of_3)

[Output] 40.0

这意味着数据集中有40%的值小于3。

如果我们想要一个包含每个值的百分位数的列表,可以使用列表解析:

all_percentiles = [percentileofscore(dataset, value, kind='strict') for value in dataset]

[Output] [0.0, 20.0, 40.0, 60.0, 80.0]

(感谢Cobra的编辑建议!)

2
第二个代码块应该写成:percentile_of_3 = percentileofscore(dataset, 3, kind='strict') - Cobra

2

你应该使用列表推导式,将每个列表值除以 max(lst) -1

lst = [1,2,3,4,5]
max_val = max(lst) -1
lst = [(elem-1)/max_val * 100 for elem in lst]
print(lst)

输出

[0.0, 25.0, 50.0, 75.0, 100.0]

您也可以使用numpy数组来实现这一点。
arr = np.array([1,2,3,4,5])
result = (arr - 1) / (np.max(arr) - 1) * 100

1
使用偏移量使1的值变为0,计算最大值,减去1,对其他值执行同样的操作,在列表推导式中计算百分比。
lst = [1,2,3,4,5]
maxval = max(lst)-1
newlst = [(v-1)*100/maxval for v in lst]

print(newlst)

结果(如果需要整数,请使用//进行除法)

[0.0, 25.0, 50.0, 75.0, 100.0]

1
如果您的输入可能包含任意数字(例如[3, 7, 13, 20]),需要将其映射到0%-100%,则需要找出最小值和最大值,并将值拉伸到0…100:
values = [ 3, 7, 13, 20 ]
min_value = min(values)
max_value = max(values)
for value in values:
  fraction = float(value - min_value) / (max_value - min_value)
  percentage = fraction * 100
  print(value, percentage)

或者作为理解:
percentiles = [ float(value - min_value) / (max_value - min_value) * 100
                for value in values ]

对于大的输入,使用numpy可以加快速度:

import numpy as np

values = np.array([ 3, 7, 13, 20 ])
min_value = values.min()
max_value = values.max()
percentiles = (values - min_value) / (max_value - min_value) * 100

1
我采用维基百科上的百分位数定义,如下所示:

百分位数的一种常见定义是:在由 N 个有序值(从小到大排序)组成的列表中,P 分位数(0 < P ≤ 100)是列表中最小的一个值,使得不超过 P% 的数据严格小于该值,而至少有 P% 的数据小于等于该值。

因此,对于你的数据,答案是:
[20,40,60,80,100]

我假设您没有均匀分布且数字可以重复。您可以使用字典来查找结果:
nbr = [1,1,3,4,5]
sorted_nbr = sorted(nbr)
ans = {x: 100*(1+i)/len(sorted_nbr) for i,x in enumerate(sorted_nbr)}

This yield:

{1: 40.0, 3: 60.0, 4: 80.0, 5: 100.0}

如果您需要列表,则使用:

[ans[x] for x in nbr]

0
你应该使用np.true_divide
x = np.arange(5)
np.true_divide(x, 4)*100
[Output] array([ 0.  ,  25.,  50. ,  75.,  100.  ])

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