Semua teknik hemat memori pada Chapter-Chapter sebelumnya masih menuntut satu syarat: tabelnya muat di RAM. Ketika file CSV berukuran belasan gigabyte dan komputer hanya punya memori seperempatnya, membaca seluruh file sekaligus bukan pilihan. Solusi pandas adalah parameter chunksize pada read_csv(): alih-alih mengembalikan DataFrame utuh, method tersebut mengembalikan iterator yang menghasilkan potongan DataFrame berukuran tetap. Chapter ini mempraktikkan pola pemrosesan per potongan — agregasi, filter lalu gabung — dan membuktikan hasilnya identik dengan membaca file sekaligus.
Iterator, Bukan DataFrame #
Skrip berikut membuat file CSV 120.000 baris secara runtime (deterministik, dari seed tetap) di folder sementara, lalu memprosesnya dengan chunksize=30_000 — pada pekerjaan nyata, file ini berada di disk dan berukuran jauh lebih besar dari memori:
import shutil
import tempfile
from pathlib import Path
import numpy as np
import pandas as pd
# Bangun file CSV 120.000 baris (deterministik) di folder sementara
rng = np.random.default_rng(42)
n = 120_000
df = pd.DataFrame(
{
"id_pesanan": [f"TRX-{i:06d}" for i in range(n)],
"kota": rng.choice(["Jakarta", "Bandung", "Surabaya", "Medan", "Semarang"], size=n),
"produk": rng.choice(
["Beras", "Minyak Goreng", "Gula Pasir", "Kopi", "Telur", "Tepung Terigu", "Sabun", "Sarden"],
size=n,
),
"jumlah": rng.integers(1, 11, size=n),
"harga": rng.choice([15000, 25000, 40000, 55000, 70000], size=n),
}
)
df["total"] = df["jumlah"] * df["harga"]
folder = tempfile.mkdtemp()
jalur = Path(folder) / "transaksi_besar.csv"
df.to_csv(jalur, index=False)
print("ukuran file:", f"{jalur.stat().st_size:,}", "byte")
print()
# 1. chunksize menghasilkan iterator, bukan DataFrame
reader = pd.read_csv(jalur, chunksize=30_000)
print("tipe objek:", type(reader).__name__)
print()
# 2. Agregasi per chunk: jumlahkan hasil tiap potongan
jumlah_baris = 0
total_semua = 0
for potongan in reader:
jumlah_baris += len(potongan)
total_semua += int(potongan["total"].sum())
print("baris terkumpul:", jumlah_baris)
print("total terkumpul:", f"{total_semua:,}")
print()
# 3. get_chunk: ambil potongan dengan ukuran bebas
reader2 = pd.read_csv(jalur, chunksize=30_000)
p1 = reader2.get_chunk(10_000)
p2 = reader2.get_chunk()
print("get_chunk(10000):", p1.shape)
print("get_chunk() berikutnya:", p2.shape)
reader2.close()
print()
# 4. Pola filter-then-concat
potongan_lolos = []
for potongan in pd.read_csv(jalur, chunksize=30_000):
potongan_lolos.append(potongan[potongan["total"] > 500_000])
hasil = pd.concat(potongan_lolos, ignore_index=True)
print("baris lolos filter:", len(hasil))
print("total lolos:", f"{int(hasil['total'].sum()):,}")
print()
# 5. Hasilnya identik dengan membaca seluruh file sekaligus
penuh = pd.read_csv(jalur)
penuh_lolos = penuh[penuh["total"] > 500_000]
print("identik dgn baca penuh:", len(hasil) == len(penuh_lolos) and int(hasil["total"].sum()) == int(penuh_lolos["total"].sum()))
shutil.rmtree(folder)
print("file csv sementara dihapus")Output yang Dihasilkan:
ukuran file: 5,093,605 byte
tipe objek: TextFileReader
baris terkumpul: 120000
total terkumpul: 27,041,560,000
get_chunk(10000): (10000, 6)
get_chunk() berikutnya: (30000, 6)
baris lolos filter: 9548
total lolos: 5,819,970,000
identik dgn baca penuh: True
file csv sementara dihapusMari kita telaah baris-baris pentingnya:
- Baris 24-27 (pembuatan file uji): DataFrame 120.000 baris ditulis ke CSV di folder
tempfilelalu dihapus di akhir skrip; ukurannya 5.093.605 byte. Pada skenario nyata, langkah ini digantikan file yang sudah ada di disk. - Baris 31-32 (
chunksize=30_000): hasilnya bukan DataFrame, melainkan objekTextFileReader— iterator yang baru membaca potongan berikutnya ketika diminta. Memori yang dipakai sebanding dengan satu potongan, bukan seluruh file. - Baris 36-42 (agregasi per potongan): setiap iterasi menghasilkan DataFrame 30.000 baris; kita menghitung
len()dan.sum()di dalam loop, lalu menjumlahkan hasil antar potongan. Kumpulan empat potongan menghasilkan 120.000 baris dan total 27.041.560.000. - Baris 45-51 (
get_chunk): methodget_chunk(10_000)mengambil potongan berukuran bebas (10000, 6), danget_chunk()berikutnya mengambil potongan berukuran penuh (30000, 6) dari posisi yang sama. Method ini berguna saat butuh pratinjau lalu proses berkelanjutan. - Baris 54-58 (filter lalu gabung): pola filter-then-concat menyaring tiap potongan (
total > 500_000), mengumpulkan hasilnya dalam list, lalupd.concat(..., ignore_index=True)menggabungkannya — 9.548 baris lolos dengan total 5.819.970.000, dan hanya potongan kecil yang pernah ada di memori sekaligus. - Baris 62-66 (pembuktian): hasil filter per potongan dibandingkan dengan membaca seluruh file lalu memfilter — jumlah baris dan totalnya sama (
True). Chunking mengubah cara memori dipakai, bukan hasilnya.
Tiga Pola Pemrosesan Chunk #
| Tujuan | Pola di dalam loop |
|---|---|
| Statistik seluruh file | hitung sum() / count() / max() per potongan, gabungkan hasilnya |
| Subset baris tertentu | filter tiap potongan, kumpulkan di list, pd.concat di akhir |
| Transformasi lalu simpan | proses tiap potongan, tulis hasilnya bertahap ke file/database |
Chapter berikutnya menuntaskan sisi lain dari read_csv(): parameter-parameter yang membuat pembacaan file biasa — yang tetap muat di memori — berjalan lebih cepat dan lebih hemat.
Referensi resmi untuk pendalaman: pandas.read_csv , pandas.concat , dan panduan IO tools .