Bahasa Python bisa menjalankan logika transformasi apa pun, tetapi cara penulisannya menentukan apakah pipeline mudah diuji, diuji ulang, dan dirangkai. Perulangan eksplisit pada chapter sebelumnya jelas untuk pemula, tetapi tumbuh membingungkan saat langkah bertambah. Dua gaya penulisan menjadi standar di industri: gaya functional dengan stdlib murni untuk pipeline ringkas, atau pustaka pandas untuk transformasi berskala besar. Chapter ini mempraktikkan keduanya pada data pesanan toko, lalu menutup dengan panduan memilih.
Fungsi Murni dan Pipeline compose #
Gaya functional membangun pipeline dari fungsi murni — fungsi yang hasilnya hanya bergantung pada argumen, tanpa menyentuh keadaan luar. Setiap langkah transformasi menjadi satu fungsi kecil yang bisa diuji terpisah; rangkaian langkah dirangkai oleh compose menjadi satu pipeline. Contoh berikut menangani pesanan toko: buang yang dibatalkan, rapikan nama, hitung total.
def bersihkan_nama(rows):
"""Fungsi murni: trim + kapitalisasi pada kolom pelanggan."""
return [{**r, "pelanggan": r["pelanggan"].strip().title()} for r in rows]
def buang_dibatalkan(rows):
"""Fungsi murni: hanya pesanan yang tidak dibatalkan."""
return [r for r in rows if r["status"] != "cancelled"]
def hitung_total(rows):
return sum(r["subtotal"] for r in rows)
def compose(*fungsi):
"""Gabungkan beberapa fungsi menjadi satu pipeline."""
def terapkan(nilai):
hasil = nilai
for f in fungsi:
hasil = f(hasil)
return hasil
return terapkan
pipeline = compose(buang_dibatalkan, bersihkan_nama)
pesanan = [
{"pelanggan": " budi ", "status": "new", "subtotal": 250000},
{"pelanggan": "siti", "status": "cancelled", "subtotal": 90000},
{"pelanggan": " DEWI ", "status": "shipped", "subtotal": 320000},
]
hasil = pipeline(pesanan)
print(hasil)
print("Total:", hitung_total(hasil))Output yang Dihasilkan:
[{'pelanggan': 'Budi', 'status': 'new', 'subtotal': 250000}, {'pelanggan': 'Dewi', 'status': 'shipped', 'subtotal': 320000}]
Total: 570000Mari kita telaah baris-baris kode di atas:
- Baris 1-3 (
bersihkan_nama): comprehension membangun daftar baru;{**r, "pelanggan": ...}menyalin semua kunci lama lalu menimpa satu kunci — data masuk tidak berubah, syarat fungsi murni. - Baris 6-8 (
buang_dibatalkan): comprehension dengan filter mempertahankan pesanan berstatus selaincancelled; pesanan Siti hilang pada output. - Baris 15-22 (
compose): fungsi pabrik ini menerima daftar fungsi lalu mengembalikanterapkan, yang menjalankan fungsi berurutan — hasilbuang_dibatalkanmenjadi masukanbersihkan_nama. - Baris 25 dan 31: urutan argumen
composeadalah urutan eksekusi;pipeline(pesanan)mengalirkan data melalui kedua langkah tanpa variabel perantara.
Tiga fungsi tersebut bisa dirangkum sebagai berikut:
| Fungsi | Peran | Mengubah data masukan? |
|---|---|---|
bersihkan_nama | merapikan kolom pelanggan | tidak — membangun daftar baru |
buang_dibatalkan | memfilter status pesanan | tidak — membangun daftar baru |
hitung_total | menjumlahkan subtotal | tidak — hanya membaca |
Sifat murni membawa dua keuntungan nyata. Pengujian menjadi sepele — bersihkan_nama([baris]) selalu menghasilkan keluaran yang sama, cocok untuk unit test. Dan karena setiap fungsi hanya membaca masukannya, pipeline aman dijalankan ulang (reprocess) tanpa efek samping tersembunyi.
Ketika langkah bertambah, compose tetap terbaca: urutan argumennya adalah urutan eksekusi, dan menambah satu langkah berarti menambah satu fungsi plus satu argumen — tidak ada perulangan yang harus direstrukturisasi. Batas praktisnya sekitar lima sampai tujuh langkah; lebih dari itu, pembaca mulai sulit menelusuri aliran data dan pipeline sebaiknya dipecah menjadi beberapa tahapan bernama.
pandas: groupby Sederhana #
Untuk data besar, pandas menggeser perulangan ke operasi vektor pada DataFrame. Satu operasi groupby menggantikan perulangan agregasi manual pada chapter Transformasi Data. Contoh berikut merangkum subtotal pesanan per kota.
import pandas as pd
pesanan = pd.DataFrame({
"kota": ["Jakarta", "Bandung", "Jakarta", "Surabaya", "Bandung"],
"subtotal": [250000, 175000, 320000, 640000, 410000],
})
ringkasan = pesanan.groupby("kota", as_index=False)["subtotal"].sum()
print(ringkasan)
print("Tipe hasil:", type(ringkasan).__name__)Output yang Dihasilkan:
kota subtotal
0 Bandung 585000
1 Jakarta 570000
2 Surabaya 640000
Tipe hasil: DataFrameBaris groupby("kota", as_index=False)["subtotal"].sum() bekerja dalam tiga gerakan: kelompokkan baris berdasarkan kota, ambil kolom subtotal pada tiap kelompok, lalu jumlahkan. Argumen as_index=False membuat kota tetap menjadi kolom biasa — bentuk ini biasanya lebih nyaman dilanjutkan ke join atau penyimpanan. Hasilnya tetap DataFrame, siap ditambah kolom lain tanpa konversi tipe.
Perbandingannya dengan chapter sebelumnya: perulangan for beserta dictionary total_per_kota digantikan satu baris groupby. Pada DataFrame besar, pandas menjalankan operasi kolom secara vektor di atas numpy, sehingga kecepatannya jauh di atas perulangan Python murni. Selama operasinya bersifat per kolom — penjumlahan, rata-rata, penggabungan kategori — pandas hampir selalu lebih ringkas; begitu logika membutuhkan keputusan lintas baris yang bertingkat, kembali ke fungsi murni biasanya lebih jelas.
Kapan stdlib, Kapan pandas #
| Aspek | stdlib murni | pandas |
|---|---|---|
| Dependensi | tanpa pustaka tambahan | butuh pandas beserta numpy |
| Skala nyaman | ratusan hingga ribuan baris | ratusan ribu hingga jutaan baris |
| Gaya kode | perulangan eksplisit, mudah dibedah | vektorisasi dan groupby siap pakai |
| Tipe keluar | list dan dict Python | DataFrame siap diquery/diplot |
| Waktu mulai | instan | import lebih berat di awal |
Kedua jalur tersebut tetap berjalan di luar database: Python menarik data, mengolahnya, lalu mengembalikannya. Padahal untuk data yang sudah berada di warehouse, komputasi bisa digeser ke dalam database dengan SQL. Chapter berikutnya, Transformasi dengan SQL, membahas jalur tersebut dan membandingkannya dengan Python. Dokumentasi resmi masing-masing tersedia di docs.python.org dan pandas.pydata.org .