Confronto tra due array NumPy per l'uguaglianza, dal punto di vista degli elementi


252

Qual è il modo più semplice per confrontare due matrici NumPy per l'uguaglianza (dove l'uguaglianza è definita come: A = B iff per tutti gli indici i:) A[i] == B[i]?

Semplicemente usando ==mi dà un array booleano:

 >>> numpy.array([1,1,1]) == numpy.array([1,1,1])

array([ True,  True,  True], dtype=bool)

Devo andgli elementi di questo array per determinare se gli array sono uguali o esiste un modo più semplice per confrontare?

Risposte:


380
(A==B).all()

verifica se tutti i valori dell'array (A == B) sono True.

Nota: forse vuoi anche testare le forme A e B, come ad esempio A.shape == B.shape

Casi speciali e alternative (dalla risposta di dbaupp e dal commento di Yoavram)

Si dovrebbe notare che:

  • questa soluzione può avere un comportamento strano in un caso particolare: se uno Ao Bè vuoto e l'altro contiene un singolo elemento, allora ritorna True. Per qualche motivo, il confronto A==Brestituisce un array vuoto, per il quale l' alloperatore restituisce True.
  • Un altro rischio è se Ae Bnon hanno la stessa forma e non sono trasmissibili, quindi questo approccio genererà un errore.

In conclusione, se hai qualche dubbio Ae Bforma o semplicemente vuoi essere al sicuro: usa una delle funzioni specializzate:

np.array_equal(A,B)  # test if same shape, same elements values
np.array_equiv(A,B)  # test if broadcastable shape, same elements values
np.allclose(A,B,...) # test if same shape, elements have close enough values

26
Quasi sempre vuoi l' np.array_equalIME. (A==B).all()andrà in crash se A e B hanno lunghezze diverse . A partire da numpy 1.10, == genera un avviso di deprecazione in questo caso .
Wilfred Hughes,

Hai un buon punto, ma nel caso ho un dubbio sulla forma di solito preferisco testarlo direttamente, prima del valore. Quindi l'errore è chiaramente sulle forme che hanno un significato completamente diverso rispetto a valori diversi. Ma ciò dipende probabilmente da ogni caso d'uso
Juh_

2
un altro rischio è se gli array contengono nan. In tal caso otterrai False perché nan! = Nan
Vincenzooo,

1
Buono a precisarlo. Tuttavia, penso che questo sia logico perché nan!=nanimplica questo array(nan)!=array(nan).
Gio

Non capisco questo comportamento: import numpy as np H = 1/np.sqrt(2)*np.array([[1, 1], [1, -1]]) #hadamard matrix np.array_equal(H.dot(H.T.conj()), np.eye(len(H))) # checking if H is an unitary matrix or not H è una matrice unitaria, quindi H x H.T.conjè una matrice di identità. Ma np.array_equalrestituisce False
Dex il

91

La (A==B).all()soluzione è molto accurata, ma ci sono alcune funzioni integrate per questa attività. Vale a dire array_equal, allclosee array_equiv.

(Anche se alcuni test rapidi con timeitsembrano indicare che il (A==B).all()metodo è il più veloce, il che è un po 'strano, dato che deve allocare un array completamente nuovo.)


15
hai ragione, tranne che se uno degli array confrontati è vuoto otterrai la risposta sbagliata (A==B).all(). Ad esempio, prova (np.array([1])==np.array([])).all()Truenp.array_equal(np.array([1]), np.array([]))False
:,

1
Ho appena scoperto anche questa differenza di prestazioni. È strano perché se hai 2 array completamente diversi (a==b).all()è ancora più veloce di np.array_equal(a, b)(che potrebbe aver appena controllato un singolo elemento ed essere uscito).
Aidan Kane,

np.array_equalfunziona anche con lists of arrayse dicts of arrays. Questo potrebbe essere un motivo per prestazioni più lente.
Bernhard,

Grazie mille per la funzione allclose, questo è quello che mi serviva per i calcoli numerici . Confronta l'uguaglianza dei vettori all'interno di una tolleranza . :)
loved.by.Jesus

