Jika saya memiliki dua array:

a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b = np.array([0, 1, 3, 4, 7, 8, 9])
n = 3

Bagaimana saya bisa, tanpa menggunakan loop, menemukan indeks a yang memiliki nilai yang sama dengan nilai b diimbangi dengan beberapa nomor n?

Saya akan berpikir sesuatu seperti ini akan berhasil tetapi saya mendapatkan peringatan elementwise == comparison failed dan array kosong sebagai hasilnya:

np.where(a == b + n)

Inilah for loop yang menyelesaikan apa yang saya coba lakukan:

for val in b:
    print(np.where(a == val + n))

Ini menghasilkan:

(array([3]),)
(array([4]),)
(array([6]),)
(array([7]),)
(array([], dtype=int64),)
(array([], dtype=int64),)
(array([], dtype=int64),)
0
aweeeezy 21 September 2019, 02:40

1 menjawab

Jawaban Terbaik

Ini harus melakukan trik:

>>> a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.array([0, 1, 3, 4, 7, 8, 9])
>>> n = 3
>>> np.where((a == b[:, np.newaxis] + n).any(axis=0))
(array([3, 4, 6, 7]),)

Idenya adalah untuk menyiarkan a di b karena Anda ingin memeriksa setiap kemungkinan nilai b. Pada akhirnya, ini adalah operasi O(len(a) * len(b)), jadi Anda harus membuat larik 2D berukuran len(a) * len(b) untuk membuat vektor.

Penyiaran dicapai dengan menyisipkan sumbu lain ke b sehingga menjadi vektor kolom:

>>> b
array([0, 1, 3, 4, 7, 8, 9])
>>> b[:, np.newaxis]
array([[0],
       [1],
       [3],
       [4],
       [7],
       [8],
       [9]])

Sehingga sekarang, perbandingan akan mengembalikan array 2D:

>>> a == b[:, np.newaxis] + n
array([[False, False, False,  True, False, False, False, False, False, False],
       [False, False, False, False,  True, False, False, False, False, False],
       [False, False, False, False, False, False,  True, False, False, False],
       [False, False, False, False, False, False, False,  True, False, False],
       [False, False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False, False]])

Indeks i, j di mana ada nilai True berarti b[i] == a[j]. Karena kami hanya peduli dengan indeks a yang cocok dengan nilai apa pun di b, kami hanya mencari apa saja nilai sebenarnya di sepanjang kolom:

>>> (a == b[:, np.newaxis] + n).any(axis=0)
array([False, False, False,  True,  True, False,  True,  True, False, False])

Terakhir, yang diperlukan hanyalah mendapatkan indeks yang sesuai dengan nilai True di sini:

>>> np.where((a == b[:, np.newaxis] + n).any(axis=0))
(array([3, 4, 6, 7]),)

Contoh input Anda telah mengurutkan array, yang berarti Anda sebenarnya dapat melakukan operasi linier di O(len(a) + len(b)), tetapi Anda tidak akan dapat membuat vektorisasi secara umum. Pada dasarnya Anda dapat memiliki indeks ke dalam setiap larik, naikkan satu per satu dalam b dan terus bertambah dalam a hingga Anda mencapai nilai berikutnya. Tentu saja ini akan kurang efisien secara umum dengan array numpy daripada solusi saya di atas untuk array 'tipikal' (yaitu tidak masif).

1
alkasm 21 September 2019, 00:24