Data yang baru kita terima hampir tidak pernah sebersih data latihan di buku. Laporan hasil ekspor sering memuat baris ganda, sel yang kosong, angka yang tersimpan sebagai teks, serta label yang ditulis dengan gaya berbeda-beda. Bila keempat masalah itu langsung dihitung tanpa pemeriksaan, laporan yang dihasilkan bisa menyesatkan keputusan bisnis. Chapter ini menjadi pintu masuk Section Data Cleaning: kita memetakan empat masalah data yang paling umum, berlatih diagnosis cepat dengan pandas, lalu menyiapkan satu dataset kotor yang akan dibersihkan bertahap sampai akhir Section ini.
Empat Masalah Data yang Paling Umum #
Pembersihan data di dunia nyata berputar pada empat kategori masalah. Tabel berikut merangkum bentuk masing-masing masalah beserta akibatnya bila data langsung dipakai:
| Masalah | Bentuk di dalam data | Akibat bila dibiarkan |
|---|---|---|
| Nilai kosong (missing value) | Sel yang tidak terisi, ditandai NaN oleh pandas | sum() dan mean() melewati sel kosong, statistik menjadi bias |
| Baris duplikat | Baris identik tercatat dua kali atau lebih | Total penjualan terhitung ganda |
| Tipe data salah | Angka tersimpan sebagai teks str | Aritmetika error dan urutan sortir menyimpang |
| Label tidak konsisten | "Jakarta" dan "JAKARTA" dianggap dua kota berbeda | groupby dan value_counts() terpecah |
Keempat masalah jarang datang sendirian. Satu file CSV hasil gabungan beberapa sumber biasanya memuat semuanya sekaligus, sehingga urutan pembersihan juga penting: masalah yang satu bisa menyembunyikan masalah lain. Karena itu diagnosis kita harus menyapu keempat kategori secara sistematis, bukan menebak berdasarkan dugaan.
Dataset Latihan: Laporan Pesanan yang Kotor #
Sepanjang Section Data Cleaning kita memakai satu dataset laporan pesanan toko daring fiktif berisi sepuluh baris dan lima kolom: id_pesanan, nama_pelanggan, kota, umur, dan total_belanja. Dataset ini sengaja dibuat kotor di dalam skrip sehingga contoh tetap bisa dijalankan offline tanpa file tambahan. Skrip berikut memuat data tersebut lalu menjalankan diagnosis lengkap dalam sekali eksekusi:
import pandas as pd
pesanan = pd.DataFrame(
{
"id_pesanan": [
"PSC-101", "PSC-102", "PSC-103", "PSC-104", "PSC-105",
"PSC-106", "PSC-101", "PSC-102", "PSC-103", "PSC-107",
],
"nama_pelanggan": [
"Budi", "Siti", "Dewi", "Andi", "Rina",
"Tono", "Budi", "Siti", "Dewi", "Sari",
],
"kota": [
"Jakarta", "Bandung", "Surabaya", "JAKARTA", "Bandung",
None, "Jakarta", "Bandung", "Surabaya", "Medan",
],
"umur": [29, 34, None, 41, 27, 38, 29, 34, None, 45],
"total_belanja": [
250000, 480000, 150000, None, 320000,
275000, 250000, 480000, 165000, 190000,
],
}
)
print(pesanan)
print()
print("Sel kosong per kolom:")
print(pesanan.isna().sum())
print()
print("Baris duplikat penuh :", pesanan.duplicated().sum())
print("Duplikat id_pesanan :", pesanan.duplicated(subset=["id_pesanan"]).sum())
print()
print("Label kota yang terdeteksi:")
print(sorted(pesanan["kota"].dropna().unique()))
print()
print(pesanan.dtypes)Output yang Dihasilkan:
id_pesanan nama_pelanggan kota umur total_belanja
0 PSC-101 Budi Jakarta 29.0 250000.0
1 PSC-102 Siti Bandung 34.0 480000.0
2 PSC-103 Dewi Surabaya NaN 150000.0
3 PSC-104 Andi JAKARTA 41.0 NaN
4 PSC-105 Rina Bandung 27.0 320000.0
5 PSC-106 Tono NaN 38.0 275000.0
6 PSC-101 Budi Jakarta 29.0 250000.0
7 PSC-102 Siti Bandung 34.0 480000.0
8 PSC-103 Dewi Surabaya NaN 165000.0
9 PSC-107 Sari Medan 45.0 190000.0
Sel kosong per kolom:
id_pesanan 0
nama_pelanggan 0
kota 1
umur 2
total_belanja 1
dtype: int64
Baris duplikat penuh : 2
Duplikat id_pesanan : 3
Label kota yang terdeteksi:
['Bandung', 'JAKARTA', 'Jakarta', 'Medan', 'Surabaya']
id_pesanan str
nama_pelanggan str
kota str
umur float64
total_belanja float64
dtype: objectMembaca Hasil Diagnosis #
Mari kita telaah peran setiap bagian skrip di atas:
- Baris 3-23 (
pesanan = pd.DataFrame(...)): dataset kotor sepuluh baris; perhatikanNonepada kolomkota,umur, dantotal_belanjayang menjadi sumber nilai kosong. - Baris 27-28 (
pesanan.isna().sum()): setiap sel diperiksa apakah kosong, lalu hasilnya dijumlahkan per kolom sehingga terlihatkotakehilangan 1 sel danumurkehilangan 2 sel. - Baris 30-31 (
pesanan.duplicated().sum()): menghitung baris duplikat. Angka 2 berarti dua baris salinan identik; angka 3 padasubset=["id_pesanan"]berarti ada satu baris tambahan denganid_pesanansama tetapi isinya berbeda. Halaman Duplicate labels mendokumentasikan bagaimana pandas menandai nilai yang berulang. - Baris 33-34 (
sorted(pesanan["kota"].dropna().unique())): mengurutkan label unik kolomkota; daftar memuat"JAKARTA"dan"Jakarta"sekaligus, tanda label tidak konsisten. - Baris 36 (
pesanan.dtypes): menampilkan tipe setiap kolom;umurdantotal_belanjamenjadifloat64karena kehadiranNaN.
Hasil diagnosis memperlihatkan keempat masalah hadir dalam satu tabel kecil. Kolom umur ber-dtype float64 meskipun berisi bilangan bulat adalah sinyal klasik: satu sel kosong mengubah tipe seluruh kolom karena NaN bertipe float. Label "JAKARTA" di samping "Jakarta" adalah masalah berbeda; nilainya terisi dan tipenya benar, tetapi penulisannya tidak seragam. Masalah tipe kita perbaiki pada Chapter Memperbaiki Tipe Data, sedangkan label teks dibahas pada Chapter Membersihkan Teks.
Alur Diagnosis Empat Langkah #
Sebelum menyentuh satu sel pun, jadikan alur berikut kebiasaan awal setiap kali menerima data baru:
- Periksa bentuk dan tipe data dengan
df.shape,df.dtypes, dan pandas.DataFrame.info . - Hitung sel kosong per kolom dengan
df.isna().sum(). - Hitung baris duplikat dengan
df.duplicated().sum()dandf.duplicated(subset=["kolom_kunci"]).sum(). - Daftar nilai unik kolom kategorikal dengan
df["kota"].unique()untuk menemukan label yang tidak seragam.
Dengan peta masalah di tangan, arah pembersihan menjadi jelas: nilai kosong ditangani lebih dulu karena paling sering memicu masalah lain. Chapter berikutnya membahas apa itu missing values, bagaimana pandas 3.0 menandainya pada tiap tipe data, dan mengapa NaN tidak pernah dibandingkan dengan tanda sama dengan. Panduan resmi Working with missing data
menjadi rujukan utama sepanjang pembahasan tersebut.