Membandingkan dua larik numpy untuk memenuhi dua kondisi

Aug 18 2020

Pertimbangkan dua larik numpy yang memiliki bentuk yang sama, A dan B, terdiri dari 1 dan 0. Contoh kecil ditampilkan:

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

Sekarang saya ingin menetapkan nilai ke dua variabel Boolean test1 dan test2 sebagai berikut:

test1 : Apakah ada setidaknya satu contoh di mana 1 di Akolom dan 1 di Bkolom yang SAMA memiliki perbedaan baris tepat 1 atau 2? Jika ya, maka test1 = True, jika tidak False.

Dalam contoh di atas, kolom 0 dari kedua larik memiliki 1 yang terpisah 2 baris, jadi test1 = True. (ada contoh lain di kolom 2 juga, tapi itu tidak masalah - kami hanya memerlukan satu contoh.)

test2 : Apakah 1 nilai dalam Adan Bsemua memiliki alamat array yang berbeda? Jika ya, maka test2 = True, jika tidak False.

Dalam contoh di atas, kedua larik memiliki [4,3] = 1, jadi test2 = False.

Saya berjuang untuk menemukan cara yang efisien untuk melakukan ini dan sangat menghargai bantuan.

Jawaban

1 MadPhysicist Aug 18 2020 at 09:53

Berikut adalah cara sederhana untuk menguji apakah dua larik memiliki entri satu elemen terpisah dalam kolom yang sama (hanya dalam satu arah):

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

Jadi Anda bisa melakukannya

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

Tes kedua dapat dilakukan dengan mengubah lokasi menjadi indeks, menumpuknya bersama-sama, dan menggunakan np.uniqueuntuk menghitung jumlah duplikat. Duplikat hanya dapat berasal dari indeks yang sama dalam dua larik karena larik tidak akan pernah memiliki indeks duplikat. Kami selanjutnya dapat mempercepat penghitungan dengan menggunakan flatnonzerosebagai pengganti nonzero:

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

Tes yang lebih efisien akan digunakan np.intersect1ddengan cara yang sama:

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

Anda dapat menggunakan masked_arrays dan untuk tugas kedua Anda dapat melakukan:

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

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

Dan cara naif untuk melakukan tugas pertama adalah:

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

keluaran:

True
True
ArundeepChohan Aug 18 2020 at 09:56

Untuk Test2: Anda dapat memeriksa apakah mereka menemukan indeks serupa yang ditemukan untuk nilai 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))