多于两个参数的Numpy`logical_or`

use*_*893 72 python arrays numpy

Numpy的logical_or函数只需要比较两个数组.如何找到两个以上数组的并集?(关于Numpy的问题可以提出同样的问题,logical_and并获得两个以上数组的交集.)

aba*_*ert 150

如果您正在询问numpy.logical_or,那么不,正如文档明确指出的那样,唯一的参数是x1, x2,并且可选out:

numpy.logical_or(x1, x2[, out])=<ufunc 'logical_or'>


您当然可以将多个logical_or调用链接在一起,如下所示:

>>> x = np.array([True, True, False, False])
>>> y = np.array([True, False, True, False])
>>> z = np.array([False, False, False, False])
>>> np.logical_or(np.logical_or(x, y), z)
array([ True,  True,  True,  False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

在NumPy中推广这种链接的方法是reduce:

>>> np.logical_or.reduce((x, y, z))
array([ True,  True,  True,  False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

当然,这也会,如果你有一个多维数组,而不是单独的工作阵列-实际上,这就是它的意思被使用:

>>> xyz = np.array((x, y, z))
>>> xyz
array([[ True,  True, False, False],
       [ True, False,  True, False],
       [False, False, False, False]], dtype=bool)
>>> np.logical_or.reduce(xyz)
array([ True,  True,  True,  False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

但是三个等长1D数组的元组是NumPy项中的array_like,可以用作2D数组.


在NumPy之外,你也可以使用Python reduce:

>>> functools.reduce(np.logical_or, (x, y, z))
array([ True,  True,  True,  False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

然而,与NumPy不同reduce,Python并不经常需要.对于大多数情况,有一种更简单的方法 - 例如,将多个Python or运算符链接在一起,不要reduce结束operator.or_,只需使用any.如果没有,使用显式循环通常更具可读性.

事实上,NumPy any也适用于这种情况,尽管它并不是那么微不足道; 如果你没有明确地给它一个轴,你最终会得到一个标量而不是一个数组.所以:

>>> np.any((x, y, z), axis=0)
array([ True,  True,  True,  False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

正如您所料,logical_and类似 - 您可以将其链接,np.reduce它,functools.reduce它或all用显式替换axis.

其他操作怎么样logical_xor?同样,同样的交易...除了在这种情况下没有适用的all/ any-type函数.(你会怎么称呼它odd?)

  • `np.logical_or.reduce((x,y,z))`正是我想要的! (2认同)

cit*_*man 8

基于 abarnert 对 n 维案例的回答:

特尔;博士: np.logical_or.reduce(np.array(list))


Gia*_*lli 7

我尝试了以下三种不同的方法来获取大小为n的k 个数组的logical_and列表l

  1. 使用递归numpy.logical_and(见下文)
  2. 使用numpy.logical_and.reduce(l)
  3. 使用numpy.vstack(l).all(axis=0)

然后我对该logical_or函数做了同样的事情。令人惊讶的是,递归方法是最快的方法。

import numpy
import perfplot

def and_recursive(*l):
    if len(l) == 1:
        return l[0].astype(bool)
    elif len(l) == 2:
        return numpy.logical_and(l[0],l[1])
    elif len(l) > 2:
        return and_recursive(and_recursive(*l[:2]),and_recursive(*l[2:]))

def or_recursive(*l):
    if len(l) == 1:
        return l[0].astype(bool)
    elif len(l) == 2:
        return numpy.logical_or(l[0],l[1])
    elif len(l) > 2:
        return or_recursive(or_recursive(*l[:2]),or_recursive(*l[2:]))

def and_reduce(*l):
    return numpy.logical_and.reduce(l)

def or_reduce(*l):
    return numpy.logical_or.reduce(l)

def and_stack(*l):
    return numpy.vstack(l).all(axis=0)

def or_stack(*l):
    return numpy.vstack(l).any(axis=0)

k = 10 # number of arrays to be combined

perfplot.plot(
    setup=lambda n: [numpy.random.choice(a=[False, True], size=n) for j in range(k)],
    kernels=[
        lambda l: and_recursive(*l),
        lambda l: and_reduce(*l),
        lambda l: and_stack(*l),
        lambda l: or_recursive(*l),
        lambda l: or_reduce(*l),
        lambda l: or_stack(*l),
    ],
    labels = ['and_recursive', 'and_reduce', 'and_stack', 'or_recursive', 'or_reduce', 'or_stack'],
    n_range=[2 ** j for j in range(20)],
    logx=True,
    logy=True,
    xlabel="len(a)",
    equality_check=None
)
Run Code Online (Sandbox Code Playgroud)

下面是 k = 4 时的性能。

k=4 的性能

下面是 k = 10 时的性能。

k=10 的性能

对于较高的 n 来说,似乎也有大约恒定的时间开销。

  • 尝试将 `functools.reduce(numpy.logic_and, l)` 和 `functools.reduce(numpy.logic_or, l)` 添加到您的比较中。有趣的是,我发现它们实际上比 `k=4` 和 `k=10` 的递归实现更快,特别是如果 `len(a) &lt; 10**4`。 (2认同)

Hyp*_*eus 6

由于布尔代数在定义时都是可交换的和关联的,因此对于a,b和c的布尔值,以下语句或等效语句.

a or b or c

(a or b) or c

a or (b or c)

(b or a) or c

所以如果你有一个二元的"logical_or",你需要传递三个参数(a,b和c),你可以调用

logical_or(logical_or(a, b), c)

logical_or(a, logical_or(b, c))

logical_or(c, logical_or(b, a))

或者你喜欢的任何排列.


回到python,如果你想测试一个条件(由一个带有被测试者的函数产生test并返回一个布尔值)是否适用于a或b或c或列表L的任何元素,你通常会使用

any(test(x) for x in L)
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 6

如果有人仍然需要这一点-假设你有三个布尔数组a,b,c形状相同,这给and元素方面:

a * b * c
Run Code Online (Sandbox Code Playgroud)

这给了or:

a + b + c
Run Code Online (Sandbox Code Playgroud)

这是你想要的吗?堆叠很多logical_andlogical_or不实用.


小智 6

我使用这个可以扩展到 n 个数组的解决方法:

>>> a = np.array([False, True, False, False])
>>> b = np.array([True, False, False, False])
>>> c = np.array([False, False, False, True])
>>> d = (a + b + c > 0) # That's an "or" between multiple arrays
>>> d
array([ True,  True, False,  True], dtype=bool)
Run Code Online (Sandbox Code Playgroud)