Dimensi kualitas

Dimensi kualitas data, yaitu kelengkapan, validitas, kesegaran, dan konsistensi.

Daftar isi

Pemeriksaan kualitas data bergerak dari kesan ke angka ketika setiap aspeknya didefinisikan secara kuantitatif, karena angka dapat dibandingkan dengan ambang batas dan dihitung ulang oleh mesin. Topik ini membahas empat dimensi kualitas data yang paling sering diukur pada pipeline, yaitu kelengkapan, validitas, kesegaran, dan konsistensi, beserta definisi kuantitatif sederhananya. Satu berkas CSV kecil dengan masalah yang ditanamkan secara sengaja diperiksa oleh skrip Python, dan skor setiap dimensi dicetak sebagai keluaran nyata yang dapat dihitung ulang.

Empat dimensi kualitas data#

Dimensi kualitas data (data quality dimension) adalah aspek yang diukur secara terpisah untuk menilai kesesuaian data dengan tujuan pemakaiannya. Empat dimensi berikut dipilih karena masing-masing dapat dinyatakan sebagai proporsi yang dihitung langsung dari data. Definisinya sengaja dibuat sederhana, sehingga skrip apa pun dapat menghitungnya tanpa alat khusus.

Kelengkapan (completeness) mengukur banyaknya nilai wajib yang kosong, dan ukurannya berupa proporsi sel terisi terhadap seluruh sel wajib pada tabel. Validitas (validity) mengukur kesesuaian nilai yang ada dengan format dan rentang yang ditetapkan, misalnya jumlah barang yang tidak boleh nol, dan ukurannya berupa proporsi baris yang lolos seluruh aturan nilai. Kesegaran (freshness) mengukur umur data, yaitu selisih antara tanggal data dan tanggal pemakaiannya, dan ukurannya berupa proporsi baris yang berumur di bawah batas. Konsistensi (consistency) mengukur kesesuaian nilai antartabel, misalnya id_pelanggan pada tabel pesanan yang harus ada di tabel pelanggan, dan ukurannya berupa proporsi rujukan yang ditemukan pada tabel acuannya.

Tabel berikut merangkum definisi kuantitatif keempatnya.

DimensiPertanyaan intiDefinisi kuantitatif
Kelengkapanapakah nilai wajib adasel terisi dibagi seluruh sel wajib
Validitasapakah nilai sesuai aturanbaris lolos dibagi baris bernilai
Kesegaranapakah data cukup barubaris segar dibagi baris bertanggal
Konsistensiapakah antartabel cocokrujukan ditemukan dibagi rujukan diperiksa

Data contoh dengan masalah yang ditanamkan#

Contoh pemeriksaan menggunakan dua berkas CSV kecil, yaitu pesanan.csv sebagai tabel utama dan pelanggan.csv sebagai tabel acuan konsistensi. Lima masalah ditanamkan pada pesanan.csv. Kelimanya berupa satu baris yang seluruh selnya kosong, satu id_pelanggan yang kosong, satu jumlah_item bernilai 0 di luar rentang, satu tanggal yang terlalu tua, dan satu id_pelanggan yang tidak ada di tabel acuan. Isi kedua berkasnya sebagai berikut.

text pesanan.csv
id_pesanan,tanggal_pesanan,id_pelanggan,jumlah_item
P101,2026-10-30,C01,2
P102,2026-10-31,C02,1
P103,2026-11-01,,3
,,,
P104,2026-09-10,C01,5
P105,2026-11-01,C99,0
text pelanggan.csv
id_pelanggan,nama,kota
C01,Ali,Jakarta
C02,Budi,Bandung
C03,Citra,Surabaya

pelanggan.csv tidak membawa masalah, sehingga seluruh pelanggaran berada di sisi pesanan.csv. Pada pekerjaan sungguhan, tabel acuan biasanya berupa tabel dimensi yang sudah dibersihkan, dan pemeriksaan konsistensi menggantikan kunci asing yang tidak ditegakkan mesin basis data. Konsep yang sama berlaku untuk tabel apa pun yang saling merujuk.

Skor per dimensi dengan skrip Python#

Skrip berikut menghitung skor keempat dimensi sekaligus mencetak daftar pelanggaran per baris. Tanggal pembanding kesegaran berupa literal 2026-11-02 agar keluarannya deterministik, sedangkan pada pipeline sungguhan tanggal itu diambil dari waktu run. Skor dinyatakan sebagai proporsi, dan daftar pelanggaran menyebut barisnya, sehingga setiap angka dapat dilacak sumbernya.

python pemeriksaan-kualitas.py
"""Pemeriksaan empat dimensi kualitas data pada pesanan.csv.

Setiap dimensi dinyatakan sebagai proporsi sederhana:
- kelengkapan  = sel terisi / seluruh sel wajib
- validitas    = baris lolos aturan / baris bernilai
- kesegaran    = baris segar / baris bertanggal
- konsistensi  = rujukan ditemukan / rujukan diperiksa
"""
import csv
from datetime import date

