Rentang nilai

Membuat rentang nilai dengan arange dan linspace beserta jebakan langkahnya.

Daftar isi

Topik ini membahas dua fungsi NumPy untuk membentuk rentang nilai, yaitu np.arange dan np.linspace. Keduanya menghasilkan deretan bilangan beraturan, tetapi kontraknya berbeda. np.arange menghitung dari langkah antarnilai, sedangkan np.linspace menghitung dari jumlah titik yang diinginkan. Setelah topik ini dipahami, pilihan antara keduanya dapat ditentukan berdasarkan kebutuhan, termasuk menghindari jebakan langkah pecahan pada np.arange.

arange: rentang berdasarkan langkah#

np.arange(start, stop, step) menghasilkan bilangan yang dimulai dari start dan naik dengan kenaikan step. Bila hanya satu argumen yang diberikan, rentang dimulai dari nol dengan langkah satu. Bila dua argumen yang diberikan, langkahnya tetap satu sedangkan argumen pertama menjadi batas awal.

python
import numpy as np

print(np.arange(5))
print(np.arange(2, 11, 2))
text Keluaran
[0 1 2 3 4]
[ 2  4  6  8 10]

Keluaran np.arange(5) berisi lima bilangan bulat dari 0 sampai 4, karena nilai default start adalah 0 dan step adalah 1. Spasi tambahan pada [ 2 4 6 8 10] hanyalah perataan kolom agar bilangan dua digit sejajar, bukan penanda nilai yang berbeda. Nilai pada rentang selalu bertipe sama, dalam hal ini bilangan bulat karena ketiga argumennya bulat. Argumen langkah boleh berupa bilangan pecahan, tetapi perilakunya menyimpan jebakan yang dibahas pada bagian Jebakan langkah pecahan.

Fungsi ini sering dipakai sebagai sumber indeks atau penghitung posisi karena keluarannya berupa bilangan bulat berurutan. Nilai stop yang tidak ikut justru cocok untuk keperluan semacam ini, karena rentang indeks Python juga mengikuti pola mulai ikut dan berhenti tidak. Deret posisi untuk mengakses elemen array dengan demikian dapat ditulis dalam satu panggilan fungsi.

Batas akhir tidak disertakan#

Kontrak np.arange memasukkan batas awal dan tidak pernah memasukkan batas akhir. Deret berhenti pada nilai terakhir yang masih berada di bawah stop. Akibatnya, jumlah elemen sama dengan pembulatan ke atas dari (stop - start) / step, bukan pembagian biasa yang mungkin menghasilkan pecahan.

python
import numpy as np

print(np.arange(0, 10, 3))
print(np.arange(10, 0, -3))
text Keluaran
[0 3 6 9]
[10  7  4  1]

Dari 0 sampai di bawah 10 dengan langkah 3, nilai yang muncul adalah 0, 3, 6, dan 9, sedangkan 10 tidak pernah tercapai sehingga tidak ikut. Baris kedua memperlihatkan langkah negatif, yaitu deret menurun dari 10 dengan penurunan 3 sampai tepat di atas 0. Pola yang sama berlaku untuk kedua arah: batas akhir selalu berada di luar hasil.

Ketidaksertaan batas akhir ini sama dengan kebiasaan range pada Python, sehingga pola berpikirnya dapat dipindahkan begitu saja. Perbedaannya, np.arange menghasilkan array siap pakai dalam satu panggilan, bukan objek yang baru menghasilkan nilai saat diulang. Untuk deret yang panjangnya besar, perbedaan bentuk keluaran ini menentukan bagaimana kode berikutnya mengolah nilainya.

Jebakan langkah pecahan#

Perilaku di atas terasa berbeda ketika langkahnya pecahan. Perkiraan manual sering menghitung batas akhir sebagai anggota deret, padahal kontraknya tidak memasukkannya.

python
import numpy as np

