Analisis pada data yang bermasalah menghasilkan jawaban yang tampak meyakinkan padahal keliru — itulah alasan validasi selalu mendahului analisis. Pada bagian ini kita memeriksa data mentah nilai_siswa.csv dengan daftar periksa kualitas: bentuk data, tipe tiap kolom, baris duplikat, sel kosong, dan konsistensi nilai kategorikal. Kerangka pemeriksaannya sama dengan yang kita pakai di proyek-proyek sebelumnya; yang berlatih di sini adalah kejelian membaca hasilnya pada dataset yang belum pernah kita sentuh — persis situasi Anda nanti dengan dataset pilihan sendiri.

Pemeriksaan Pertama: Bentuk, Tipe, dan Hitungan Cepat #

Pemeriksaan pembuka selalu berupa penghitungan murah yang bisa dibaca sekali lihat: berapa baris dan kolom, ada berapa duplikat, ada berapa sel kehadiran yang berisi tanda -, dan berapa banyak nama siswa unik. Setelah itu kita lihat nilai unik pada kolom kelas untuk memeriksa konsistensi kategorinya:

python
import pandas as pd

df = pd.read_csv("../data/nilai_siswa.csv")

print("Jumlah baris dan kolom  :", df.shape)
print("Baris duplikat persis   :", df.duplicated().sum())
print("Sel kehadiran '-'       :", (df["kehadiran_persen"] == "-").sum())
print("Nama siswa unik         :", df["siswa"].nunique())
print("\nNilai unik kolom kelas:")
print(df["kelas"].value_counts().to_string())
print("\nTipe data tiap kolom:")
print(df.dtypes.to_string())

Output yang Dihasilkan:

text
Jumlah baris dan kolom  : (32, 5)
Baris duplikat persis   : 1
Sel kehadiran '-'       : 1
Nama siswa unik         : 31

Nilai unik kolom kelas:
kelas
B    16
A    15
a     1

Tipe data tiap kolom:
siswa                   object
kelas                   object
jam_belajar_mingguan     int64
kehadiran_persen        object
nilai_ujian              int64

Mari kita bedah temuan tersebut satu per satu:

  1. 32 baris untuk 31 nama unik — selisih satu, dan duplicated().sum() menunjukkan 1 baris duplikat persis. Ada satu siswa yang terekam dua kali dengan isi baris yang sama persis; kemungkinan hasil ekspor yang dijalankan dua kali.
  2. Satu sel kehadiran bernilai - — tanda ini adalah cara sistem pencatat menandai data yang kosong, bukan angka. Karena satu sel saja sudah cukup, seluruh kolom kehadiran_persen terbaca object alih-alih numerik — persis selisih tipe yang terdeteksi saat membaca dokumentasi pada Bagian 2.
  3. value_counts() memuat tiga nilai kelas — seharusnya hanya A dan B. Nilai a muncul satu kali dengan huruf kecil; bagi komputer ia berbeda dari A, padahal bagi manusia sama. Bila a digabungkan ke A, kolom kelas berisi 16 baris A dan 16 baris B — tetapi hitungan A itu masih memuat satu salinan Joko, sehingga siswa kelas A sesungguhnya 15 orang, bukan 16.
  4. Kolom siswa berperan sebagai penanda — 31 nama unik pada 32 baris menegaskan bahwa baris tambahan adalah salinan, bukan dua siswa bernama sama.

Menelusuri Baris Bermasalah #

Agregat memberi tahu ada berapa masalah; langkah berikutnya adalah menunjukkan letaknya. Kita tampilkan baris duplikat beserta baris aslinya memakai duplicated(keep=False), lalu saring baris dengan masalah lain memakai gabungan kondisi:

python
import pandas as pd

df = pd.read_csv("../data/nilai_siswa.csv")

print("Baris duplikat persis (beserta baris aslinya):")
print(df[df.duplicated(keep=False)].to_string(index=False))

print("\nBaris dengan masalah lain:")
mask = (df["kehadiran_persen"] == "-") | (df["kelas"] != df["kelas"].str.upper())
print(df[mask].to_string(index=False))

Output yang Dihasilkan:

text
Baris duplikat persis (beserta baris aslinya):
siswa kelas  jam_belajar_mingguan kehadiran_persen  nilai_ujian
 Joko     A                     6               75           62
 Joko     A                     6               75           62

Baris dengan masalah lain:
siswa kelas  jam_belajar_mingguan kehadiran_persen  nilai_ujian
 Gita     a                     7               80           58
  Uma     B                     9                -           65

Mari kita baca hasil penelusuran tersebut:

  1. duplicated(keep=False) menampilkan pasangan lengkap: baris Joko muncul dua kali dengan isi identik — enam jam belajar, kehadiran 75, nilai 62. Salinan ini akan membuat Joko terhitung ganda dalam rata-rata kelas bila dibiarkan.
  2. Operator | menggabungkan dua kondisi dengan makna “atau”: baris ditampilkan bila kehadirannya - atau penulisan kelasnya tidak sama dengan versi huruf besarnya. Kondisi kedua (df["kelas"] != df["kelas"].str.upper()) adalah cara ringkas menangkap ketidaksesuaian kapitalisasi.
  3. Dua baris masalah lain terpisah letaknya — Gita (kelas tertulis a) dan Uma (kehadiran -). Berbeda dengan Joko, keduanya bukan salinan: barisnya sah, hanya satu selnya yang bermasalah. Konsekuensinya penanganannya pun berbeda — inilah yang menentukan rencana pada Bagian 5.

Tabel Temuan dan Rencana Penanganan #

Kita rangkum seluruh temuan beserta rencana penanganannya — daftar ini menjadi kontrak kerja untuk Bagian 5:

MasalahLetakDampak bila dibiarkanRencana penanganan
Baris duplikat persisJoko (2 baris identik)Joko terhitung ganda di rata-rataBuang baris salinan
Sel kehadiran -UmaKolom kehadiran tak bisa dihitung; P2 tak terjawabSelidiki: isi ulang bila ada dasarnya, bila tidak, buang barisnya
Kelas tertulis aGitaKelas terpisah menjadi tiga kelompok saat agregasiSeragamkan ke huruf besar

Perhatikan rencana untuk sel - sengaja ditulis dua langkah. Mengisi ulang hanya jujur bila ada rumus atau sumber lain untuk menghitung nilainya — pada proyek penjualan dulu kita bisa menghitung gelas dari pendapatan dibagi harga satuan. Untuk kehadiran, tidak ada kolom lain yang bisa dipakai menghitungnya, dan menebak dengan rata-rata justru menambah angka rekayasan ke data. Keputusan akhirnya kita ambil dengan mata terbuka pada Bagian 5.

Data mentah sudah dipetakan masalahnya sampai ke letak barisnya. Saatnya mengeksekusi rencana penanganan satu per satu hingga data siap dianalisis — kita kerjakan pada Bagian 5: Membersihkan Data .