首页 > 解决方案 > 百分位数计算:我可以将此 for 循环转换为向量运算吗?

问题描述

我有一个分数数组作为输入,我想输出一个数组,每个分数都附有百分位数。而且我有意识地不使用stats.percentileofscore(),因为我正在使用它作为学习 numpy 数据处理和操作的机会。

给定输入:

math_scores = np.array([51, 61, 45, 72, 78, 61, 84, 50, 42, 57])

我希望的输出print(scores_with_percentile)是:

[[51 35]
 [61 60]
 [45 15]
 [72 75]
 [78 85]
 [61 60]
 [84 95]
 [50 25]
 [42  5]
 [57 45]]

计算基于此维基百科页面中的公式

我写了以下代码:

math_scores = np.array([51, 61, 45, 72, 78, 61, 84, 50, 42, 57])
data_size = math_scores.shape
percentile_col = np.zeros(data_size, dtype=int)

for i, score in enumerate(math_scores):
    count = (math_scores < score).sum()
    freq = (math_scores == score).sum()
    percentile_col[i] = (count + (0.5*freq))*100/data_size

scores_with_percentile = np.stack((math_scores, percentile_col), axis=1)
print(scores_with_percentile)

这对我来说很好,但我确信它不是很有效,因为我才开始熟悉 numpy。我想知道是否可以通过使用一些向量操作来避免 for 循环。也欢迎任何其他改进代码的建议。

标签: pythonarraysnumpy

解决方案


每当我们想要遍历同一个 numpy 数组的元素时,我们可以在新轴上创建另一个数组。所以我们可以在二维数组上使用 numpy 的向量化函数。

math_scores = np.array([51, 61, 45, 72, 78, 61, 84, 50, 42, 57])
data_size = math_scores.shape
count = np.less(math_scores, math_scores[:,np.newaxis]).sum(axis=1)
freq = np.equal(math_scores,math_scores[:,np.newaxis]).sum(axis=1)
percentile_col = (count + (0.5*freq))*100/data_size

scores_with_percentile = np.stack((math_scores, percentile_col), axis=1)
print(scores_with_percentile)

[[51. 35.]
 [61. 60.]
 [45. 15.]
 [72. 75.]
 [78. 85.]
 [61. 60.]
 [84. 95.]
 [50. 25.]
 [42.  5.]
 [57. 45.]]

推荐阅读