Data nyata hampir selalu bolong. Sensor cuaca mati sehingga suhu satu hari tidak terekam, kasir lupa memasukkan harga — di MATLAB semua kekosongan numerik itu ditandai NaN (not a number), dan NaN menular: satu sel kosong cukup membuat mean seluruh kolom menjadi NaN. Chapter Missing Values dan NaN sudah memperkenalkan maknanya; kini kita tangani secara sistematis dengan tiga strategi menurut konteks data. Cakupan chapter ini:

  • Deteksi dan penghitungan sel hilang dengan isnan
  • Strategi hapus: buang observasi yang tidak lengkap
  • Strategi omit: statistik yang mengabaikan NaN
  • Strategi imputasi: isi ulang dengan median dan interpolasi linear

Dataset yang dipakai di chapter ini sengaja diberi lubang — unit hilang di hari 2 dan 8, harga hilang di hari 4 dan 11:

matlab
penjualanKotor = [1 12 15000; 2 NaN 15000; 3 9 16000; 4 22 NaN; 5 18 15000;
                  6 7 17000; 7 25 15000; 8 NaN 16000; 9 14 17000; 10 20 16000;
                  11 16 NaN; 12 19 15000];
suhuKotor = [30 32 NaN 29 33 NaN 31 30 35 32];   % 2 pengukuran gagal

NaN Menular ke Statistik #

Aturannya: satu NaN di input cukup membuat hasil operasi menjadi NaN — mean, sum, median, semuanya menulari. Mekanismenya: NaN didefinisikan tak setara dengan nilai mana pun, TERMASUK dirinya sendiri (NaN == NaN bernilai false), sehingga fungsi agregasi tidak bisa melewatkannya tanpa diperintahkan. Konsekuensinya langsung terasa:

matlab
fprintf('mean unit (ada NaN)  : %g\n', mean(penjualanKotor(:, 2)));

Output yang Dihasilkan:

text
mean unit (ada NaN)  : NaN

Penjelasan singkat: kolom unit memuat dua NaN, dan mean menjumlahkan seluruh elemen — jumlah yang tercemar NaN menghasilkan NaN. Perbandingan NaN == NaN yang selalu false juga berarti deteksi TIDAK bisa memakai ==; satu-satunya detektor yang benar adalah fungsi isnan.

Deteksi dan Menghitung dengan isnan #

Aturannya: isnan(M) menghasilkan mask logical seukuran M — true pada setiap sel hilang. Mekanismenya: mask tersebut memakai seluruh perangkat mask yang kita kuasai — sum untuk menghitung, any(..., 2) untuk menandai baris, dan negasi ~ untuk memilih bagian sehat:

matlab
fprintf('sel NaN di dataset   : %d\n', sum(isnan(penjualanKotor(:))));
fprintf('baris yang mengandung: %d\n', sum(any(isnan(penjualanKotor), 2)));

Output yang Dihasilkan:

text
sel NaN di dataset   : 4
baris yang mengandung: 4

Mari kita bedah baris-baris kode di atas:

  1. Baris 1 (sum(isnan(penjualanKotor(:)))): penjualanKotor(:) meratakan matriks menjadi satu kolom — pola dari Chapter Logical Indexing — lalu mask isnan dijumlahkan: empat sel kosong.
  2. Baris 2 (any(isnan(...), 2)): any dengan dimensi 2 menandai baris yang mengandung SATU SAJA sel NaN; empat baris (hari 2, 4, 8, 11) tercemar — mask baris inilah kunci seluruh strategi berikutnya.

Strategi 1: Hapus Baris Observasi #

Cara paling jujur terhadap data rusak: buang observasi yang tidak lengkap. Aturannya: mask barisKotor dari any(isnan(...), 2) dinegasikan lalu dipakai memilih baris — penjualanKotor(~barisKotor, :) mempertahankan hanya observasi utuh. Mekanismenya identik dengan filter baris pada Chapter Filtering; hanya sumber masknya yang berbeda:

matlab
barisKotor = any(isnan(penjualanKotor), 2);
penjualanBersih = penjualanKotor(~barisKotor, :);
fprintf('dataset bersih       : %d baris x %d kolom\n', ...
        size(penjualanBersih, 1), size(penjualanBersih, 2));

Output yang Dihasilkan:

text
dataset bersih       : 8 baris x 3 kolom

Mari kita bedah baris-baris kode di atas:

  1. Baris 1 (barisKotor = ...): mask 12×1 — true pada hari 2, 4, 8, 11.
  2. Baris 2 (penjualanBersih = ...): negasi ~barisKotor memilih delapan observasi sehat; dataset menyusut dari 12×3 menjadi 8×3 tanpa sel NaN tersisa. Strategi ini cocok saat jumlah data berlimpah dan baris rusaknya sedikit.

