Ekstraksi adalah tahap pertama setiap pipeline: data dibawa keluar dari sumber sebelum bisa ditransformasi. Tugasnya terdengar sepele, tetapi pilihan cara ekstraksi menentukan dua hal besar — seberapa berat beban yang kita timpakan ke sistem sumber, dan seberapa banyak memori yang kita pakai di server pipeline. Mengambil seluruh tabel berjuta baris sekaligus bisa membebani database produksi toko dan menghabiskan memori; sebaliknya, mengambil terlalu sedikit data membuat analisis tidak valid. Chapter ini membahas ragam sumber data, dua teknik penyelamatan sumber daya (seleksi kolom dan sampling), lalu ekstraksi bertahap dengan generator untuk file besar.

Sumber Data: File, Database, dan API #

Sebelum menulis kode, kita perlu tahu dari mana data bisa datang. Tiga keluarga sumber berikut menutup hampir semua kasus pipeline batch:

  • File — CSV, JSON, Parquet hasil ekspor atau unduhan. Termurah dibaca, tetapi tidak bisa diquery; seluruh isi harus dibaca berurutan.
  • Database — tabel operasional (pelanggan, produk, pesanan) di PostgreSQL atau sistem sejenis. Bisa diquery dengan filter dan proyeksi kolom, sehingga seleksi bisa digeser ke sumber.
  • API — endpoint HTTP milik layanan pihak ketika, misalnya status pengiriman dari API logistik. Biasanya dibatasi laju permintaan (rate limit) dan mengembalikan data bertahap per halaman.

Prinsip umumnya: lakukan seleksi sedekat mungkin dengan sumber. Memfilter kolom di query database jauh lebih murah daripada mengekstrak semua kolom lalu membuang sebagian besar di server pipeline.

Seleksi Kolom dan Sampling #

Sumber percobaan kita adalah pelanggan.csv berikut — enam pelanggan dengan lima kolom, hasil ekspor harian dari sistem operasional.

text pelanggan.csv
pelanggan_id,nama,kota,umur,email
1,Budi,Jakarta,29,[email protected]
2,Siti,Bandung,34,[email protected]
3,Dewi,Jakarta,27,[email protected]
4,Andi,Surabaya,41,[email protected]
5,Rina,Yogyakarta,23,[email protected]
6,Fajar,Bandung,38,[email protected]

Dua teknik ringan membuat ekstraksi hemat. Seleksi kolom hanya membawa kolom yang benar-benar dianalisis; sampling hanya membawa sebagian baris untuk keperluan eksplorasi. Kode berikut membaca data pelanggan, memilih dua kolom, lalu mengambil contoh acak tiga dari enam pelanggan.

python ekstraksi dengan seleksi kolom dan sampling
import csv
import random

# Baca seluruh kolom dari sumber
with open("pelanggan.csv", newline="", encoding="utf-8") as berkas:
    baris = list(csv.DictReader(berkas))

# Seleksi kolom: hanya nama dan kota yang dibutuhkan analisis
terpilih = [{"nama": b["nama"], "kota": b["kota"]} for b in baris]
print("Seleksi kolom:", terpilih[:3], "...")

# Sampling: 3 dari 6 pelanggan untuk eksplorasi awal
random.seed(42)
contoh = random.sample(terpilih, 3)
print("Hasil sampling (seed 42):", contoh)

Output yang Dihasilkan:

text
Seleksi kolom: [{'nama': 'Budi', 'kota': 'Jakarta'}, {'nama': 'Siti', 'kota': 'Bandung'}, {'nama': 'Dewi', 'kota': 'Jakarta'}] ...
Hasil sampling (seed 42): [{'nama': 'Fajar', 'kota': 'Bandung'}, {'nama': 'Budi', 'kota': 'Jakarta'}, {'nama': 'Rina', 'kota': 'Yogyakarta'}]

Comprehension di baris seleksi membangun daftar baru yang hanya berisi kunci nama dan kota; kolom umur dan email tidak pernah ikut. Pada sampling, random.seed(42) membuat hasil dapat diulang — tanpa seed, setiap eksekusi menghasilkan contoh berbeda dan temuan eksplorasi sulit direproduksi. Detail kedua fungsi ini tersedia di dokumentasi modul csv dan dokumentasi modul random .