a = np.arange(0, 1, 0.2)
print(a)
print(a.size)
b = np.arange(0, 1, 0.1)
print(b)
print(b.size)
text Keluaran
[0.  0.2 0.4 0.6 0.8]
5
[0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
10

Deret pertama memuat lima elemen, bukan enam, karena 1.0 tidak pernah ikut. Deret kedua berhenti di 0.9 karena alasan yang sama. Saat langkahnya pecahan, perkiraan mental sering menghitung batas akhir sebagai anggota deret, padahal kontrak np.arange tetap menyingkirkannya.

python
import numpy as np

c = np.arange(0, 0.9, 0.1)
print(c)
print(c.size)
text Keluaran
[0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8]
9

Angka 0.9 terasa habis dibagi oleh 0.1 karena 0.9 / 0.1 = 9.0, tetapi deretnya tetap berhenti di 0.8. Pada langkah pecahan, jumlah elemen dan elemen terakhir dihitung melalui bilangan pecahan biner yang pembulatannya tidak selalu sesuai perhitungan desimal, sehingga hasilnya dapat berbeda dari perkiraan manual dan dari platform lain. Dokumentasi resmi NumPy menyarankan np.linspace untuk langkah non-integer.

linspace: rentang berdasarkan jumlah titik#

np.linspace(start, stop, num) menghasilkan tepat num titik yang terbagi rata dari start sampai stop, dan kedua batas ikut secara default. Langkah antartitik dihitung otomatis sebagai (stop - start) / (num - 1), sehingga yang dikendalikan adalah jumlah titik, bukan langkahnya.

python
import numpy as np

print(np.linspace(0, 1, 5))
print(np.linspace(0, 1, 5, endpoint=False))
text Keluaran
[0.   0.25 0.5  0.75 1.  ]
[0.  0.2 0.4 0.6 0.8]

Lima titik dari 0 sampai 1 menghasilkan langkah 0.25, dan batas akhir 1.0 ikut sebagai elemen terakhir. Parameter endpoint=False membuang batas akhir, sehingga langkah berubah menjadi (1 - 0) / 5 = 0.2 dan deretnya berhenti di 0.8. Perhatikan bahwa hasil selalu bertipe pecahan, sebab langkah dihitung melalui pembagian.

Langkah yang dihitung otomatis dapat diperiksa langsung dengan retstep=True. Parameter ini mengubah nilai balik menjadi pasangan array dan langkahnya, sehingga keduanya dapat ditampilkan sekaligus.

python
import numpy as np

titik, langkah = np.linspace(10, 20, 5, retstep=True)
print(titik)
print(langkah)
text Keluaran
[10.  12.5 15.  17.5 20. ]
2.5

Lima titik dari 10 sampai 20 menghasilkan langkah 2.5, dan nilai langkah itu dilaporkan sebagai angka kedua dari pasangan hasilnya.

Karena langkah dihitung dari pembagian, keluaran np.linspace selalu bertipe pecahan meskipun start dan stop-nya bulat. Perilaku ini berbeda dari np.arange yang mengikuti tipe argumennya. Perbedaan tersebut perlu diperhitungkan ketika hasilnya akan dipakai sebagai indeks, karena indeks menuntut bilangan bulat.

Memilih antara arange dan linspace#

Kedua fungsi saling melengkapi, dan pilihannya ditentukan oleh sisi yang perlu dikendalikan. Bila langkahnya yang pasti, np.arange lebih langsung. Bila jumlah titiknya yang pasti, atau bila kedua batas harus ikut, np.linspace lebih tepat.

KebutuhanPilihan yang sesuaiAlasan
Langkah bulat yang pasti, misalnya indeks genapnp.arangeLangkah integer bebas dari masalah pembulatan
Jumlah titik yang pasti dengan kedua batas ikutnp.linspaceJumlah titik ditetapkan langsung dan kedua batas termasuk
Rentang bilangan pecahannp.linspaceJumlah titik tidak bergantung pada pembulatan pecahan
Deret menurun dengan langkah tetapnp.arangeLangkah negatif dituliskan langsung tanpa pengaturan tambahan

Aturan praktisnya sederhana. Untuk indeks atau hitungan bulat, np.arange menjadi pilihan alami. Untuk rentang pecahan apa pun, mulailah dari np.linspace karena jumlah elemennya dapat dipastikan dari argumennya sendiri. Perbedaan tipe hasilnya juga mengikuti pola ini, yaitu bulat untuk rentang bulat dari np.arange dan pecahan untuk np.linspace karena langkahnya dihitung melalui pembagian.

Ringkasan#

  • np.arange(start, stop, step) membentuk deret dari start dengan kenaikan step. Dengan satu argumen, rentang dimulai dari nol dengan langkah satu, dan langkah negatif menghasilkan deret menurun.
  • Batas akhir np.arange tidak pernah ikut, sehingga jumlah elemennya adalah pembulatan ke atas dari (stop - start) / step.
  • Langkah pecahan pada np.arange membuat jumlah elemen mudah meleset karena pembulatan pecahan biner, sehingga np.linspace lebih andal untuk rentang pecahan.
  • np.linspace(start, stop, num) menghasilkan tepat num titik termasuk kedua batas, dengan endpoint=False untuk membuang batas akhir dan retstep=True untuk melaporkan langkahnya.

Referensi#