numpy数组比较的快捷评估

时间:2016-01-18 10:19:50

标签: python numpy

如果我想比较两个数组,比如说我想测试A中的所有元素是否小于B中的值,我使用if (A < B).all():。但实际上,这需要分配和评估完整数组C = A < B,然后在其上调用C.all()。这有点浪费。有没有办法'快捷'比较,即直接按元素评估A < B(不分配和计算临时C),并在第一个无效元素比较时停止并返回False发现?

2 个答案:

答案 0 :(得分:1)

你的阵列有多大?我会想象它们非常大,例如在性能成为问题之前A.shape = (1000000)或更大。你会考虑使用numpy views吗?

您可以尝试定义视图,例如(A < B).all(),而不是比较(A < B).any()(A[:10] < B[:10]).all()。这是一个可能有效的简单循环:

k = 0
while( (A[k*10: (k+1)*10] < B[k*10: (k+1)*10] ).all() ):
    k += 1

您可以使用100或10**3段大小而不是10。显然,如果您的细分受众群大小为1,则说:

k = 0
while ( A[k] < B[k] ):
    k+= 1

有时,比较整个阵列可能会占用大量内存。如果AB的长度为10000,并且我需要比较每对元素,那么我将耗尽空间。

答案 1 :(得分:0)

普通Python andor使用快捷方式评估,但numpy没有。

(A < B).all()

使用numpy构建基块,广播,逐元素与<的比较以及all缩减。 <只适用于其他二元操作,加上,时间和,或,或,等等。all与其他缩减方法anymax一样, summean,可以对整个数组或按行或按列进行操作。

可以编写一个将all<组合成一个迭代的函数,但是很难得到我刚才描述的一般性。

但是如果您必须使用快捷操作实现迭代解决方案并快速执行,我建议使用nditer开发该想法,然后使用cython进行编译。< / p>

http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html是使用nditer的好教程,它会引导您在cython中使用它。 nditer负责广播和迭代,让您专注于比较和任何捷径。

这是一个可以投射到cython的迭代器的草图:

import numpy as np

a = np.arange(4)[:,None]
b = np.arange(2,5)[None,:]
c = np.array(True)
it = np.nditer([a, b, c], flags=['reduce_ok'],
    op_flags = [['readonly'], ['readonly'],['readwrite']])
for x, y, z in it:
    z[...] = x<y
    if not z:
        print('>',x,y)
        break
    else:
        print(x,y)
print(z)

运行示例:

1420:~/mypy$ python stack34852272.py 
(array(0), array(2))
(array(0), array(3))
(array(0), array(4))
(array(1), array(2))
(array(1), array(3))
(array(1), array(4))
('>', array(2), array(2))
False

以默认False和其他break条件开头,您可以获得快捷方式any。推广测试以处理<<=等将会更有效。

使用Python工作,然后在Cython中尝试。如果您在执行该步骤时遇到问题,请返回一个新问题。 SO拥有Cython用户的良好基础。