6.12. Seleksi dan penataan ulang

Reduksi menciutkan array menjadi skalar atau hasil berperingkat lebih rendah. Seleksi mencakup operasi yang memilih elemen mana yang bertahan dan di mana mereka berakhir: pilihan kondisional, pemotongan, pengurutan, pencarian indeks, pengurutan ulang sepanjang sebuah sumbu.

6.12.1. Pilihan kondisional

where() mengembalikan array yang mengambil elemen dari x di mana kondisinya benar dan dari y sebaliknya. Ketiga operand di-broadcast bersama-sama:

a = np.array([1, 2, 3, 4, 5], dtype=np.float)
np.where(a < 3, a, 0.0)
# array([1.0, 2.0, 0.0, 0.0, 0.0])

Ini adalah alat yang tepat untuk operasi "if/else per elemen" tanpa menulis loop Python.

clip() adalah singkatan dari maximum(lo, minimum(a, hi)) -- jenuhkan nilai ke dalam sebuah rentang:

np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])

maximum() dan minimum() mengambil dua operand dan mengembalikan yang lebih besar / lebih kecil per elemen:

np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))

6.12.2. Menemukan indeks

nonzero() mengembalikan koordinat setiap elemen bukan-nol, dibagi menjadi satu array indeks per dimensi. Untuk input 2-D, hasilnya adalah tuple dari dua array: yang pertama berisi indeks baris, yang kedua berisi indeks kolom. Memasangkan keduanya secara kolom memberikan (row, col) dari setiap posisi bukan-nol:

m = np.array([[0, 2, 0],
              [3, 0, 0]], dtype=np.float)
np.nonzero(m)
# (array([0, 1], dtype=uint16), array([1, 0], dtype=uint16))

Entri bukan-nol dalam m adalah m[0, 1] = 2 dan m[1, 0] = 3. Array pertama yang dikembalikan [0, 1] memberikan indeks barisnya; yang kedua [1, 0] memberikan indeks kolomnya. Membaca kedua array berdampingan memulihkan posisi (0, 1) dan (1, 0).

Dua reduksi juga menghasilkan indeks:

  • argmin() / argmax() -- indeks dari elemen terkecil / terbesar.

  • argsort() -- array integer yang akan mengurutkan input sepanjang sumbu yang diberikan (default ke yang terakhir):

    a = np.array([40, 10, 30, 20], dtype=np.uint8)
    idx = np.argsort(a)             # array([1, 3, 2, 0], dtype=uint16)
    a[idx]                          # array([10, 20, 30, 40])
    

    argsort selalu mengembalikan uint16; array yang diurutkan karena itu tidak boleh memiliki lebih dari 65.535 elemen pada sumbu yang diurutkan.

bincount() menghitung kemunculan setiap integer non-negatif dalam input uint8 / uint16 1-D:

histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)

Berguna untuk membangun histogram dari nilai piksel integer kecil tanpa menulis loop Python.

6.12.3. Pengurutan dan penataan ulang

sort() mengembalikan salinan array yang diurutkan sepanjang sumbu yang diberikan (terakhir secara default). Gunakan sort() langsung pada array untuk versi in-place:

np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])

flip() membalikkan urutan sepanjang sumbu yang diberikan (setiap sumbu ketika tidak ada axis yang diteruskan):

np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])

roll() menggeser elemen secara siklik sebesar jumlah yang diberikan. Berguna untuk mengimplementasikan shift register bergaya ring-buffer:

np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])

take() adalah bentuk eksplisit dari fancy indexing -- pilih elemen pada indeks yang sewenang-wenang:

a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.take(a, [0, 2, 4])
# array([10, 30, 50], dtype=uint8)

6.12.4. Penyaringan dan pengeditan struktural

compress() adalah bentuk eksplisit dari pengindeksan boolean -- kembalikan irisan a yang dipilih oleh kondisi boolean:

a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)

delete() mengembalikan salinan dengan entri pada indeks yang diberikan dihapus:

a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)

diff() mengembalikan perbedaan maju diskrit ke-n dari array sepanjang sebuah sumbu. Digunakan untuk menghitung perubahan orde pertama antara sampel yang berdekatan:

samples = np.array([1, 3, 6, 10, 15], dtype=np.float)
np.diff(samples)
# array([2.0, 3.0, 4.0, 5.0])

6.12.5. Biaya setiap operasi

Hampir setiap fungsi di halaman ini mengembalikan array yang baru dialokasikan. Dua pengecualian:

  • sort() mengurutkan di tempat; fungsi bebas sort() mengembalikan salinan yang diurutkan.

  • take() menerima kata kunci out= untuk menulis ke dalam buffer yang sudah ada.

Dalam loop yang berjalan berkali-kali per detik, lebih baik menggunakan sort() in-place dan menggunakan kembali buffer yang sudah dialokasikan di tempat lain. Mask boolean sendiri dialokasikan setiap kali perbandingan dijalankan -- bangun mask sekali dan gunakan kembali di seluruh operasi daripada membangunnya kembali di dalam setiap iterasi.