Si noti che np.array_equiv([1,1,1], 1) is True. Questo perché: La forma coerente significa che hanno la stessa forma oppure è possibile trasmettere un array di input per creare la stessa forma dell'altro.
EliadL

13

Misuriamo le prestazioni usando il seguente pezzo di codice.

import numpy as np
import time

exec_time0 = []
exec_time1 = []
exec_time2 = []

sizeOfArray = 5000
numOfIterations = 200

for i in xrange(numOfIterations):

    A = np.random.randint(0,255,(sizeOfArray,sizeOfArray))
    B = np.random.randint(0,255,(sizeOfArray,sizeOfArray))

    a = time.clock() 
    res = (A==B).all()
    b = time.clock()
    exec_time0.append( b - a )

    a = time.clock() 
    res = np.array_equal(A,B)
    b = time.clock()
    exec_time1.append( b - a )

    a = time.clock() 
    res = np.array_equiv(A,B)
    b = time.clock()
    exec_time2.append( b - a )

print 'Method: (A==B).all(),       ', np.mean(exec_time0)
print 'Method: np.array_equal(A,B),', np.mean(exec_time1)
print 'Method: np.array_equiv(A,B),', np.mean(exec_time2)

Produzione

Method: (A==B).all(),        0.03031857
Method: np.array_equal(A,B), 0.030025185
Method: np.array_equiv(A,B), 0.030141515

Secondo i risultati precedenti, i metodi numpy sembrano essere più veloci della combinazione dell'operatore == e del metodo all () e confrontando i metodi numpy il più veloce sembra essere il metodo numpy.array_equal .


4
Dovresti utilizzare una dimensione dell'array più grande che richiede almeno un secondo per essere compilata per aumentare l'accuratezza dell'esperimento.
Vikhyat Agarwal,

Questo si riproduce anche quando viene cambiato l'ordine di confronto? o reinizializzare A e B ogni volta? Questa differenza potrebbe anche essere spiegata dalla memorizzazione nella cache delle celle A e B.
O Groman,

3
Non c'è alcuna differenza significativa tra questi tempi.
A 마 SE l'

13

Se si desidera verificare se due array hanno lo stesso shapeAND, elementsè necessario utilizzare np.array_equalin quanto è il metodo consigliato nella documentazione.

Per quanto riguarda le prestazioni, non ci si aspetta che un controllo dell'uguaglianza ne superi un altro, poiché non c'è molto spazio per l'ottimizzazione comparing two elements. Solo per il gusto, ho ancora fatto alcuni test.

import numpy as np
import timeit

A = np.zeros((300, 300, 3))
B = np.zeros((300, 300, 3))
C = np.ones((300, 300, 3))

timeit.timeit(stmt='(A==B).all()', setup='from __main__ import A, B', number=10**5)
timeit.timeit(stmt='np.array_equal(A, B)', setup='from __main__ import A, B, np', number=10**5)
timeit.timeit(stmt='np.array_equiv(A, B)', setup='from __main__ import A, B, np', number=10**5)
> 51.5094
> 52.555
> 52.761

Quindi praticamente uguale, non c'è bisogno di parlare della velocità.

Le (A==B).all()si comporta più o meno come il seguente frammento di codice:

x = [1,2,3]
y = [1,2,3]
print all([x[i]==y[i] for i in range(len(x))])
> True

5

Di solito due array presentano alcuni piccoli errori numerici,

Puoi usare numpy.allclose(A,B), invece di (A==B).all(). Questo restituisce un valore True / False


0

Adesso usa np.array_equal. Dalla documentazione:

np.array_equal([1, 2], [1, 2])
True
np.array_equal(np.array([1, 2]), np.array([1, 2]))
True
np.array_equal([1, 2], [1, 2, 3])
False
np.array_equal([1, 2], [1, 4])
False
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.