Data pelanggan berbentuk tabel — kolom nama berisi teks, kolom umur bilangan bulat, kolom belanja bilangan pecahan — secara alami disimpan sebagai structured array seperti pada Chapter Structured Array, dengan akses field yang bisa diperhalus lewat recarray pada Chapter Record Array. Masalah muncul ketika data itu harus lanjut ke pustaka lain: pandas dan scikit-learn menginginkan matriks dua dimensi bertipe seragam, bukan array satu dimensi berisi record campuran.
Modul numpy.lib.recfunctions adalah kotak peralatan untuk mengubah susunan field structured array. Cakupan bab ini:
structured_to_unstructured— meratakan record menjadi matriks biasa.merge_arrays— menggabungkan dua structured array menjadi satu.append_fields,drop_fields,rename_fields— menambah, membuang, dan mengganti nama field.
Satu hal perlu diatur lebih dulu: cara mengimpor modul ini dengan benar.
Mengimpor numpy.lib.recfunctions dengan Benar #
Berbeda dari sebagian besar modul NumPy, recfunctions tidak ikut termuat saat import numpy. Akibatnya, akses langsung seperti np.lib.recfunctions.structured_to_unstructured tanpa mengimpor modulnya menghasilkan AttributeError. Pola yang kita pakai sepanjang bab adalah impor eksplisit dengan alias rfn:
import numpy as np
try:
f = np.lib.recfunctions.structured_to_unstructured
print("akses langsung berhasil:", f.__name__)
except AttributeError as e:
print("AttributeError:", e)
import numpy.lib.recfunctions as rfn
print("import langsung berhasil:", rfn.structured_to_unstructured.__name__)Output yang Dihasilkan:
AttributeError: module 'numpy.lib' has no attribute 'recfunctions'
import langsung berhasil: structured_to_unstructuredMari kita bedah:
- Baris 3-5: akses atribut
recfunctionspadanp.libdiuji lebih dulu; karena submodul belum termuat di memori, Python melemparAttributeError. - Baris 6-8: penanganan error mencetak pesannya, lalu mengimpor submodul secara langsung. Sejak baris ini pula
np.lib.recfunctionsmulai dikenali, karena impor langsung sekaligus memuat modul tersebut.
structured_to_unstructured: dari Record ke Matriks #
Fungsi yang paling sering dipakai. Structured array yang field-nya semua numerik diratakan menjadi matriks dua dimensi biasa, dengan tipe hasil berupa promosi tipe seluruh field. Bentuk inilah yang diterima estimator pada Chapter NumPy dan scikit-learn:
import numpy as np
import numpy.lib.recfunctions as rfn
pelanggan = np.array(
[("Budi", 34, 250000.0), ("Siti", 29, 180000.0), ("Dewi", 41, 320000.0)],
dtype=[("nama", "U10"), ("umur", "i4"), ("belanja", "f8")],
)
angka = rfn.structured_to_unstructured(pelanggan[["umur", "belanja"]])
print(angka)
print(angka.dtype, angka.shape)
print(angka[:, 1].mean())Output yang Dihasilkan:
[[3.4e+01 2.5e+05]
[2.9e+01 1.8e+05]
[4.1e+01 3.2e+05]]
float64 (3, 2)
250000.0Penjelasan:
- Baris 9 (
pelanggan[["umur", "belanja"]]): mengindeks structured array dengan daftar nama field menghasilkan structured array baru yang hanya berisi dua field numerik itu. - Baris 10 (
rfn.structured_to_unstructured(...)): dua field per record diratakan menjadi satu baris matriks; hasilnyafloat64berbentuk(3, 2)— matriks biasa, bukan lagi kumpulan record. - Baris 12: operasi seperti
meankini berjalan langsung pada kolom matriks.
Angka pada matriks tercetak dalam notasi ilmiah karena NumPy memakai satu format seragam untuk seluruh elemen array; pengaturan tampilan ini dibahas pada Chapter NumPy Print Options.
Kolom Teks vs Kolom Numerik #
Field string <U10 mengubah rencana. structured_to_unstructured tidak menolak field teks — seluruh tipe dipromosikan menjadi string lebar tetap, sehingga angka ikut berubah menjadi teks dan matriksnya tidak bisa dihitung:
import numpy as np
import numpy.lib.recfunctions as rfn
pelanggan = np.array(
[("Budi", 34, 250000.0), ("Siti", 29, 180000.0), ("Dewi", 41, 320000.0)],
dtype=[("nama", "U10"), ("umur", "i4"), ("belanja", "f8")],
)
semua = rfn.structured_to_unstructured(pelanggan)
print(semua.dtype, semua.shape)
print(semua[0])
label = pelanggan["nama"]
angka = rfn.structured_to_unstructured(pelanggan[["umur", "belanja"]])
print(label[0], angka[0, 1])Output yang Dihasilkan:
<U32 (3, 3)
['Budi' '34' '250000.0']
Budi 250000.0Penjelasan:
- Baris 9-11: ketiga field ikut diratakan; dtype hasil
<U32berasal daripromote_types("U10", "i4")yang kemudian dipromosikan lagi dengan"f8". Nilai34dan250000.0kini tersimpan sebagai teks. - Baris 12-14: inilah pemisahan kolom: kolom teks
namadiambil langsung dari structured array sebagai label, sedangkan matriks numerik dirakit dari subset fieldumurdanbelanja. Elemenangka[0, 1]kembali menjadi bilangan pecahan250000.0.
merge_arrays: Menggabungkan Dua Structured Array #
Data pelanggan sering datang terpisah: satu berkas memuat nama dan umur, berkas lain memuat total belanja dan jumlah kunjungan. rfn.merge_arrays menyandingkan dua structured array yang jumlah barisnya sama. Tanpa opsi tambahan, hasilnya field bertingkat dengan nama otomatis f0 dan f1; opsi flatten=True meratakannya menjadi field-field sejajar:
import numpy as np
import numpy.lib.recfunctions as rfn
dasar = np.array(
[("Budi", 34), ("Siti", 29), ("Dewi", 41)],
dtype=[("nama", "U10"), ("umur", "i4")],
)
belanja = np.array(
[(250000.0, 4), (180000.0, 2), (320000.0, 7)],
dtype=[("total", "f8"), ("kunjungan", "i4")],
)
gabungan = rfn.merge_arrays((dasar, belanja), flatten=True)
print(gabungan)
print(gabungan.dtype.names)Output yang Dihasilkan:
[('Budi', 34, 250000., 4) ('Siti', 29, 180000., 2)
('Dewi', 41, 320000., 7)]
('nama', 'umur', 'total', 'kunjungan')Penjelasan:
- Baris 13 (
merge_arrays((dasar, belanja), flatten=True)): record kedua array disandingkan per indeks;flatten=Truemencegah field bertingkat sehingga empat field tampil sejajar dalam satu dtype. - Baris 15 (
dtype.names): nama field hasil gabungan adalah gabungan nama kedua sumber; tanpaflatten, nama otomatisnyaf0danf1. - Jumlah baris kedua array wajib sama, karena penyandingan dilakukan per indeks record.
Menambah, Membuang, dan Mengganti Nama Field #
Tiga fungsi terakhir merapikan skema: append_fields menambah field baru, drop_fields membuang field yang tidak diperlukan, dan rename_fields mengganti nama tanpa menyentuh data:
import numpy as np
import numpy.lib.recfunctions as rfn
pelanggan = np.array(
[("Budi", 34, 250000.0), ("Siti", 29, 180000.0)],
dtype=[("nama", "U10"), ("umur", "i4"), ("belanja", "f8")],
)
dengan_level = rfn.append_fields(pelanggan, "level", ["silver", "emas"], dtypes="U10")
print(dengan_level.dtype.names)
print(dengan_level)
ringkas = rfn.drop_fields(dengan_level, "umur")
ringkas = rfn.rename_fields(ringkas, {"belanja": "total_belanja"})
print(ringkas.dtype.names)
print(ringkas)Output yang Dihasilkan:
('nama', 'umur', 'belanja', 'level')
[('Budi', 34, 250000.0, 'silver') ('Siti', 29, 180000.0, 'emas')]
('nama', 'total_belanja', 'level')
[('Budi', 250000., 'silver') ('Siti', 180000., 'emas')]Penjelasan:
- Baris 9 (
append_fields(...)): fieldlevelditambahkan di posisi akhir dengan data per baris dari list; parameterdtypesmenetapkan tipenya. Untuk nilai isian yang sama di semua baris, kirim array berisi nilai itu — misalnyanp.zeros(2)— karena NumPy 2.1.3 belum menyediakanreplicate_fields, padanan fungsi ini di versi lebih baru. - Baris 12 (
drop_fields): fieldumurdibuang; sisa fieldnyanama,belanja, danlevel. - Baris 13 (
rename_fields): kamus{nama_lama: nama_baru}hanya mengubah label; nilai setiap record tidak bergerak.
Sebagai penutup, peta fungsi yang sudah kita coba:
| Fungsi | Tugas |
|---|---|
structured_to_unstructured | meratakan field numerik menjadi matriks biasa |
merge_arrays | menyandingkan dua structured array per baris |
append_fields | menambah field baru |
drop_fields | membuang field |
rename_fields | mengganti nama field |
Dengan kolom teks dipisah dari matriks numerik, data pelanggan sudah berbentuk yang diharapkan pustaka analisis; jalur lengkapnya diuji pada Chapter NumPy dan scikit-learn.