Membandingkan dua larik numpy untuk memenuhi dua kondisi
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 A
kolom dan 1 di B
kolom 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 A
dan B
semua 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
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.unique
untuk 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 flatnonzero
sebagai 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.intersect1d
dengan cara yang sama:
test2 = not np.intersect1d(np.flatnonzero(A), np.flatnonzero(B)).size
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
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))