多个逻辑参数的Numpy`logical_or`


88

Numpy的logical_or函数只需要两个数组比较即可。如何找到两个以上数组的并集?(关于Numpy'slogical_and并获得两个以上数组的交集,可能会问相同的问题。)



有没有类似于any()的方法?
user3074893 2013年

@ user3074893:这是完全相同的问题。您要我扩大答案吗?
abarnert 2013年

Answers:


174

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

numpy.logical_orx1, 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)

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

>>> np.logical_or.reduce((x, y, z))
array([ True,  True,  True,  False], dtype=bool)

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

>>> 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)

但是,三个相等长度的1D数组的元组在NumPy方面类似于array_,并且可以用作2D数组。


在NumPy之外,您还可以使用Python的reduce

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

但是,与NumPy的不同reduce,Python并不是经常需要的。在大多数情况下,有一种更简单的方法来执行操作-例如,将多个Pythonor运算符链接在一起,不要停下reduceoperator.or_,只需要使用即可any。如果没有,使用显式循环通常更易读。

实际上,NumPyany也可以用于这种情况,尽管它并不是那么简单。如果您未明确为其指定轴,则最终将得到标量而不是数组。所以:

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

如您所料,它logical_and是相似的-您可以将其链接起来,np.reduce也可以用显式functools.reduce替换。allaxis

那么其他操作logical_xor呢?再次,同样的处理……除了在这种情况下不存在all/ any-type函数。(你叫什么odd??)


2
np.logical_or.reduce((x, y, z))正是我想要的!
blaylockbk

reduce不再是python 3中的内部函数。而是使用:functools.reduce()
marvin

10

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

a * b * c

这给出了or

a + b + c

这是你想要的吗?堆叠很多logical_and还是logical_or不实际的。


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)

但是Pythonor并不是真正的布尔值or,这不仅是因为它可以处理bools以外的值(a如果返回atrue,b否则返回),还因为它短路(含义a or b可能为True,而b or a引发异常)。
abarnert 2013年

@abarnert谢谢,我已经修改了帐户的答案。
Hyperboreus 2013年

(我不确定为什么人们会对此表示不满,但是…OP似乎特别在谈论布尔值,他称之为“逻辑条件”。)
abarnert 2013年

@abarnert不要问我。我认为,如果您在后台直接进行数学运算(在这种情况下为布尔代数),那么许多编程问题就更容易解决。
Hyperboreus 2013年

4

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

TL; DR: np.logical_or.reduce(np.array(list))


4

使用sum函数:

a = np.array([True, False, True])
b = array([ False, False,  True])
c = np.vstack([a,b,b])

Out[172]: 
array([[ True, False,  True],
   [False, False,  True],
   [False, False,  True]], dtype=bool)

np.sum(c,axis=0)>0
Out[173]: array([ True, False,  True], dtype=bool)

4

我使用可以扩展到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)

1

我尝试了以下三种不同的方法来获取大小为nk个数组的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
)

以下是k = 4的性能。

k = 4的性能

下面是k = 10的性能。

k = 10时的性能

似乎对于较高的n也存在大约恒定的时间开销。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.