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:

python
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:

text
<class 'numpy.rec.recarray'>
['Budi' 'Siti' 'Dewi']
8500000.0
False

Mari kita bedah:

  1. Baris 8 (pegawai.view(np.recarray)): interpreter membungkus buffer yang sama dengan kelas numpy.rec.recarray, tanpa menyalin satu byte pun.
  2. Baris 10 (rec.nama): notasi atribut mengembalikan field nama sebagai array string — hasilnya identik dengan pegawai["nama"].
  3. Baris 11 (rec[0].gaji): satu record pun ikut nyaman diakses; numpy.void dari structured array kini juga mendukung akses atribut.
  4. Baris 12: rec.nama is rec.nama menghasilkan False — 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:

python
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:

text
[('Andi', 0, 6000000.) ('Rina', 0, 7500000.)]
[('Budi', 34) ('Siti', 29)]
int64

Penjelasan singkat:

  1. Baris 4 (np.recarray(2, dtype=dtype)): wadah dua record dialokasikan; field yang belum diisi tetap bernilai nol, terlihat dari umur yang masih 0.
  2. Baris 5-6: penugasan via atribut sama saja dengan penugasan per field pada structured array.
  3. Baris 8 (np.rec.fromarrays(...)): dua list kolom digabung menjadi record; nama field diambil dari string names yang dipisah koma. NumPy memilih tipe sendiri di sini, sehingga umur menjadi int64 — berbeda dari skema i4 yang 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:

python
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:

text
[('Budi', 99)]
1
[99]

Bedah hasilnya:

  1. Baris 5-6: field size diisi 99 melalui akses per record r[0].size — level record masih berhasil karena tidak ada tabrakan di sana.
  2. Baris 8 (r.size): hasilnya 1, yaitu jumlah elemen array, bukan 99. Notasi atribut kalah oleh properti bawaan ndarray.size.
  3. Baris 9 (r["size"]): akses kurung siku selalu menunjuk field, sehingga 99 kembali dengan aman.

Biaya Akses Atribut dan Praktik Baik #

Perbedaan rec.nama dan rec["nama"] dapat dirangkum:

Aspekrec.nama (atribut)rec["nama"] (field)
Keterbacaan ekspresilebih ringkaslebih eksplisit
Biaya per akses+ overhead pembuatan viewlebih tipis
Nama yang bertabrakanberisiko kembali ke atribut bawaanselalu menunjuk field
Data di memoriidentikidentik