python - 矢量化 pythonic 方法来获取大于当前元素的元素数

标签 python performance numpy vectorization

我想将数组 b 中的每个条目与其各自的列进行比较,以找出有多少条目(来自该列)大于引用。我的代码看起来慢得令人尴尬,我怀疑这是由于 for 循环而不是矢量操作造成的。

我们可以“向量化”以下代码吗?

import numpy as np

n = 1000
m = 200
b = np.random.rand(n,m)
p = np.zeros((n,m))

for i in range(0,n): #rows
   for j in range(0,m):  # cols
     r = b[i,j]  
     p[i,j] = ( ( b[:,j] > r).sum() ) / (n) 

经过深思熟虑,我认为对每一列进行排序可以使以后的比较更快,从而提高整体运行时间。

经过更多搜索后,我相信我需要按列的百分位数 (http://lagrange.univ-lyon1.fr/docs/scipy/0.17.1/generated/scipy.stats.percentileofscore.html)

最佳答案

只是需要更深入的研究来弄清楚我们可以简单地使用 argsort() 索引沿着每一列在每次迭代中获得大于当前元素的计数。

方法 #1

考虑到该理论,一种解决方案是简单地使用两个 argsort-ing 来获取计数 -

p = len(b)-1-b.argsort(0).argsort(0)

方法 #2

我们可以进一步优化它,因为 argsort 索引是唯一的数字。因此,第二个 argsort 步骤可以使用一些数组赋值 + advanced-indexing,就像这样 -

def count_occ(b):
    n,m = b.shape     
    out = np.zeros((n,m),dtype=int)
    idx = b.argsort(0)
    out[idx, np.arange(m)] = n-1-np.arange(n)[:,None]
    return out

最后,按照两种方法的问题中所述,除以 n


基准测试

对目前发布的所有方法进行计时 -

In [174]: np.random.seed(0)
     ...: n = 1000
     ...: m = 200
     ...: b = np.random.rand(n,m)

In [175]: %timeit (len(b)-1-b.argsort(0).argsort(0))/float(n)
100 loops, best of 3: 17.6 ms per loop

In [176]: %timeit count_occ(b)/float(n)
100 loops, best of 3: 12.1 ms per loop

# @Brad Solomon's soln
In [177]: %timeit np.sum(b > b[:, None], axis=-2) / float(n)
1 loop, best of 3: 349 ms per loop

# @marco romelli's loopy soln
In [178]: %timeit loopy_soln(b)/float(n)
10 loops, best of 3: 139 ms per loop

关于python - 矢量化 pythonic 方法来获取大于当前元素的元素数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49880927/

相关文章:

python - Fork 和 exec 未产生正确的结果

performance - Windows Server 2008 上的 UDP 性能上限

python - 检查 NaT 或 pandas 时间戳

python - 如何从字符串 'long' 创建一个 numpy dtype?

lambda 中的 Python isub

python - 何时使用哪个模糊函数来比较 2 个字符串

python - 使用 flask 方法 View

java - Oracle Hotspot JVM : generally, 哪些操作特别占用 CPU?

sql-server - 用于获取性能统计信息的 SQL 命令

python - 如何通过切片范围有效地索引到一维 numpy 数组