Data teks dari dunia nyata jarang serapi contoh buku: ada baris keterangan di bagian atas log, ada sel yang kosong karena sensor gagal membaca, dan ada angka desimal yang ditulis dengan koma mengikuti kebiasaan Indonesia (27,5). np.loadtxt berhenti bekerja pada ketidakrapian semacam ini, karena fungsinya mengasumsikan setiap baris berisi angka lengkap.
Untuk berkas dengan struktur tak rapi, NumPy menyediakan np.genfromtxt — pembaca teks yang lebih lentur: bisa memberi nama kolom, mengganti nilai kosong, melewati baris keterangan, dan mengubah format angka lewat converter. Bab ini membahas parameter-parameternya satu per satu.
names=True dan Structured Array #
Parameter names=True memberi tahu genfromtxt bahwa baris pertama berisi nama kolom, bukan data. Hasilnya bukan array biasa, melainkan structured array yang tiap barisnya menyimpan beberapa kolom dengan nama:
import numpy as np
from io import StringIO
teks = """hari,beras,gula
1,15000,18000
2,15200,17900
3,15300,18100"""
data = np.genfromtxt(StringIO(teks), delimiter=",", names=True)
print(data.dtype.names)
print(data["beras"])
print(data["hari"].mean())Output yang Dihasilkan:
('hari', 'beras', 'gula')
[15000. 15200. 15300.]
2.0Mari kita bedah:
- Baris 3-7 (
teks = """..."""): string CSV dibungkusStringIOagar bisa dibaca seperti berkas tanpa benar-benar menulis ke disk — pola yang nyaman untuk contoh dan pengujian. - Baris 8 (
names=True): baris pertama dijadikan nama kolom;data.dtype.namesmengembalikan tuple('hari', 'beras', 'gula'). - Baris 9-10: kolom diakses lewat namanya —
data["beras"]— bukan lewat indeks angka, sehingga kode lebih mudah dibaca. - Baris 11: karena semua nilai dibaca sebagai
float64(dtype bawaangenfromtxt), agregasi seperti.mean()langsung bisa dijalankan.
Menangani Nilai Kosong #
Sel kosong pada CSV adalah kasus paling umum di data lapangan. Secara bawaan, genfromtxt mengisi sel kosong dengan nan untuk kolom numerik — perilaku yang sehat karena kekosongan memang tidak boleh diam-diam dianggap nol. Bila kosong memang berarti nol, kita bisa menentukannya lewat filling_values:
import numpy as np
from io import StringIO
teks = """hari,gula
1,18000
2,
3,18100"""
data = np.genfromtxt(StringIO(teks), delimiter=",", names=True)
print(data["gula"])
data2 = np.genfromtxt(StringIO(teks), delimiter=",", names=True,
filling_values=0)
print(data2["gula"])Output yang Dihasilkan:
[18000. nan 18100.]
[18000. 0. 18100.]Penjelasan tiap bagian:
- Baris 4: baris kedua data sengaja dibiarkan tanpa nilai setelah koma — sel gula kosong.
- Baris 7: pembacaan pertama menghasilkan
nanpada posisi yang kosong; satunancukup untuk membuat agregasi ikutnan, jadi sengaja tidak disembunyikan. - Baris 8-9 (
filling_values=0): pembacaan kedua mengganti setiap sel kosong dengan0; parameter ini juga bisa berupa dict per kolom, mis.filling_values={"gula": 0}.
Melewati Baris Keterangan #
Log hasil instrumentasi sering diawali beberapa baris keterangan sebelum tabelnya dimulai. Parameter skip_header melewati sejumlah baris pertama; parameter pasangannya skip_footer memotong baris dari akhir:
import numpy as np
from io import StringIO
teks = """# log sensor stasiun 3
# Jakarta, pagi
hari,suhu
1,27.5
2,28.1"""
data = np.genfromtxt(StringIO(teks), delimiter=",", names=True,
skip_header=2)
print(data)Output yang Dihasilkan:
[(1., 27.5) (2., 28.1)]Mari kita telaah:
- Baris 4-5: dua baris pertama adalah keterangan yang diawali
#— di sinilahskip_header=2diperlukan, karenagenfromtxttidak menganggap baris itu komentar secara bawaan. - Baris 6-8: setelah dua baris keterangan dilewati, baris
hari,suhumenjadi nama kolom dan dua baris berikutnya menjadi data. - Baris keluaran: hasilnya structured array dua baris; setiap baris dicetak sebagai tuple bernama kolom.
converters untuk Format Angka Lokal #
Angka Indonesia lazim menulis desimal dengan koma: 27,5. Pembaca bawaan tidak mengenal format itu, tetapi parameter converters memungkinkan kita menyuntikkan fungsi pengubah per kolom:
import numpy as np
from io import StringIO
teks = """suhu
27,5
28,1
26,9"""
data = np.genfromtxt(StringIO(teks), skip_header=1,
converters={0: lambda s: float(s.replace(",", "."))})
print(data)
print(data.dtype)Output yang Dihasilkan:
[27.5 28.1 26.9]
float64Penjelasan tiap bagian:
- Baris 6 (
converters={0: ...}): dict ini memetakan indeks kolom ke fungsi pengubah; kolom0diolah oleh lambda yang mengganti koma dengan titik sebelumfloat()mengubahnya menjadi bilangan. - Baris 6 (catatan penting): fungsi converter menerima setiap sel dalam bentuk
str, sehinggas.replace(",", ".")bekerja langsung pada teks. - Baris 8-9: hasilnya array
float64biasa — setelah konversi, data siap dihitung tanpa jejak format lokal.
Beberapa parameter genfromtxt lain yang sering dipakai:
usecols=(0, 2)— membaca sebagian kolom saja, sama seperti padaloadtxt.autostrip=True— membuang spasi berlebih di sekeliling tiap sel.max_rows=n— membatasi jumlah baris data yang dibaca, berguna untuk mengintip berkas besar.