Confronto di due array numpy per la conformità con due condizioni

Aug 18 2020

Considera due array numpy aventi la stessa forma, A e B, composti da 1 e 0. Viene mostrato un piccolo esempio:

A = [[1 0 0 1]         B = [[0 0 0 0]
     [0 0 1 0]              [0 0 0 0]
     [0 0 0 0]              [1 1 0 0]
     [0 0 0 0]              [0 0 1 0]
     [0 0 1 1]]             [0 1 0 1]]

Ora voglio valori assegnare alle due variabili booleane test1 e test2 come segue:

test1 : esiste almeno un'istanza in cui un 1 in una Acolonna e un 1 nella STESSA Bcolonna presentano differenze di riga esattamente 1 o 2? Se è così, allora test1 = True, altrimenti False.

Nell'esempio precedente, la colonna 0 di entrambi gli array ha 1 separati da 2 righe, quindi test1 = True. (ci sono anche altre istanze nella colonna 2, ma non importa: ne abbiamo solo bisogno).

test2 : I valori 1 in Ae Bhanno tutti indirizzi di array diversi? Se è così, allora test2 = True, altrimenti False.

Nell'esempio sopra, entrambi gli array hanno [4,3] = 1, quindi test2 = False.

Sto lottando per trovare un modo efficiente per farlo e apprezzerei un po 'di assistenza.

Risposte

1 MadPhysicist Aug 18 2020 at 09:53

Ecco un modo semplice per verificare se due array hanno una voce un elemento a parte nella stessa colonna (solo in una direzione):

(A[1:, :] * B[:-1, :]).any(axis=None)

Quindi puoi farlo

test1 = (A[1:, :] * B[:-1, :] + A[:-1, :] * B[1:, :]).any(axis=None) or (A[2:, :] * B[:-2, :] + A[:-2, :] * B[2:, :]).any(axis=None)

Il secondo test può essere eseguito convertendo le posizioni in indici, impilandole insieme e utilizzando np.uniqueper contare il numero di duplicati. I duplicati possono provenire solo dallo stesso indice in due array poiché un array non avrà mai indici duplicati. Possiamo accelerare ulteriormente il calcolo utilizzando flatnonzeroinvece di nonzero:

test2 = np.all(np.unique(np.concatenate((np.flatnonzero(A), np.flatnonzero(B))), return_counts=True)[1] == 1)

Un test più efficiente userebbe np.intersect1din modo simile:

test2 = not np.intersect1d(np.flatnonzero(A), np.flatnonzero(B)).size
1 Ehsan Aug 18 2020 at 08:14

Puoi usare masked_arrays e per la seconda attività puoi fare:

A_m = np.ma.masked_equal(A, 0)
B_m = np.ma.masked_equal(B, 0)

test2 = np.any((A_m==B_m).compressed())

E un modo ingenuo di svolgere il primo compito è:

test1 = np.any((np.vstack((A_m[:-1],A_m[:-2],A_m[1:],A_m[2:]))==np.vstack((B_m[1:],B_m[2:],B_m[:-1],B_m[:-2]))).compressed())

produzione:

True
True
ArundeepChohan Aug 18 2020 at 09:56

Per Test2: potresti semplicemente controllare se hanno trovato indici simili trovati per un valore di 1.

A =  np.array([[1, 0, 0, 1],[0, 0, 1, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 1, 1]])
B = np.array([[0, 0, 0, 0],[0, 0, 0, 0],[1, 1, 0, 0],[0, 0, 1, 0],[0, 1, 0, 1]])
print(len(np.intersect1d(np.flatnonzero(A==1),np.flatnonzero(B==1)))>0))