Strategi 2: Statistik yang Mengabaikan NaN #

Kadang data tidak boleh dibuang — kolom lain masih sehat. Aturannya: mask ~isnan(x) memilih hanya elemen valid, lalu statistik dihitung pada subset tersebut (pola omit). Mekanismenya: logical indexing memungut elemen sehat dari kolom, lalu mean/median bekerja normal pada subset itu:

matlab
unit = penjualanKotor(:, 2);
valid = ~isnan(unit);
fprintf('mean unit valid      : %.2f\n', mean(unit(valid)));
fprintf('median unit valid    : %.2f\n', median(unit(valid)));

Output yang Dihasilkan:

text
mean unit valid      : 16.20
median unit valid    : 17.00

Mari kita bedah baris-baris kode di atas:

  1. Baris 1-2 (valid = ~isnan(unit)): mask 12×1 bernilai true pada sepuluh hari yang unitnya terekam.
  2. Baris 3-4 (mean(unit(valid))): rata-rata dihitung dari sepuluh nilai saja — 16,20; median 17,00 — dua angka yang mustahil diperoleh tanpa menyaring NaN lebih dulu.

Strategi 3: Imputasi dengan Median dan Interpolasi #

Statistik valid, tapi laporan lengkap butuh dataset TANPA lubang — sel kosong diisi (imputasi). Aturannya: nilai pengganti dipilih menurut watak data — median untuk kolom tanpa pola waktu (tahan outlier), dan interpolasi linear interp1 untuk deret waktu yang bergerak mulus. Mekanismenya: mask isnan menunjuk posisi lubang; assignment menuliskan nilai pengganti tepat di sana:

matlab
unitIsi = unit;
unitIsi(~valid) = median(unit(valid));
fprintf('unit setelah imputasi: '); fprintf('%d ', unitIsi); fprintf('\n');

adaData = ~isnan(suhuKotor);
xAda = find(adaData);
xHilang = find(~adaData);
suhuIsi = suhuKotor;
suhuIsi(xHilang) = interp1(xAda, suhuKotor(xAda), xHilang);
fprintf('suhu setelah imputasi: '); fprintf('%g ', suhuIsi); fprintf('\n');
fprintf('mean suhu setelah isi: %.2f\n', mean(suhuIsi));

Output yang Dihasilkan:

text
unit setelah imputasi: 12 17 9 22 18 7 25 17 14 20 16 19
suhu setelah imputasi: 30 32 30.5 29 33 32 31 30 35 32
mean suhu setelah isi: 31.45

Mari kita bedah baris-baris kode di atas:

  1. Baris 1-2 (unitIsi(~valid) = median(...)): salinan dibuat dulu; dua posisi NaN (hari 2 dan 8) diisi median kolom sehat, yaitu 17 — median dipilih karena hari ekstrem (unit 25) tidak menyeret nilai pengganti.
  2. Baris 4-6 (find + interp1): xAda dan xHilang adalah indeks hari yang tercatat dan yang bolong; interp1(xAda, y, xHilang) menghubungkan titik tercatat dengan garis lurus lalu membaca nilai pada posisi hilang.
  3. Baris 7-9 (suhuIsi): hari 3 diisi 30,5 — tengah suhu hari 2 (32) dan hari 4 (29); hari 6 diisi 32, tengah 33 dan 31. Deret tetap mulus dan mean terhitung dari nilai terisi: 31,45.

Ringkasan pilihan strategi:

StrategiPanggilan kunciKapan dipakai
Hapus barisM(~any(isnan(M), 2), :)data berlimpah, baris rusak sedikit
Omit statistikmean(x(~isnan(x)))kolom lain masih dibutuhkan
Imputasi medianx(~v) = median(x(v))kolom tanpa pola waktu
Imputasi linearinterp1(xAda, y, xHilang)deret waktu bergerak mulus

Berkas contoh.m pada bagian bawah halaman menerapkan ketiga strategi berurutan pada dataset yang sama — deteksi, hapus baris, statistik mask, lalu dua imputasi.

Ringkasan #

Data hilang numerik ditandai NaN, menular ke seluruh statistik, dan tidak bisa dibandingkan dengan == — deteksinya lewat isnan, dihitung dengan sum(mask), dan diringkas per baris dengan any(isnan(M), 2). Selanjutnya: hapus baris M(~mask, :) saat data berlimpah, statistik pada x(~isnan(x)) saat kolom lain masih sehat, atau imputasi — median untuk kolom biasa, interp1 linear untuk deret waktu. Dataset bersih di tangan, kita siap merangkumnya di chapter Statistical Summary.