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:

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

text
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 dihapus

Mari kita telaah baris-baris pentingnya:

  1. Baris 24-27 (pembuatan file uji): DataFrame 120.000 baris ditulis ke CSV di folder tempfile lalu dihapus di akhir skrip; ukurannya 5.093.605 byte. Pada skenario nyata, langkah ini digantikan file yang sudah ada di disk.
  2. Baris 31-32 (chunksize=30_000): hasilnya bukan DataFrame, melainkan objek TextFileReader — iterator yang baru membaca potongan berikutnya ketika diminta. Memori yang dipakai sebanding dengan satu potongan, bukan seluruh file.
  3. 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.
  4. Baris 45-51 (get_chunk): method get_chunk(10_000) mengambil potongan berukuran bebas (10000, 6), dan get_chunk() berikutnya mengambil potongan berukuran penuh (30000, 6) dari posisi yang sama. Method ini berguna saat butuh pratinjau lalu proses berkelanjutan.
  5. Baris 54-58 (filter lalu gabung): pola filter-then-concat menyaring tiap potongan (total > 500_000), mengumpulkan hasilnya dalam list, lalu pd.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.
  6. 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 #

TujuanPola di dalam loop
Statistik seluruh filehitung sum() / count() / max() per potongan, gabungkan hasilnya
Subset baris tertentufilter tiap potongan, kumpulkan di list, pd.concat di akhir
Transformasi lalu simpanproses 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 .