计算相对于给定总体的百分位排名

Posted

技术标签:

【中文标题】计算相对于给定总体的百分位排名【英文标题】:Compute percentile rank relative to a given population 【发布时间】:2018-07-04 01:39:48 【问题描述】:

我有“参考人群”(例如,v=np.random.rand(100)),我想计算给定集合的百分位排名(例如,np.array([0.3, 0.5, 0.7]))。

很容易一一计算:

def percentile_rank(x):
    return (v<x).sum() / len(v)
percentile_rank(0.4)
=> 0.4

(实际上,有一个 ootb scipy.stats.percentileofscore - 但它对向量起作用)。

np.vectorize(percentile_rank)(np.array([0.3, 0.5, 0.7]))
=> [ 0.33  0.48  0.71]

这会产生预期的结果,但我觉得应该有一个内置的。

我也可以作弊:

pd.concat([pd.Series([0.3, 0.5, 0.7]),pd.Series(v)],ignore_index=True).rank(pct=True).loc[0:2]

0    0.330097
1    0.485437
2    0.718447

这在两个方面很糟糕:

    我不希望测试数据[0.3, 0.5, 0.7] 成为排名的一部分。 我不想浪费时间计算参考人群的排名。

那么,惯用的方法是什么?

【问题讨论】:

【参考方案1】:

我认为pd.cut可以做到这一点

s=pd.Series([-np.inf,0.3, 0.5, 0.7])
pd.cut(v,s,right=False).value_counts().cumsum()/len(v)
Out[702]: 
[-inf, 0.3)    0.37
[0.3, 0.5)     0.54
[0.5, 0.7)     0.71
dtype: float64

函数的结果

np.vectorize(percentile_rank)(np.array([0.3, 0.5, 0.7]))
Out[696]: array([0.37, 0.54, 0.71])

【讨论】:

这似乎依赖于被排序的测试分数。如果可能的话,我宁愿避免这种情况。【参考方案2】:

你可以使用quantile:

np.random.seed(123)
v=np.random.rand(100)

s = pd.Series(v)
arr = np.array([0.3,0.5,0.7])

s.quantile(arr)

输出:

0.3    0.352177
0.5    0.506130
0.7    0.644875
dtype: float64

【讨论】:

我认为这是我正在寻找的函数的 inverse【参考方案3】:

设置:

In [62]: v=np.random.rand(100)

In [63]: x=np.array([0.3, 0.4, 0.7])

使用 Numpy 广播:

In [64]: (v<x[:,None]).mean(axis=1)
Out[64]: array([ 0.18,  0.28,  0.6 ])

检查:

In [67]: percentile_rank(0.3)
Out[67]: 0.17999999999999999

In [68]: percentile_rank(0.4)
Out[68]: 0.28000000000000003

In [69]: percentile_rank(0.7)
Out[69]: 0.59999999999999998

【讨论】:

vx 都是SeriesDataFrame 中的列)时,我得到ValueError: Lengths must match to compare @sds,在这种情况下你可以这样做:(v.values&lt;x.values[:,None]).mean(axis=1)

以上是关于计算相对于给定总体的百分位排名的主要内容,如果未能解决你的问题,请参考以下文章

如何根据计算获得百分位排名

计算 SQL 中计数相对于类别的百分比

百分位是啥

Elasticsearch - 计算嵌套聚合相对于父存储桶的百分比

计算列中值的百分位数

percentileofscore函数