numpy.logical_and与乘法

时间:2016-01-25 23:19:30

标签: python arrays numpy boolean boolean-operations

鉴于三个numpy数组abc(编辑:具有相同的形状/大小),似乎对于非复数数字

a * b * c != 0  # test element-wise whether all are non-zero

给出与以下相同的结果:

np.logical_and(a, np.logical_and(b, c))

第一个版本中是否存在隐藏的陷阱?是否有更简单的方法来测试它?

4 个答案:

答案 0 :(得分:3)

鉴于bc持有实数,np.logical_and(b, c)实际上会涉及到底层转换为布尔值。

我们可以提前进行转换吗?如果是这样,那会有帮助吗?

现在,检查 ALL 相应元素是否为非零的陈述操作等同于检查布尔值是否 ANY 相应的元素为零,即

~((a == 0) + (b==0) + (c==0)

OR

~((a == 0) | (b==0) | (c==0))

此外,与zero进行比较后,这将涉及预先转换为布尔值,因此可能有助于提高性能。这是涉及的运行时数 -

案例#1:

In [10]: # Setup inputs
    ...: M, N = 100, 100
    ...: a = np.random.randint(0,5,(M,N))
    ...: b = np.random.randint(0,5,(M,N))
    ...: c = np.random.randint(0,5,(M,N))
    ...: 

In [11]: %timeit np.logical_and(a, np.logical_and(b, c))
    ...: %timeit a * b * c != 0
    ...: %timeit ~((a == 0) + (b==0) + (c==0))
    ...: %timeit ~((a == 0) | (b==0) | (c==0))
    ...: 
10000 loops, best of 3: 96.6 µs per loop
10000 loops, best of 3: 78.2 µs per loop
10000 loops, best of 3: 51.6 µs per loop
10000 loops, best of 3: 51.5 µs per loop

案例#2:

In [12]: # Setup inputs
    ...: M, N = 1000, 1000
    ...: a = np.random.randint(0,5,(M,N))
    ...: b = np.random.randint(0,5,(M,N))
    ...: c = np.random.randint(0,5,(M,N))
    ...: 

In [13]: %timeit np.logical_and(a, np.logical_and(b, c))
    ...: %timeit a * b * c != 0
    ...: %timeit ~((a == 0) + (b==0) + (c==0))
    ...: %timeit ~((a == 0) | (b==0) | (c==0))
    ...: 
100 loops, best of 3: 11.4 ms per loop
10 loops, best of 3: 24.1 ms per loop
100 loops, best of 3: 9.29 ms per loop
100 loops, best of 3: 9.2 ms per loop

案例#3:

In [14]: # Setup inputs
    ...: M, N = 5000, 5000
    ...: a = np.random.randint(0,5,(M,N))
    ...: b = np.random.randint(0,5,(M,N))
    ...: c = np.random.randint(0,5,(M,N))
    ...: 

In [15]: %timeit np.logical_and(a, np.logical_and(b, c))
    ...: %timeit a * b * c != 0
    ...: %timeit ~((a == 0) + (b==0) + (c==0))
    ...: %timeit ~((a == 0) | (b==0) | (c==0))
    ...: 
1 loops, best of 3: 294 ms per loop
1 loops, best of 3: 694 ms per loop
1 loops, best of 3: 268 ms per loop
1 loops, best of 3: 268 ms per loop

似乎comparison to zero approach有很好的利益百分比!

答案 1 :(得分:3)

一些观察结果:

import numpy as np
import timeit
​
a = np.random.randint(0, 5, 100000)
b = np.random.randint(0, 5, 100000)
c = np.random.randint(0, 5, 100000)
​
method_one = np.logical_and(np.logical_and(a, b), c)
%timeit np.logical_and(np.logical_and(a, b), c)
​
method_two = a*b*c != 0
%timeit a*b*c != 0
​
method_three = np.logical_and(np.logical_and(a.astype('bool'), b.astype('bool')), c.astype('bool'))
%timeit np.logical_and(np.logical_and(a.astype('bool'), b.astype('bool')), c.astype('bool'))
​
method_four = a.astype('bool') * b.astype('bool') * c.astype('bool')  != 0
%timeit a.astype('bool') * b.astype('bool') * c.astype('bool')  != 0


# verify all methods give equivalent results
all([
    np.all(method_one == method_two), 
    np.all(method_one == method_three),
    np.all(method_one == method_four)
    ]
   )
1000 loops, best of 3: 713 µs per loop
1000 loops, best of 3: 341 µs per loop
1000 loops, best of 3: 252 µs per loop
1000 loops, best of 3: 388 µs per loop

True

一些解释:

  1. a*b*c != 0方法的速度取决于向量的dtype,因为乘法是先完成的。因此,如果您有浮点数或bigints或其他更大的dtype,则此步骤将比具有布尔值或小整数的相同长度的向量花费更长的时间。强制转换为bool dtype会加快此方法的速度。如果向量具有不同的 dtypes,则事情会更慢。将整数数组乘以浮点数组需要将整数转换为浮点数,然后转换为布尔值。不是最佳的。

  2. 由于我不明白的原因, Prune 的答复声明 但是,逻辑测试更快似乎只有在输入向量已经是布尔值时才是正确的。也许在直接logical_and()方法中强制转换为布尔值的方式比使用.asdtype('bool')要慢。

  3. 最快的方法似乎是(1)提前强制输入布尔值,然后(2)使用np.logical_and()

答案 2 :(得分:0)

给出简短摘要:a * b * c != 0可能导致上溢或下溢。替代~((a == 0) | (b == 0) | (c == 0))似乎比任何其他测试实现执行得更快。

答案 3 :(得分:-1)

他们是一样的。 0和无错误;任何其他值 True 。但是,逻辑测试更快。如果列表中有很多数组,请考虑使用Python的所有任何方法。

例如:

for value in [True, False, 0, 1, None, 7, 'a', [False, False, False]]:
    if value:
        print value, True
    else:
        print value, False

输出:

True True
False False
0 False
1 True
None False
7 True
a True
[False, False, False] True