Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 百分位计算:我可以将此for循环转换为向量操作吗?_Python_Arrays_Numpy - Fatal编程技术网

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