You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Numpy实现SciPy percentileofscore的等效功能(含平局处理)

用Numpy实现SciPy percentileofscore的等效功能

问题背景

SciPy的percentileofscore函数可计算数组中每个元素的百分位排名,为减少依赖希望用Numpy内置方法实现,且需保留其默认的平局百分位数平均特性(例如输入[100,100]应返回[50,50]而非[0,100])。但直接使用np.percentile得到的结果完全不符合预期:

import numpy as np
from scipy.stats import percentileofscore

a = np.array([3, 2, 1])
# np.percentile输出:根据给定百分位提取对应分位数,与排名无关
print(np.percentile(a, a))
# >>> array([1.06, 1.04, 1.02])

# percentileofscore输出:每个元素的百分位排名
print(percentileofscore(a, a))
# >>> array([100.        ,  66.66666667,  33.33333333])

关键逻辑差异

np.percentile与percentileofscore是互逆操作:

  • np.percentile(arr, p):根据给定的百分位p,从数组arr中提取对应分位数
  • percentileofscore(arr, x):计算元素x在数组arr中的百分位排名(即有多少百分比的元素小于等于x,平局时取平均)

Numpy实现方案

以下代码完全匹配percentileofscore默认(kind='mean')行为:

import numpy as np

def numpy_percentileofscore(arr, scores):
    sorted_arr = np.sort(arr)
    # 统计小于当前score的元素数量
    count_less = np.searchsorted(sorted_arr, scores, side='left')
    # 统计等于当前score的元素数量
    count_eq = np.searchsorted(sorted_arr, scores, side='right') - count_less
    # 按平局平均规则计算百分位
    return (count_less + 0.5 * count_eq) / len(arr) * 100

# 测试示例
a = np.array([3, 2, 1])
print(numpy_percentileofscore(a, a))
# >>> array([100.        ,  66.66666667,  33.33333333])

b = np.array([100, 100])
print(numpy_percentileofscore(b, b))
# >>> array([50., 50.])

代码解释

  1. 排序数组:对原数组排序,便于后续统计元素位置
  2. 统计小于当前值的元素数:用np.searchsorted(side='left')找到第一个大于等于目标值的索引,该索引即为小于目标值的元素总数
  3. 统计等于当前值的元素数:用side='right'的索引减去side='left'的索引,得到与目标值相等的元素数量
  4. 计算百分位:通过(小于数 + 0.5*等于数)/总数 *100的公式,实现平局时的平均百分位计算,与SciPy默认逻辑完全一致

内容的提问来源于stack exchange,提问作者jbuddy_13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:37:01