A logical_or
função de Numpy leva não mais do que dois arrays para comparar. Como posso encontrar a união de mais de duas matrizes? (A mesma pergunta pode ser feita em relação ao Numpy logical_and
e obter a interseção de mais de duas matrizes.)
88
any()
?Respostas:
Se você está perguntando sobre
numpy.logical_or
, então não, como os documentos dizem explicitamente, os únicos parâmetros sãox1, x2
, e opcionalmenteout
:Claro, você pode encadear várias
logical_or
chamadas como esta:>>> 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)
A maneira de generalizar este tipo de encadeamento no NumPy é com
reduce
:>>> np.logical_or.reduce((x, y, z)) array([ True, True, True, False], dtype=bool)
E é claro que isso também funcionará se você tiver um array multidimensional em vez de arrays separados - na verdade, é assim que ele deve ser usado:
>>> 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)
Mas uma tupla de três matrizes 1D de comprimento igual é um array_like em termos NumPy e pode ser usada como uma matriz 2D.
Fora do NumPy, você também pode usar Python
reduce
:>>> functools.reduce(np.logical_or, (x, y, z)) array([ True, True, True, False], dtype=bool)
No entanto, ao contrário do NumPy
reduce
, o Python não é frequentemente necessário. Para a maioria dos casos, há uma maneira mais simples de fazer as coisas - por exemplo, encadear váriosor
operadores Python , nãoreduce
sobreoperator.or_
, apenas useany
. E quando não há , geralmente é mais legível usar um loop explícito.E, de fato, o NumPy
any
pode ser usado para este caso também, embora não seja tão trivial; se você não der explicitamente um eixo, você acabará com um escalar em vez de um array. Então:>>> np.any((x, y, z), axis=0) array([ True, True, True, False], dtype=bool)
Como você pode esperar,
logical_and
é semelhante - você pode encadear,np.reduce
it,functools.reduce
it ou substituirall
por um explicitaxis
.E quanto a outras operações, como
logical_xor
? Novamente, o mesmo negócio ... exceto que, neste caso, não há funçãoall
/any
-type que se aplica. (Como você chamariaodd
?)fonte
np.logical_or.reduce((x, y, z))
era exatamente o que eu estava procurando!reduce
não é mais uma função interna no python 3. Em vez disso, use:functools.reduce()
No caso de alguém ainda precisa disso - Digamos que você tenha três matrizes de booleanos
a
,b
,c
com a mesma forma, isso dáand
elemento-wise:isso dá
or
:É isso que voce quer? Empilhar muito
logical_and
oulogical_or
não é prático.fonte
Como as álgebras booleanas são comutativas e associativas por definição, as seguintes instruções ou equivalentes para valores booleanos de a, be c.
a or b or c
(a or b) or c
a or (b or c)
(b or a) or c
Então, se você tiver um "lógico_ou" que é diádico e precisar passar três argumentos (a, b e c), você pode chamar
logical_or(logical_or(a, b), c)
logical_or(a, logical_or(b, c))
logical_or(c, logical_or(b, a))
ou qualquer permutação que você quiser.
De volta ao python, se você quiser testar se uma condição (produzida por uma função
test
que leva um testado e retorna um valor booleano) se aplica a a ou b ou c ou qualquer elemento da lista L, você normalmente usaany(test(x) for x in L)
fonte
or
não é realmente booleanoor
, tanto porque funciona com valores diferentes debool
s (retornara
ifa
é verdadeiro,b
caso contrário) e porque causa curto-circuito (o significadoa or b
pode ser True, enquantob or a
gera uma exceção).Com base na resposta da abarnert para o caso n-dimensional:
TL; DR:
np.logical_or.reduce(np.array(list))
fonte
usando a função soma:
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)
fonte
Eu uso esta solução alternativa que pode ser estendida para n matrizes:
>>> 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)
fonte
Tentei os três métodos diferentes a seguir para obter o
logical_and
de uma lista l de k arrays de tamanho n :numpy.logical_and
(veja abaixo)numpy.logical_and.reduce(l)
numpy.vstack(l).all(axis=0)
Então fiz o mesmo para a
logical_or
função. Surpreendentemente, o método recursivo é o mais rápido.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 )
Aqui, abaixo, os desempenhos para k = 4.
E aqui abaixo os desempenhos para k = 10.
Parece que há uma sobrecarga de tempo aproximadamente constante também para n mais alto.
fonte