Skor dimensi pada chapter sebelumnya memberi tahu kita bahwa 30% baris pesanan melanggar aturan validity — sayangnya, angka tersebut baru muncul setelah data berada di tabel dan dikonsumsi dashboard. Data validation memindahkan pemeriksaan itu ke arah sebelumnya: baris yang melanggar aturan ditangkap di gerbang, bukan ditemukan pemakai di laporan. Chapter Validasi Data saat Ingestion sudah memperkenalkan pola karantina di gerbang ingestion; sekarang kita bedah lebih dalam cara merancang aturan validasinya sendiri: aturan sebagai data yang bisa ditambah tanpa mengubah kode, tingkat keparahan yang menentukan tindakan, dan laporan pelanggaran yang bisa langsung ditindaklanjuti.
Aturan Validasi sebagai Data #
Validator yang ditulis sebagai rangkaian if bersarang cepat menjadi sulit dirawat: menambah satu aturan berarti menyentuh logika utama, dan tidak ada cara mudah menjawab “aturan apa saja yang berlaku untuk tabel ini?”. Pendekatan yang lebih sehat adalah memperlakukan aturan sebagai data — setiap aturan terdiri dari tiga bagian:
- Nama dan deskripsi: kalimat yang bisa dibaca pemilik data, misalnya “total antara 0 dan 50 juta”.
- Fungsi pemeriksa: menerima tabel, mengembalikan penanda baris mana yang lolos.
- Tingkat keparahan (severity):
blokirmenghentikan pemrosesan,peringatanhanya dilaporkan.
Dengan struktur ini, validator menjalankan semua aturan dan mengumpulkan seluruh pelanggaran sekaligus, bukan berhenti di pelanggaran pertama. Laporan lengkap membuat satu sesi perbaikan menangani semua masalah, bukan satu masalah per eksekusi.
Jenis Aturan yang Paling Sering Dipakai #
| Jenis Aturan | Pertanyaan yang Dijawab | Contoh pada Tabel Pesanan |
|---|---|---|
| Not-null | Apakah kolom wajib terisi? | order_id tidak boleh kosong |
| Rentang | Apakah angka masuk batas wajar? | total antara 0 dan 50 juta |
| Format | Apakah teks sesuai pola? | email memuat @ dan domain |
| Daftar nilai | Apakah nilai berasal dari himpunan sah? | status salah satu dari empat status |
| Referential integrity | Apakah rujukan ke tabel lain valid? | pelanggan terdaftar di tabel pelanggan |
| Uniqueness | Apakah nilai tidak berulang? | order_id tidak ganda |
Membangun Validator Sederhana dengan pandas #
Kita terapkan pola di atas pada delapan baris pesanan yang bermasalah. Setiap fungsi pemeriksa mengembalikan boolean mask — True untuk baris yang lolos — sehingga semua jenis aturan dapat digabung dengan operasi mask yang sama:
"""Kerangka aturan validasi sederhana: daftar aturan + laporan pelanggaran."""
import re
import pandas as pd
pesanan = pd.DataFrame(
[
["ORD-101", "Budi", "[email protected]", 150000],
["ORD-102", "Siti", "[email protected]", 320000],
["ORD-103", "Dewi", "dewi example com", 99000],
["ORD-104", "Budi", "[email protected]", -5000],
[None, "Siti", "[email protected]", 260000],
["ORD-106", "Rina", "[email protected]", 87000],
["ORD-107", "Dewi", "[email protected]", 320000000],
["ORD-108", "Budi", "[email protected]", 175000],
],
columns=["order_id", "pelanggan", "email", "total"],
)
pelanggan_terdaftar = {"Budi", "Siti", "Dewi"}
def terisi(df, kolom):
"""Baris yang lolos aturan tidak-null pada kolom."""
return df[kolom].notna()
def dalam_rentang(df, kolom, bawah, atas):
return df[kolom].between(bawah, atas)
def cocok_pola(df, kolom, pola):
return df[kolom].fillna("").str.match(re.compile(pola))
def merujuk(df, kolom, referensi):
return df[kolom].isin(referensi)
ATURAN = [
("blokir", "order_id terisi", lambda df: terisi(df, "order_id")),
("blokir", "total antara 0 dan 50 juta", lambda df: dalam_rentang(df, "total", 0, 50_000_000)),
("peringatan", "email sesuai pola", lambda df: cocok_pola(df, "email", r"^[\w.+-]+@[\w-]+\.[\w.-]+$")),
("peringatan", "pelanggan terdaftar", lambda df: merujuk(df, "pelanggan", pelanggan_terdaftar)),
]
for severitas, nama, cek in ATURAN:
lolos = cek(pesanan)
if lolos.all():
print(f"[LULUS] {nama}")
else:
gagal = pesanan.index[~lolos].tolist()
print(f"[{severitas.upper():11}] {nama}: {len(gagal)} baris gagal di indeks {gagal}")
# Referential integrity versi set difference: nilai yang tidak dikenal sumber mana.
tak_dikenal = set(pesanan["pelanggan"].dropna()) - pelanggan_terdaftar
print(f"pelanggan tak terdaftar: {sorted(tak_dikenal)}")Output yang Dihasilkan:
[BLOKIR ] order_id terisi: 1 baris gagal di indeks [4]
[BLOKIR ] total antara 0 dan 50 juta: 2 baris gagal di indeks [3, 6]
[PERINGATAN ] email sesuai pola: 1 baris gagal di indeks [2]
[PERINGATAN ] pelanggan terdaftar: 1 baris gagal di indeks [5]
pelanggan tak terdaftar: ['Rina']Mari kita telaah baris-baris kode di atas:
- Baris 19 (
pelanggan_terdaftar): himpunan pelanggan sah berperan sebagai tabel referensi mini — di pipeline produksi, himpunan ini dibaca dari tabelpelanggandi warehouse. - Baris 22-36 (empat fungsi pemeriksa): setiap fungsi menerima DataFrame dan mengembalikan mask baris yang lolos;
cocok_polamengisi nilai kosong dengan string kosong lebih dulu agarstr.matchtidak menghasilkanNaN. - Baris 39-44 (
ATURAN): daftar aturan memasangkan severitas, nama, dan fungsi pemeriksa; menambah aturan baru cukup menambah satu baris di daftar ini. - Baris 46-52 (perulangan pelaporan):
~lolosmembalik mask untuk menemukan baris yang gagal, danpesanan.index[...]mengambil indeksnya — laporan menunjuk baris persis yang perlu diperbaiki. - Baris 55-56 (set difference): operasi
set(...) - pelanggan_terdaftarmenghasilkan nilai pelanggan yang tidak dikenal, langkah awal menyelidiki apakahRinapelanggan baru atau salah ketik.
Tingkat Keparahan Menentukan Tindakan #
Laporan di atas memisahkan dua kelompok: pelanggaran blokir berarti data tidak boleh masuk tabel utama — baris 4 (order_id kosong) dan baris 3 serta 6 (total di luar rentang) layak dikarantina; pelanggaran peringatan masih boleh diproses tetapi wajib dilaporkan — email rusak pada baris 2 tidak menghalangkan analisis pendapatan. Pemisahan ini mencegah dua kegagalan berlawanan: pipeline berhenti total karena satu baris bermasalah, atau data bermasalah lolos karena tidak ada yang berani menghentikan pipeline.
Dari Validator Buatan Sendiri ke Tool Teruji #
Pola “aturan sebagai data” ini persis yang diadopsi tool validasi industri: Great Expectations menyusun aturan sebagai kumpulan expectation yang tervalidasi berkala, dan Pandera mendeklarasikan aturan pada DataFrame dengan schema ber-annotation. Keduanya dibahas tuntas sebagai chapter tersendiri di section ini; dokumentasi Great Expectations tersedia di docs.greatexpectations.io . Validator buatan sendiri tetap relevan untuk aturan khusus domain — yang penting bukan toolnya, melainkan disiplinnya: aturan eksplisit, laporan lengkap, dan tindakan yang jelas.
Aturan yang kita tulis sejauh ini memeriksa isi nilai. Lapis pemeriksaan berikutnya memeriksa bentuk tabel itu sendiri — kolom apa saja yang boleh ada dan bertipe apa — sebelum satu pun aturan nilai dijalankan. Kita bahas pada chapter berikutnya: Schema Validation.