HARI_INI = date(2026, 11, 2)   # tanggal literal agar keluaran deterministik
JENDELA_HARI = 30              # batas umur baris, dalam hari
RENTANG_ITEM = (1, 100)        # rentang nilai jumlah_item yang valid
KOLOM_WAJIB = ("id_pesanan", "tanggal_pesanan", "id_pelanggan", "jumlah_item")


def baca_csv(path):
    with open(path, newline="", encoding="utf-8") as berkas:
        return list(csv.DictReader(berkas))


def periksa(barisan, kunci_pelanggan):
    """Hitung skor keempat dimensi dan kumpulkan pelanggarannya."""
    pelanggaran = []

    # kelengkapan: proporsi sel wajib yang terisi
    total_sel = len(barisan) * len(KOLOM_WAJIB)
    sel_kosong = 0
    for nomor, baris in enumerate(barisan, start=1):
        label = baris["id_pesanan"] or f"baris-{nomor}"
        for kolom in KOLOM_WAJIB:
            if baris[kolom].strip() == "":
                sel_kosong += 1
                pelanggaran.append(f"kelengkapan  {label:<9} {kolom} kosong")
    skor_kelengkapan = (total_sel - sel_kosong) / total_sel

    # validitas: baris bernilai yang memenuhi rentang dan format
    bernilai = 0
    valid = 0
    for baris in barisan:
        if baris["jumlah_item"].strip() == "":
            continue
        bernilai += 1
        jumlah = int(baris["jumlah_item"])
        date.fromisoformat(baris["tanggal_pesanan"])  # error bila format rusak
        if RENTANG_ITEM[0] <= jumlah <= RENTANG_ITEM[1]:
            valid += 1
        else:
            pelanggaran.append(
                f"validitas    {baris['id_pesanan']:<9} jumlah_item {jumlah} "
                f"di luar rentang {RENTANG_ITEM[0]}-{RENTANG_ITEM[1]}"
            )
    skor_validitas = valid / bernilai

    # kesegaran: baris bertanggal yang berumur di bawah batas
    bertanggal = 0
    segar = 0
    for baris in barisan:
        if baris["tanggal_pesanan"].strip() == "":
            continue
        bertanggal += 1
        tanggal = date.fromisoformat(baris["tanggal_pesanan"])
        umur = (HARI_INI - tanggal).days
        if umur <= JENDELA_HARI:
            segar += 1
        else:
            pelanggaran.append(
                f"kesegaran    {baris['id_pesanan']:<9} tanggal_pesanan "
                f"{tanggal.isoformat()} berumur {umur} hari"
            )
    skor_kesegaran = segar / bertanggal

    # konsistensi: id_pelanggan yang ditemukan di tabel acuan
    dirujuk = 0
    cocok = 0
    for baris in barisan:
        if baris["id_pelanggan"].strip() == "":
            continue
        dirujuk += 1
        if baris["id_pelanggan"] in kunci_pelanggan:
            cocok += 1
        else:
            pelanggaran.append(
                f"konsistensi  {baris['id_pesanan']:<9} id_pelanggan "
                f"{baris['id_pelanggan']} tidak ada di pelanggan.csv"
            )
    skor_konsistensi = cocok / dirujuk

    skor = {
        "kelengkapan": (total_sel - sel_kosong, total_sel, skor_kelengkapan),
        "validitas": (valid, bernilai, skor_validitas),
        "kesegaran": (segar, bertanggal, skor_kesegaran),
        "konsistensi": (cocok, dirujuk, skor_konsistensi),
    }
    return skor, pelanggaran


if __name__ == "__main__":
    pesanan = baca_csv("pesanan.csv")
    pelanggan = baca_csv("pelanggan.csv")
    kunci = {baris["id_pelanggan"] for baris in pelanggan}
    skor, pelanggaran = periksa(pesanan, kunci)

    print(f"berkas diperiksa : pesanan.csv ({len(pesanan)} baris), "
          f"acuan pelanggan.csv ({len(pelanggan)} baris)")
    print(f"kelengkapan : {skor['kelengkapan'][0]}/{skor['kelengkapan'][1]} "
          f"sel terisi = {skor['kelengkapan'][2]:.1%}")
    print(f"validitas   : {skor['validitas'][0]}/{skor['validitas'][1]} "
          f"baris memenuhi aturan = {skor['validitas'][2]:.1%}")
    print(f"kesegaran   : {skor['kesegaran'][0]}/{skor['kesegaran'][1]} "
          f"baris berumur <= {JENDELA_HARI} hari = {skor['kesegaran'][2]:.1%}")
    print(f"konsistensi : {skor['konsistensi'][0]}/{skor['konsistensi'][1]} "
          f"rujukan ada di pelanggan.csv = {skor['konsistensi'][2]:.1%}")
    print()
    print("pelanggaran yang ditemukan:")
    for satu in pelanggaran:
        print(satu)
