Python 百分位计算:我可以将此for循环转换为向量操作吗?
我有一个分数数组作为输入,我想输出一个数组,每个分数都有百分位数。我有意识地没有使用Python 百分位计算:我可以将此for循环转换为向量操作吗?,python,arrays,numpy,Python,Arrays,Numpy,我有一个分数数组作为输入,我想输出一个数组,每个分数都有百分位数。我有意识地没有使用stats.percentileofscore(),因为我正在利用这个机会来学习numpy数据处理和操作 根据输入: math_scores=np.array([51,61,45,72,78,61,84,50,42,57]) 我希望print(分数与百分位数)的输出为: [[51 35] [61 60] [45 15] [72 75] [78 85] [61 60] [84 95] [50 25]
stats.percentileofscore()
,因为我正在利用这个机会来学习numpy数据处理和操作
根据输入:
math_scores=np.array([51,61,45,72,78,61,84,50,42,57])
我希望print(分数与百分位数)
的输出为:
[[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])
数据大小=数学分数.shape
百分位数列=np.0(数据大小,数据类型=int)
对于i,枚举分数(数学分数):
计数=(数学分数<分数).sum()
freq=(数学分数==分数).sum()
百分位坐标[i]=(计数+(0.5*频率))*100/数据大小
分数,百分位数=np.stack((数学分数,百分位数),轴=1)
打印(带有百分比的分数)
这对我来说很好,虽然我确信它不是很有效,因为我才刚刚开始熟悉numpy。
我想知道我是否可以通过使用一些向量运算来避免for循环。
也欢迎提出任何其他改进代码的建议。诚实地定义一个用于百分位计算的函数,然后将其映射到您的数组可能是最佳选择:
math_scores=np.array([51,61,45,72,78,61,84,50,42,57])
def计算百分比(分数,分数):
计数=(分数<分数).sum()
freq=(分数==分数).sum()
返回值(计数+(0.5*freq))*100/len(分数)
输出=np.数组([(数学分数,计算百分位数(数学分数,数学分数))用于数学分数中的数学分数])
我尝试使用
np.vectorize
和其他一些奇特的numpy函数复制该行为,但要么我无法使其工作,要么解决方案过于臃肿。每当我们想要循环相同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.]]
在数组中循环时,需要多次计算每个项目小于或等于特定项目的项目数。它花费了很多时间,实际上任何元素都是O(n),所有元素都是O(n²)。有一个排序版本的分数会很好,然后任何元素都需要O(log(n))时间,所有元素都需要O(nlog(n))时间。这就是
numpy
的searchsorted
方法的设计目的。当然,首先需要对分数进行排序(这也是O(nlog(n)))。这就是我迄今为止所尝试的:
sorted_math_scores = np.sort(math_scores)
count = np.searchsorted(sorted_math_scores, math_scores)
freq = np.searchsorted(sorted_math_scores, math_scores, side='right') - count
percentile_col = (count + (0.5*freq))*100/data_size
顺便说一句,我已经花了很多精力来寻找一种更具体的方法来找到
freq
,但是没有财富。这不是最好的。基于Python的“for”循环速度很慢,numpy是在基于C的“for”循环之上设计的。我看过一个例子,它甚至慢了70倍。很好的建议。我不知道np.less和np.equal。我直接使用了count=(math_scores