Satu berkas .npy hanya menampung satu array, padahal hasil pekerjaan nyata sering berupa satu set array yang saling terkait: pembacaan sensor lengkap dengan waktunya, daftar harga beserta nama komoditasnya, atau bobot beberapa layer sekaligus. Menyimpan semuanya sebagai berkas terpisah memaksa kita mengelola puluhan nama berkas dan menjaga konsistensinya sendiri.

Solusi NumPy adalah arsip .npz: satu berkas ZIP yang di dalamnya berisi beberapa berkas .npy, satu array per anggota. Bab ini membahas dua fungsi pengemasnya — np.savez dan np.savez_compressed — beserta aturan penamaan array di dalam arsip.

Mengemas dengan np.savez #

np.savez menerima nama arsip lalu array-array yang akan dikemas. Memberi nama array dilakukan lewat argumen kata kunci (keyword argument); nama itu menjadi kunci yang dipakai saat memuat:

python
import numpy as np

suhu = np.array([27.5, 28.1, 26.9, 30.2])
harga = np.array([15000, 18000, 35000], dtype=np.int64)
np.savez("arsip.npz", suhu=suhu, harga=harga)
data = np.load("arsip.npz")
print(data.files)
print(data["suhu"])
print(data["harga"])

Output yang Dihasilkan:

text
['suhu', 'harga']
[27.5 28.1 26.9 30.2]
[15000 18000 35000]

Mari kita bedah:

  1. Baris 5 (np.savez("arsip.npz", suhu=suhu, harga=harga)): NumPy mengemas dua array ke dalam satu berkas ZIP; setiap anggota arsip adalah berkas .npy bernama suhu.npy dan harga.npy.
  2. Baris 6-7 (np.load + data.files): arsip dimuat dan atribut .files mendaftar nama semua anggota sesuai urutan saat dikemas.
  3. Baris 8-9: setiap anggota diakses dengan indeks kurung siku seperti dict; isi yang kembali adalah ndarray utuh dengan dtype aslinya.

Penamaan Otomatis arr_0, arr_1 #

Bagaimana jika array dikirim tanpa nama? np.savez tetap menerimanya dan memberi nama bawaan secara berurutan: arr_0, arr_1, dan seterusnya:

python
import numpy as np

suhu = np.array([27.5, 28.1])
harga = np.array([15000, 18000], dtype=np.int64)
np.savez("tanpa_nama.npz", suhu, harga)
data = np.load("tanpa_nama.npz")
print(data.files)
print(data["arr_0"])

Output yang Dihasilkan:

text
['arr_0', 'arr_1']
[27.5 28.1]

Penjelasan tiap bagian:

  1. Baris 5 (np.savez("tanpa_nama.npz", suhu, harga)): dua array dikirim sebagai argumen posisi tanpa kata kunci.
  2. Baris 6-7: daftar anggota menunjukkan nama bawaan arr_0 dan arr_1; urutannya mengikuti urutan argumen.
  3. Baris 8: array pertama tetap bisa diakses, tetapi kuncinya tidak bermakna. Ketika arsip akan dibaca oleh manusia atau skrip lain, selalu beri nama eksplisit.

Kompresi dengan np.savez_compressed #

Data hasil pengukuran sering berulang: harga yang stagnan, stok yang tetap, pembacaan yang stabil. Pola berulang seperti ini memampatkan dengan sangat efisien. np.savez_compressed bekerja identik dengan np.savez, tetapi setiap anggota arsip dikompresi dengan algoritme ZIP:

python
import numpy as np
import os

data = np.tile(np.array([[15000, 18000, 35000],
                         [15200, 17900, 35100]]), (50000, 1))
np.savez("biasa.npz", data=data)
np.savez_compressed("kompres.npz", data=data)
print("npz    :", os.path.getsize("biasa.npz"), "byte")
print("npz.z  :", os.path.getsize("kompres.npz"), "byte")
print("lebih kecil:", os.path.getsize("kompres.npz") < os.path.getsize("biasa.npz"))

Output yang Dihasilkan:

text
npz    : 2400262 byte
npz.z  : 7245 byte
lebih kecil: True

Mari kita telaah:

  1. Baris 5-6 (np.tile(..., (50000, 1))): matriks harga 2 baris diulang hingga 100.000 baris, menyimulasikan log harga yang sangat berulang — 2,4 juta byte data inti.
  2. Baris 7-8: arsip yang sama disimpan dua kali, tanpa dan dengan kompresi.
  3. Baris 9-11: ukuran berkas terkompresi hanya 7.245 byte — data yang berulang bisa memampat hingga ratusan kali lebih kecil. Untuk data acak, penghematannya jauh lebih kecil; kompresi selalu berbayar waktu baca-tulis.
FungsiIsi berkasKompresiCocok untuk
np.savesatu arraytidaksatu hasil perhitungan
np.savezbanyak array dalam ZIPtidakarsip yang sering dibaca
np.savez_compressedbanyak array dalam ZIPya (deflate)data berulang, arsip cadangan