text Keluaran
berkas diperiksa : pesanan.csv (6 baris), acuan pelanggan.csv (3 baris)
kelengkapan : 19/24 sel terisi = 79.2%
validitas   : 4/5 baris memenuhi aturan = 80.0%
kesegaran   : 4/5 baris berumur <= 30 hari = 80.0%
konsistensi : 3/4 rujukan ada di pelanggan.csv = 75.0%

pelanggaran yang ditemukan:
kelengkapan  P103      id_pelanggan kosong
kelengkapan  baris-4   id_pesanan kosong
kelengkapan  baris-4   tanggal_pesanan kosong
kelengkapan  baris-4   id_pelanggan kosong
kelengkapan  baris-4   jumlah_item kosong
validitas    P105      jumlah_item 0 di luar rentang 1-100
kesegaran    P104      tanggal_pesanan 2026-09-10 berumur 53 hari
konsistensi  P105      id_pelanggan C99 tidak ada di pelanggan.csv

Keluaran memperlihatkan empat skor dari berkas yang sama, dan setiap skor disusutkan oleh pelanggaran yang berbeda. Kelengkapan turun karena lima sel kosong, dua di antaranya berasal dari satu baris yang seluruhnya kosong. Validitas dan kesegaran masing-masing kehilangan satu baris, sedangkan konsistensi menjadi skor terendah karena satu dari empat rujukan tidak ditemukan. Tidak ada dimensi yang menggantikan dimensi lain, sehingga keempatnya perlu dihitung secara bersamaan.

Menindaklanjuti skor#

Skor berguna setelah disandingkan dengan ambang batas yang ditetapkan per tabel. Tabel transaksi dapat mewajibkan kelengkapan 100%, sedangkan tabel log kejadian dapat menoleransi sel kosong sampai 5%. Ambang batas itu juga menentukan tindak lanjutnya, yaitu pipeline berhenti, baris dikarantina, atau skor dicatat sebagai log untuk ditinjau berkala.

Posisi pemeriksaan tiap dimensi juga berbeda di dalam pipeline. Kelengkapan dan validitas paling murah diperiksa segera setelah data masuk, sebelum nilai cacat dipakai oleh transformasi apa pun. Kesegaran biasanya diperiksa di awal run untuk memutuskan apakah sumber sudah siap, sedangkan konsistensi diperiksa setelah tabel yang dirujuk tersedia. Pemeriksaan yang ditempatkan sedini mungkin menekan biaya perbaikan, karena cacat yang terdeteksi dekat sumbernya belum sempat menular ke tabel turunan.

Kesalahan umum#

  1. Menghitung validitas atas sel yang kosong. Penyebabnya, pemeriksa rentang diterapkan pada seluruh baris tanpa memisahkan sel kosong. Akibatnya, satu baris cacat terhitung dua kali pada dua dimensi dan skor validitas menjadi menyesatkan. Perbaikannya, sel kosong dihitung pada dimensi kelengkapan, sedangkan aturan validitas hanya dinilai pada baris yang nilainya ada.
  2. Membandingkan kesegaran dengan tanggal sistem saat skrip ditulis. Penyebabnya, pembanding tanggal mengambil tanggal hari ini secara implisit. Akibatnya, keluaran skrip berubah setiap hari dan tidak dapat dipakai sebagai pemeriksaan otomatis. Perbaikannya, tanggal pembanding dinyatakan eksplisit sebagai parameter run, sebagaimana literal HARI_INI pada skrip contoh.
  3. Menurunkan ambang batas sampai semua skor lulus. Penyebabnya, ambang batas diturunkan agar pipeline tidak lagi berhenti. Akibatnya, data cacat mengalir ke laporan dan ambang batas kehilangan maknanya. Perbaikannya, ambang batas disetel menurut risiko tabel, lalu baris yang gagal disalurkan ke karantina sebagaimana dibahas pada topik pengujian pipeline.

Ringkasan#

  • Empat dimensi kualitas yang dapat dihitung langsung dari data adalah kelengkapan, validitas, kesegaran, dan konsistensi, masing-masing dinyatakan sebagai proporsi.
  • Skor per dimensi memerlukan aturan yang eksplisit, yaitu kolom wajib, rentang nilai, jendela kesegaran, dan tabel acuan.
  • Skor berguna setelah disandingkan dengan ambang batas per tabel, dan setiap pelanggaran dicatat per baris agar dapat ditindaklanjuti.

Referensi#