Ekstraksi Bertahap dengan Generator #

Untuk file berukuran besar, pola list(csv.DictReader(...)) pada chapter sebelumnya berbahaya: seluruh isi file dimuat ke memori sekaligus. Solusinya adalah ekstraksi bertahap (chunked extraction) — data dibaca sedikit demi sedikit, diproses, baru dilanjutkan ke bagian berikutnya. Python menyediakan generator untuk pola ini: fungsi yang menghasilkan nilai satu per satu dengan yield dan berhenti di posisi terakhir hingga diminta lagi.

File yang dibaca bertahap adalah penjualan_harian.csv berikut — tujuh baris penjualan dengan pola export harian.

text penjualan_harian.csv
tanggal,kota,total
2026-09-01,Jakarta,1250000
2026-09-02,Jakarta,980000
2026-09-03,Bandung,640000
2026-09-04,Jakarta,1420000
2026-09-05,Bandung,715000
2026-09-06,Surabaya,530000
2026-09-07,Jakarta,1110000

Ukuran chunk dua baris dipilih agar perilakunya terlihat jelas pada output; pada data sungguhan, satu chunk berisi ribuan baris.

python ekstraksi bertahap dengan generator
import csv


def baca_chunk(path, ukuran):
    """Generator: menghasilkan list berisi maksimal `ukuran` baris per panggilan."""
    with open(path, newline="", encoding="utf-8") as berkas:
        pembaca = csv.reader(berkas)
        next(pembaca)  # lewati baris judul
        tumpukan = []
        for baris in pembaca:
            tumpukan.append(baris)
            if len(tumpukan) == ukuran:
                yield tumpukan
                tumpukan = []
        if tumpukan:  # sisa baris yang tidak genap se-chunk
            yield tumpukan


for nomor, chunk in enumerate(baca_chunk("penjualan_harian.csv", 2), start=1):
    print(f"Chunk {nomor} ({len(chunk)} baris): {chunk}")

Output yang Dihasilkan:

text
Chunk 1 (2 baris): [['2026-09-01', 'Jakarta', '1250000'], ['2026-09-02', 'Jakarta', '980000']]
Chunk 2 (2 baris): [['2026-09-03', 'Bandung', '640000'], ['2026-09-04', 'Jakarta', '1420000']]
Chunk 3 (2 baris): [['2026-09-05', 'Bandung', '715000'], ['2026-09-06', 'Surabaya', '530000']]
Chunk 4 (1 baris): [['2026-09-07', 'Jakarta', '1110000']]

Mari kita telaah baris-baris kode di atas:

  1. Baris 4-5 (signature): baca_chunk menerima path dan ukuran chunk; kata kunci yield di dalam tubuh fungsi menjadikannya generator, bukan fungsi biasa.
  2. Baris 6-8 (buka dan lewati judul): file dibuka sekali untuk seluruh proses; next(pembaca) membuang baris judul agar chunk hanya berisi data.
  3. Baris 9-14 (akumulasi dan serah terima): setiap baris ditampung ke tumpukan; begitu panjangnya menyentuh ukuran, yield menyerahkan chunk ke pemanggil dan eksekusi generator berhenti sampai chunk berikutnya diminta.
  4. Baris 15-16 (sisa): tujuh baris data dengan chunk dua baris menghasilkan tiga chunk penuh plus sisa satu baris — cabang if tumpukan memastikan sisa tersebut tidak terlewat.
  5. Baris 19-20 (pemanggil): perulangan for meminta chunk dari generator satu per satu; pada satu waktu, memori hanya menampung satu chunk, bukan seluruh file.

Konsekuensi praktisnya: pemakaian memori konstan terhadap ukuran chunk, bukan terhadap ukuran file. File 10 juta baris bisa diproses dengan chunk 10.000 baris seperti file 1.000 baris. Kedalaman lebih lanjut tentang mekanisme yield dibahas pada chapter Iterators dan Generators di course Python.

Data mentah kini berada di tangan kita — di dalam memori dalam bentuk daftar dictionary. Kondisinya masih jauh dari siap analisis: tipe data belum benar, format belum seragam, dan kolom turunan belum ada. Chapter berikutnya, Transformasi Data, membahas kategori transformasi beserta contoh pembersihan string, konversi tanggal, dan perhitungan total.