Membandingkan dua array NumPy untuk kesetaraan, elemen-bijaksana

252

Apa cara paling sederhana untuk membandingkan dua array NumPy untuk kesetaraan (di mana kesetaraan didefinisikan sebagai: A = B iff untuk semua indeks i:) A[i] == B[i]?

Cukup menggunakan ==memberi saya array boolean:

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

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

Apakah saya harus andelemen array ini untuk menentukan apakah array sama, atau apakah ada cara yang lebih sederhana untuk membandingkan?

clstaudt
sumber

Jawaban:

380
(A==B).all()

uji apakah semua nilai array (A == B) Benar.

Catatan: mungkin Anda juga ingin menguji bentuk A dan B, seperti A.shape == B.shape

Kasus dan alternatif khusus (dari jawaban dbaupp dan komentar yoavram)

Perlu dicatat bahwa:

  • solusi ini dapat memiliki perilaku aneh dalam kasus tertentu: jika salah satu Aatau Bkosong dan yang lain berisi elemen tunggal, maka ia kembali True. Untuk beberapa alasan, perbandingan A==Bmengembalikan array kosong, yang alldikembalikan operator True.
  • Risiko lain adalah jika Adan Btidak memiliki bentuk yang sama dan tidak dapat disiarkan, maka pendekatan ini akan menimbulkan kesalahan.

Kesimpulannya, jika Anda memiliki keraguan tentang Adan Bbentuk atau hanya ingin aman: gunakan salah satu fungsi khusus:

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
Juh_
sumber
26
Anda hampir selalu menginginkan np.array_equalIME. (A==B).all()akan macet jika A dan B memiliki panjang yang berbeda . Pada numpy 1,10, == memunculkan peringatan penghentian dalam kasus ini .
Wilfred Hughes
Anda sudah mendapatkan poin yang bagus, tetapi dalam kasus ini saya ragu dengan bentuknya, saya biasanya memilih untuk langsung mengujinya, sebelum nilainya. Maka kesalahannya jelas pada bentuk yang memiliki arti yang sama sekali berbeda daripada memiliki nilai yang berbeda. Tapi itu mungkin tergantung pada masing-masing use-case
Juh_
2
Risiko lain adalah jika array berisi nan. Dalam hal ini Anda akan mendapatkan False karena nan! = Nan
Vincenzooo
1
Bagus untuk menunjukkannya. Namun, saya pikir ini logis karena nan!=nanmenyiratkan itu array(nan)!=array(nan).
Juh_
Saya tidak mengerti perilaku ini: 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 adalah matriks kesatuan, jadi H x H.T.conjadalah matriks identitas. Tetapi np.array_equalmengembalikan False
Dex
91

The (A==B).all()solusi adalah sangat rapi, tetapi ada beberapa fungsi built-in untuk tugas ini. Yaitu array_equal, allclosedan array_equiv.

(Meskipun, beberapa pengujian cepat dengan timeittampaknya menunjukkan bahwa (A==B).all()metode ini adalah yang tercepat, yang agak aneh, mengingat harus mengalokasikan array yang sama sekali baru.)

huon
sumber
15
Anda benar, kecuali bahwa jika salah satu array yang dibandingkan kosong, Anda akan mendapatkan jawaban yang salah (A==B).all(). Misalnya, coba (np.array([1])==np.array([])).all()Truenp.array_equal(np.array([1]), np.array([]))False
:,
1
Saya baru saja menemukan perbedaan kinerja ini. Aneh karena jika Anda memiliki 2 array yang sama sekali berbeda (a==b).all()masih lebih cepat daripada np.array_equal(a, b)(yang bisa saja memeriksa satu elemen dan keluar).
Aidan Kane
np.array_equaljuga bekerja dengan lists of arraysdan dicts of arrays. Ini mungkin menjadi alasan untuk kinerja yang lebih lambat.
Bernhard
Terima kasih banyak untuk fungsinya allclose, itulah yang saya butuhkan untuk perhitungan numerik . Ini membandingkan kesetaraan vektor dalam toleransi . :)
loved.by.Yesus
Catat itu np.array_equiv([1,1,1], 1) is True. Ini karena: Bentuk yang konsisten berarti bentuknya sama, atau satu array input dapat disiarkan untuk membuat bentuk yang sama dengan yang lainnya.
EliadL
13

Mari kita mengukur kinerja dengan menggunakan potongan kode berikut.

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)

Keluaran

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

Menurut hasil di atas, metode numpy tampaknya lebih cepat daripada kombinasi dari operator == dan metode all () dan dengan membandingkan metode numpy , yang tercepat tampaknya adalah metode numpy.array_equal .

pengecut
sumber
4
Anda harus menggunakan ukuran array yang lebih besar yang memerlukan setidaknya satu detik untuk dikompilasi untuk meningkatkan akurasi percobaan.
Vikhyat Agarwal
Apakah ini juga mereproduksi ketika urutan perbandingan diubah? atau memasang kembali A dan B secara acak setiap kali? Perbedaan ini mungkin juga dijelaskan dari caching memori sel A dan B.
Atau Groman
3
Tidak ada perbedaan yang berarti antara pengaturan waktu ini.
To 마 SE
13

Jika Anda ingin memeriksa apakah dua array memiliki shapeAND yang sama, elementsAnda harus menggunakannya np.array_equalkarena metode ini direkomendasikan dalam dokumentasi.

Dari segi kinerja jangan berharap bahwa pemeriksaan kesetaraan akan mengalahkan yang lain, karena tidak ada banyak ruang untuk dioptimalkan comparing two elements. Demi Tuhan, saya masih melakukan beberapa tes.

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

Jadi hampir sama, tidak perlu berbicara tentang kecepatan.

The (A==B).all()berperilaku cukup banyak seperti potongan kode berikut:

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

Biasanya dua array akan memiliki beberapa kesalahan numerik kecil,

Anda bisa menggunakan numpy.allclose(A,B), alih-alih (A==B).all(). Ini mengembalikan bool Benar / Salah

R Zhang
sumber
0

Sekarang gunakan np.array_equal. Dari dokumentasi:

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
keramat
sumber