如何获得numpy/scipy中特定百分位数的索引?

mer*_*011 11 python numpy scipy

我看过这个答案,解释了如何计算特定百分位数的价值,这个答案解释了如何计算与每个元素相对应的百分位数.

  • 使用第一个解决方案,我可以计算值并扫描原始数组以查找索引.

  • 使用第二种解决方案,我可以扫描整个输出数组以查找我正在寻找的百分位数.

但是,如果我想知道对应于特定百分位数的索引(在原始数组中)(或包含最接近该索引的元素的索引),则两者都需要额外的扫描.

是否有更直接或内置的方法来获得对应百分位数的指数?

注意:我的数组没有排序,我希望索引在原始的未排序数组中.

Jai*_*ime 7

这有点令人费解,但你可以得到你想要的东西np.argpartition.让我们采取一个简单的阵列,并将其洗牌:

>>> a = np.arange(10)
>>> np.random.shuffle(a)
>>> a
array([5, 6, 4, 9, 2, 1, 3, 0, 7, 8])
Run Code Online (Sandbox Code Playgroud)

如果你想找到例如分位数0.25的索引,这将对应于idx排序数组的位置项:

>>> idx = 0.25 * (len(a) - 1)
>>> idx
2.25
Run Code Online (Sandbox Code Playgroud)

你需要弄清楚如何将它舍入到int,比如你用最接近的整数:

>>> idx = int(idx + 0.5)
>>> idx
2
Run Code Online (Sandbox Code Playgroud)

如果你现在打电话np.argpartition,这就是你得到的:

>>> np.argpartition(a, idx)
array([7, 5, 4, 3, 2, 1, 6, 0, 8, 9], dtype=int64)
>>> np.argpartition(a, idx)[idx]
4
>>> a[np.argpartition(a, idx)[idx]]
2
Run Code Online (Sandbox Code Playgroud)

很容易检查这两个最后两个表达式分别是.25分位数的索引和值.


Adr*_*ins 5

如果要使用 numpy,还可以使用内置的百分位函数。从 numpy 的 1.9.0 版开始,百分位数具有“插值”选项,可让您选择较低/较高/最近的百分位数值。以下将适用于未排序的数组并找到最近的百分位索引:

import numpy as np
p=70 # my desired percentile, here 70% 
x=np.random.uniform(10,size=(1000))-5.0  # dummy vector

# index of array entry nearest to percentile value
pcen=np.percentile(x,p,interpolation='nearest')
i_near=abs(x-pcen).argmin()
Run Code Online (Sandbox Code Playgroud)

大多数人通常会想要最接近的百分位值,如上所述。但为了完整起见,您还可以轻松指定获取低于或高于规定百分比值的条目:

# Use this to get index of array entry greater than percentile value:
pcen=np.percentile(x,p,interpolation='higher')

# Use this to get index of array entry smaller than percentile value:
pcen=np.percentile(x,p,interpolation='lower')
Run Code Online (Sandbox Code Playgroud)

对于 numpy < v1.9.0 的旧版本,插值选项不可用,因此等效的是:

# Calculate 70th percentile:
pcen=np.percentile(x,p)
i_high=np.asarray([i-pcen if i-pcen>=0 else x.max()-pcen for i in x]).argmin()
i_low=np.asarray([i-pcen if i-pcen<=0 else x.min()-pcen for i in x]).argmax()
i_near=abs(x-pcen).argmin()
Run Code Online (Sandbox Code Playgroud)

总之:

i_high 指向数组条目,它是下一个等于或大于请求百分位数的值。

i_low 指向数组条目,它是下一个等于或小于请求的百分位数的值。

i_near 指向最接近百分位数的数组条目,可以更大或更小。

我的结果是:

pcen
Run Code Online (Sandbox Code Playgroud)

2.3436832738049946

x[i_high]
Run Code Online (Sandbox Code Playgroud)

2.3523077864975441

x[i_low]
Run Code Online (Sandbox Code Playgroud)

2.339987054079617

x[i_near]
Run Code Online (Sandbox Code Playgroud)

2.339987054079617

i_high,i_low,i_near
Run Code Online (Sandbox Code Playgroud)

(876, 368, 368)

即位置 876 是超过 pcen 的最近值,但位置 368 更近,但略小于百分位值。

  • 关于解决方案 `i_near=abs(x-np.percentile(x,p,interpolation='nearest')).argmin()` 执行 `y=np.percentile(x,p,interpolation=') 要快得多最近') i_near=abs(xy).argmin()` 甚至更快一点点做`y=np.percentile(x,p,interpolation='nearest') i_near=np.where(x==A) .argmin()` (2认同)

Gre*_*bet 1

假设数组已排序...除非我误解了您的意思,否则您可以通过取数组的长度 -1,将其乘以分位数,然后四舍五入到最接近的整数来计算百分位数的索引。

round( (len(array) - 1) * (percentile / 100.) )
Run Code Online (Sandbox Code Playgroud)

应该给你最接近该百分位的指数