Data hasil perhitungan sering keluar dari batas wajar: operasi pencahayaan bisa mendorong nilai piksel melewati 255, sensor suhu bisa mencatat angka di bawah batas terendah alat, dan hasil model bisa keluar dari rentang yang diminta. Teknik pembatasan ini disebut clamping (menjepit nilai ke dalam rentang), dan di NumPy satu fungsi menangani semuanya: np.clip.
Beberapa contoh penggunaannya:
- Menjaga nilai piksel gambar tetap pada rentang 0-255 setelah operasi kecerahan.
- Membatasi persentase diskon agar tidak melewati 0-100.
- Menahan keluaran model agar berada di dalam rentang kalibrasi sensor.
Dasar np.clip: Menjepit ke Rentang Minimum-Maksimum #
np.clip(a, a_min, a_max) memeriksa setiap elemen: nilai di bawah a_min diganti a_min, nilai di atas a_max diganti a_max, dan nilai di dalam rentang dibiarkan utuh. Contoh klasiknya adalah peningkatan kecerahan gambar 8-bit yang tidak boleh keluar dari rentang 0-255:
import numpy as np
pixel = np.array([80, 120, 200, 240])
kecerahan = np.clip(pixel + 50, 0, 255)
print(kecerahan)
rentang = np.array([-20, 5, 90, 130, 300])
print(np.clip(rentang, 0, 255))Output yang Dihasilkan:
[130 170 250 255]
[ 0 5 90 130 255]Mari kita bedah:
- Baris 3 (
pixel + 50): penjumlahan ufunc menghasilkan array sementara[130, 170, 250, 290]— piksel terakhir melewati batas 255. - Baris 4 (
np.clip(..., 0, 255)): nilai290dijepit turun menjadi255; tanpa clip, nilai tersebut tidak valid untuk gambar 8-bit. - Baris 7 (
np.clip(rentang, 0, 255)):-20diangkat ke0dan300diturunkan ke255, sementara tiga nilai tengah tidak tersentuh.
Perlu diketahui, np.clip mengembalikan array baru dan tidak mengubah array input; dtype keluarannya mengikuti dtype input, sehingga array integer tetap integer setelah dijepit. Bila hasil ingin ditulis ke buffer yang sudah ada, gunakan parameter out untuk menghindari alokasi tambahan.
Satu Batas Saja dengan None #
Sering kali hanya satu sisi yang perlu dijaga. Isi a_min atau a_max dengan None untuk menonaktifkan batas pada sisi tersebut:
import numpy as np
suhu = np.array([-8.0, 12.5, 31.0, 45.5])
print(np.clip(suhu, a_min=None, a_max=40.0))
print(np.clip(suhu, a_min=0.0, a_max=None))Output yang Dihasilkan:
[-8. 12.5 31. 40. ]
[ 0. 12.5 31. 45.5]Baris pertama hanya menjepit batas atas 40.0, sehingga -8.0 lolos tanpa diubah. Baris kedua hanya menjaga batas bawah 0.0, sehingga 45.5 tetap dipertahankan. Kombinasi ini berguna untuk menyaring outlier satu arah tanpa memengaruhi sisi lain.
clip Setara maximum(minimum(…)) #
Perilaku np.clip identik dengan menggabungkan dua ufunc pembanding: jepit dulu dengan np.minimum (batas atas), lalu dengan np.maximum (batas bawah). Kita verifikasi kesetaraannya pada array yang sama:
import numpy as np
x = np.array([-5, 0, 50, 300])
hasil_clip = np.clip(x, 0, 255)
hasil_manual = np.maximum(np.minimum(x, 255), 0)
print(hasil_clip)
print(hasil_manual)
print(np.array_equal(hasil_clip, hasil_manual))Output yang Dihasilkan:
[ 0 0 50 255]
[ 0 0 50 255]
Truenp.array_equal mengembalikan True, membuktikan kedua bentuk menghasilkan array yang sama persis. Susunan np.maximum di dalam dan np.minimum di luar inilah yang meniru np.clip; kesalahan yang sering terjadi adalah menukar posisi batas pada np.clip sendiri — np.clip(x, 255, 0) menjadikan seluruh elemen 0 karena batas atas 0 diterapkan paling akhir dan menimpa batas bawah.
Tabel berikut merangkum kapan masing-masing bentuk lebih cocok:
| Bentuk | Cocok untuk |
|---|---|
np.clip(a, min, max) | Satu langkah terbaca, mendukung None per sisi |
np.maximum(np.minimum(a, max), min) | Kode tanpa fungsi khusus, atau saat nilai batas berupa array |
Pada bentuk manual, a_min dan a_max juga boleh berupa array seukuran a, sehingga batas yang berbeda per elemen (misal rentang normal tiap sensor) tetap bisa dijepit dalam satu panggilan.