Bab-bab sebelumnya menyediakan perkakas terpisah: deteksi pada Chapter Memeriksa Nilai Valid, agregasi pada Chapter NaN-aware Aggregation, penyaringan pada Chapter Filtering Nilai Tidak Valid, dan penggantian pada Chapter Mengganti Nilai Tertentu. Pekerjaan sebenarnya merangkai semuanya menjadi satu alur yang bisa diulang: deteksi → keputusan kebijakan → penerapan → verifikasi.

Sebagai contoh yang berjalan sepanjang bab, kita memakai log stasiun cuaca kecil: empat pengamatan, masing-masing berisi suhu dan kelembapan. Dua baris bermasalah — satu kehilangan suhu, satu kehilangan kelembapan. Data kecil ini sengaja dipilih agar setiap angka bisa kita periksa dengan mata.

Tahap 1: Deteksi #

python
import numpy as np

data = np.array([
    [26.5, 71.0],
    [np.nan, 72.5],
    [28.0, np.nan],
    [27.2, 69.0],
])
print(np.isnan(data))
print("nan per kolom:", np.isnan(data).sum(axis=0))
print("baris bermasalah  :", np.isnan(data).any(axis=1))
print("jumlah baris bermasalah:", int(np.isnan(data).any(axis=1).sum()))

Output yang Dihasilkan:

text
[[False False]
 [ True False]
 [False  True]
 [False False]]
nan per kolom: [1 1]
baris bermasalah  : [False  True  True False]
jumlah baris bermasalah: 2

Mari kita bedah:

  1. Baris 3-8: matriks (4, 2); baris 2 kehilangan suhu, baris 3 kehilangan kelembapan.
  2. Baris 10 (sum(axis=0)): hitungan per kolom — masing-masing kolom kehilangan satu nilai, informasi penting untuk imputasi.
  3. Baris 11 (any(axis=1)): hitungan per baris — dua baris menyentuh nan, hasil ini yang menentukan jalur pembuangan baris dari Chapter Filtering Nilai Tidak Valid.

Tahap 2: Memilih Kebijakan #

Sebelum menyentuh data lagi, kebijakan perlu dipilih secara sadar. Tabel berikut merangkum pilihan yang tersedia:

KebijakanCocok ketikaRisiko
Buang baris tidak validdata cukup banyak dan baris bermasalah sedikitkehilangan kolom lain yang masih valid
Isi dengan statistik kolom (imputasi mean)data sedikit atau pengamatan mahal diperolehvariance mengecil, sebaran tergeser ke titik tengah
Isi dengan nilai tetap (mis. 0.0)nan punya makna khusus, misalnya sensor tidak aktifdistribusi terdistorsi bila maknanya bukan nol
Tandai dengan masked arrayanalisis lanjutan perlu tahu posisi data hilangkode lebih panjang, aturan np.ma perlu dipelajari

Pada log kita, dua dari empat baris bermasalah — porsi 50 persen. Membuang separuh pengamatan layak diragukan, tetapi imputasi juga bukan tanpa biaya. Karena itu kedua jalur utama kita kerjakan berdampingan, lalu hasilnya dibandingkan.

Jalur A: Membuang Baris Tidak Valid #

python
import numpy as np

data = np.array([
    [26.5, 71.0],
    [np.nan, 72.5],
    [28.0, np.nan],
    [27.2, 69.0],
])
bersih = data[~np.isnan(data).any(axis=1)]
print(bersih)
print("NaN tersisa         :", np.isnan(bersih).sum())
print("Rata-rata suhu      :", bersih[:, 0].mean())
print("Rata-rata kelembapan:", bersih[:, 1].mean())

Output yang Dihasilkan:

text
[[26.5 71. ]
 [27.2 69. ]]
NaN tersisa         : 0
Rata-rata suhu      : 26.85
Rata-rata kelembapan: 70.0

Penjelasan singkat:

  1. Baris 9 (~np.isnan(data).any(axis=1)): baris yang menyentuh nan dibuang sekaligus, menyisakan dua baris utuh.
  2. Baris 11: verifikasi pertama — hitung ulang; hasilnya 0, tidak ada nan yang lolos.
  3. Baris 12-13: statistik dihitung ulang atas data bersih: rata-rata suhu 26.85 dari dua pengamatan yang tersisa.

Jalur B: Mengisi dengan Rata-rata Kolom #

python
import numpy as np

data = np.array([
    [26.5, 71.0],
    [np.nan, 72.5],
    [28.0, np.nan],
    [27.2, 69.0],
])
isi = data.copy()
for kolom in range(isi.shape[1]):
    mask = np.isnan(isi[:, kolom])
    isi[mask, kolom] = np.nanmean(isi[:, kolom])
print(isi)
print("NaN tersisa         :", np.isnan(isi).sum())
print("Rata-rata suhu      :", isi[:, 0].mean())
print("Rata-rata kelembapan:", isi[:, 1].mean())

Output yang Dihasilkan:

text
[[26.5        71.        ]
 [27.23333333 72.5       ]
 [28.         70.83333333]
 [27.2        69.        ]]
NaN tersisa         : 0
Rata-rata suhu      : 27.233333333333334
Rata-rata kelembapan: 70.83333333333333

Mari kita telaah:

  1. Baris 9 (isi = data.copy()): data mentah tetap utuh sebagai arsip; perubahan hanya terjadi pada salinannya.
  2. Baris 10-12: loop berjalan per kolom karena angka pengganti berbeda — suhu diganti rata-rata suhu valid (27.23333333), kelembapan diganti rata-rata kelembapan valid (70.83333333); penugasan mask per kolom adalah pola dari Chapter Mengganti Nilai Tertentu.
  3. Baris 13-16: verifikasi ulang — nan tersisa 0, dan keempat baris tetap dipertahankan.

Tahap 4: Membandingkan dan Melaporkan #

Kedua jalur sama-sama menghasilkan data bebas nan, tetapi angkanya berbeda — dan perbedaan itu adalah pesan penting bab ini:

  1. Jumlah baris: jalur A menyisakan 2 dari 4 pengamatan; jalur B mempertahankan seluruh 4 baris.
  2. Rata-rata suhu: 26.85 (buang) versus 27.233333333333334 (isi). Nilai pengganti adalah rata-rata kolom itu sendiri, sehingga imputasi menarik rata-rata hasil mendekati pusat data valid.
  3. Rata-rata kelembapan: 70.0 (buang) versus 70.83333333333333 (isi) — geseran yang sama terlihat di kolom kedua.

Sebagai penutup, verifikasi akhir sebuah pipeline pembersihan setidaknya mencakup tiga pemeriksaan:

  1. Hitung ulang nilai tidak valid setelah penerapan — hasilnya harus nol, atau sesuai target yang ditetapkan.
  2. Bandingkan statistik sebelum dan sesudah, untuk melihat seberapa besar pengaruh kebijakan yang dipilih.
  3. Catat kebijakan yang dipakai beserta alasannya, agar langkah pembersihan bisa diulang dengan hasil yang sama.

Alur deteksi → keputusan → penerapan → verifikasi ini bukan khusus NumPy; pola yang sama berlaku saat data berpindah ke pustaka seperti pandas. Yang berubah hanya perkakasnya — fondasinya sudah kita bangun di section ini.