Pada Chapter Structured Array, field diakses dengan kurung siku: pegawai["nama"]. Penulisan itu jelas, tetapi panjang saat dipakai berulang di dalam ekspresi. Record array (np.recarray) adalah varian structured array yang mengizinkan akses field lewat notasi atribut: pegawai.nama. Di balik layar keduanya identik — memori, dtype, dan itemsize persis sama — yang berbeda hanya lapisan aksesnya.
Karena kemudahan itu tidak gratis, bab ini juga membahas biayanya: setiap akses atribut membangun view baru, dan nama field yang bertabrakan dengan atribut bawaan bisa menjadi tidak terjangkau. Setelah memahami pertukaran tersebut, kita dapat memilih kapan recarray membantu dan kapan akses field biasa lebih tepat.
Dari Structured Array ke Record Array #
Structured array biasa dapat diubah menjadi record array dengan method view(np.recarray). Tidak ada penyalinan data — keduanya berbagi buffer memori yang sama:
import numpy as np
dtype = np.dtype([("nama", "U10"), ("umur", "i4"), ("gaji", "f8")])
pegawai = np.array(
[("Budi", 34, 8500000.0), ("Siti", 29, 9200000.0), ("Dewi", 41, 7800000.0)],
dtype=dtype,
)
rec = pegawai.view(np.recarray)
print(type(rec))
print(rec.nama)
print(rec[0].gaji)
print(rec.nama is rec.nama)Output yang Dihasilkan:
<class 'numpy.rec.recarray'>
['Budi' 'Siti' 'Dewi']
8500000.0
FalseMari kita bedah:
- Baris 8 (
pegawai.view(np.recarray)): interpreter membungkus buffer yang sama dengan kelasnumpy.rec.recarray, tanpa menyalin satu byte pun. - Baris 10 (
rec.nama): notasi atribut mengembalikan fieldnamasebagai array string — hasilnya identik denganpegawai["nama"]. - Baris 11 (
rec[0].gaji): satu record pun ikut nyaman diakses;numpy.voiddari structured array kini juga mendukung akses atribut. - Baris 12:
rec.nama is rec.namamenghasilkanFalse— setiap akses atribut membangun objek view baru. Inilah sumber biaya performa yang dibahas di akhir bab.
Membuat Record Array Langsung #
Selain mengubah structured array yang sudah ada, np.recarray dapat membuat array baru langsung, dan np.rec.fromarrays dapat menyusun record dari beberapa array kolom yang terpisah:
import numpy as np
dtype = np.dtype([("nama", "U10"), ("umur", "i4"), ("gaji", "f8")])
r = np.recarray(2, dtype=dtype)
r.nama = ["Andi", "Rina"]
r.gaji = [6000000.0, 7500000.0]
print(r)
r2 = np.rec.fromarrays([["Budi", "Siti"], [34, 29]], names="nama,umur")
print(r2)
print(r2.umur.dtype)Output yang Dihasilkan:
[('Andi', 0, 6000000.) ('Rina', 0, 7500000.)]
[('Budi', 34) ('Siti', 29)]
int64Penjelasan singkat:
- Baris 4 (
np.recarray(2, dtype=dtype)): wadah dua record dialokasikan; field yang belum diisi tetap bernilai nol, terlihat dariumuryang masih0. - Baris 5-6: penugasan via atribut sama saja dengan penugasan per field pada structured array.
- Baris 8 (
np.rec.fromarrays(...)): dua list kolom digabung menjadi record; nama field diambil dari stringnamesyang dipisah koma. NumPy memilih tipe sendiri di sini, sehinggaumurmenjadiint64— berbeda dari skemai4yang kita tetapkan manual.
Jebakan Nama Field yang Bertabrakan #
Atribut recarray sudah membawa method dan properti bawaan: size, shape, mean, sum, dan seterusnya. Jika sebuah field dinamai sama, notasi atribut akan mengembalikan atribut bawaan, bukan field kita:
import numpy as np
dt = np.dtype([("nama", "U5"), ("size", "i4")])
r = np.recarray(1, dtype=dt)
r[0].nama = "Budi"
r[0].size = 99
print(r)
print(r.size)
print(r["size"])Output yang Dihasilkan:
[('Budi', 99)]
1
[99]Bedah hasilnya:
- Baris 5-6: field
sizediisi99melalui akses per recordr[0].size— level record masih berhasil karena tidak ada tabrakan di sana. - Baris 8 (
r.size): hasilnya1, yaitu jumlah elemen array, bukan99. Notasi atribut kalah oleh properti bawaanndarray.size. - Baris 9 (
r["size"]): akses kurung siku selalu menunjuk field, sehingga99kembali dengan aman.
Biaya Akses Atribut dan Praktik Baik #
Perbedaan rec.nama dan rec["nama"] dapat dirangkum:
| Aspek | rec.nama (atribut) | rec["nama"] (field) |
|---|---|---|
| Keterbacaan ekspresi | lebih ringkas | lebih eksplisit |
| Biaya per akses | + overhead pembuatan view | lebih tipis |
| Nama yang bertabrakan | berisiko kembali ke atribut bawaan | selalu menunjuk field |
| Data di memori | identik | identik |