Comparaison de deux tableaux numpy pour le respect de deux conditions

Aug 18 2020

Considérons deux tableaux numpy ayant la même forme, A et B, composés de 1 et de 0. Un petit exemple est montré:

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

Je veux maintenant attribuer des valeurs aux deux variables booléennes test1 et test2 comme suit:

test1 : Y a-t-il au moins une instance où un 1 dans une Acolonne et un 1 dans la même Bcolonne ont des différences de ligne exactement de 1 ou 2? Si tel est le cas, alors test1 = True, sinon False.

Dans l'exemple ci-dessus, la colonne 0 des deux tableaux a des 1 séparés de 2 lignes, donc test1 = True. (il existe également d'autres instances dans la colonne 2, mais cela n'a pas d'importance - nous n'avons besoin que d'une seule instance.)

test2 : les valeurs 1 dans Aet Bont-elles toutes des adresses de tableau différentes? Si tel est le cas, alors test2 = True, sinon False.

Dans l'exemple ci-dessus, les deux tableaux ont [4,3] = 1, donc test2 = False.

J'ai du mal à trouver un moyen efficace de le faire et j'apprécierais de l'aide.

Réponses

1 MadPhysicist Aug 18 2020 at 09:53

Voici un moyen simple de tester si deux tableaux ont une entrée distante d'un élément dans la même colonne (uniquement dans une direction):

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

Alors tu peux faire

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

Le deuxième test peut être effectué en convertissant les emplacements en index, en les empilant et en utilisant np.uniquepour compter le nombre de doublons. Les doublons ne peuvent provenir du même index que dans deux tableaux car un tableau n'aura jamais d'index en double. Nous pouvons encore accélérer le calcul en utilisant flatnonzeroau lieu de nonzero:

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

Un test plus efficace utiliserait np.intersect1dde la même manière:

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

Vous pouvez utiliser masked_arrays et pour la deuxième tâche, vous pouvez faire:

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

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

Et une façon naïve de faire la première tâche est:

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

production:

True
True
ArundeepChohan Aug 18 2020 at 09:56

Pour Test2: Vous pouvez simplement vérifier s'ils ont trouvé des index similaires trouvés pour une valeur de 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))