Data dunia nyata hampir selalu berlubang: sensor mati selama beberapa jam, responden melewatkan satu pertanyaan, dan sel kosong di file Excel terbaca sebagai “tidak ada nilai”. MATLAB menandai lubang tersebut dengan NaN — Not a Number — beserta dua tetangganya Inf dan -Inf untuk nilai tak hingga. Bab ini membahas asal-usul ketiganya, sifat khusus NaN yang tidak sama dengan apa pun, cara mendeteksinya dengan isnan/isinf/isfinite, dan pola aman menghitung statistik tanpa terkontaminasi missing values.

Asal-usul NaN #

Aturannya: NaN adalah hasil operasi aritmetika yang tidak terdefinisikan secara matematis. Dua sumber paling umum adalah 0/0 dan Inf - Inf. Mekanismenya mengikuti standar IEEE 754 untuk floating-point: pola bit khusus merepresentasikan NaN, dan operasi yang menghasilkan NaN tidak menghentikan program — nilai khusus tersebut “menular” ke perhitungan berikutnya:

matlab
fprintf('0/0     = %g\n', 0/0);
fprintf('Inf-Inf = %g\n', Inf - Inf);

Output yang Dihasilkan:

text
0/0     = NaN
Inf-Inf = NaN

Sifat NaN: Tidak Sama dengan Apa Pun #

Aturan paling mengejutkan dari NaN: NaN tidak sama dengan nilai apa pun — termasuk NaN yang lain. Standar IEEE 754 menetapkan bahwa setiap perbandingan yang melibatkan NaN menghasilkan false, sehingga NaN == NaN bernilai 0 dan NaN ~= NaN bernilai 1:

matlab
fprintf('NaN == NaN : %d\n', NaN == NaN);
fprintf('NaN ~= NaN : %d\n', NaN ~= NaN);

Output yang Dihasilkan:

text
NaN == NaN : 0
NaN ~= NaN : 1

Konsekuensinya besar: perbandingan x == NaN tidak pernah menghasilkan true, sehingga perbandingan langsung tidak bisa dipakai untuk mencari missing values. Kita harus bertanya pada fungsi khusus yang memeriksa pola bit-nya.

Deteksi dengan isnan, isinf, isfinite #

Keluarga fungsi pemeriksa mengembalikan logical array: nilai 1 pada posisi elemen yang memenuhi kriteria, nilai 0 pada sisanya. Mekanismenya: fungsi-fungsi ini memeriksa representasi bit setiap elemen, bukan membandingkan nilainya — itulah sebabnya isnan berhasil menangkap NaN yang tak bisa ditangkap ==:

FungsiMengembalikan 1 padaContoh
isnan(x)NaNisnan(NaN) → 1
isinf(x)Inf dan -Infisinf(-Inf) → 1
isfinite(x)bilangan hingga (bukan NaN dan bukan Inf)isfinite(25) → 1

Contoh berikut memeriksa data suhu dari sensor yang dua kali gagal merekam:

matlab
suhu = [24.5 NaN 25.1 24.8 NaN 26.0];
fprintf('isnan(suhu)   : %d %d %d %d %d %d\n', isnan(suhu));
fprintf('jumlah missing: %d dari %d data\n', sum(isnan(suhu)), numel(suhu));

Output yang Dihasilkan:

text
isnan(suhu)   : 0 1 0 0 1 0
jumlah missing: 2 dari 6 data

Mari kita bedah baris-baris kode di atas:

  1. Baris 2 (isnan(suhu)): menghasilkan vektor logical [0 1 0 0 1 0] — posisi 2 dan 5 adalah lubang data.
  2. Baris 3 (sum(isnan(suhu))): sum menjumlahkan nilai logical 1, sehingga hasilnya adalah jumlah missing values; numel melaporkan total elemen.

Propagasi NaN dalam Operasi #

Aturan penularan: satu NaN di input menghasilkan NaN di output. Perkalian 5 * NaN menghasilkan NaN, dan fungsi agregasi seperti sum serta mean ikut terkontaminasi. Tabel berikut menunjukkan perilaku fungsi-fungsi umum pada [1 NaN 3]:

FungsiHasilPerilaku
sum([1 NaN 3])NaNNaN menular
mean([1 NaN 3])NaNNaN menular
max([1 NaN 3])3NaN diabaikan
min([1 NaN 3])1NaN diabaikan

Solusi universalnya adalah pola mask: logical array ~isnan(x) bernilai 1 pada data valid; pengindeksan x(mask) hanya memilih elemen valid itu (pola logical indexing yang dibahas pada Chapter Logical Indexing):

matlab
mask = ~isnan(suhu);           % logical mask: 1 = data valid

fprintf('mean(suhu)             : %g\n', mean(suhu));
fprintf('mean(suhu(mask))       : %g\n', mean(suhu(mask)));
fprintf('mean(suhu, ''omitnan''): %g\n', mean(suhu, 'omitnan'));

Output yang Dihasilkan:

text
mean(suhu)             : NaN
mean(suhu(mask))       : 25.1
mean(suhu, 'omitnan'): 25.1

Mari kita bedah baris-baris kode di atas:

  1. Baris 3 (mean(suhu)): rata-rata mentah terkontaminasi NaN — satu lubang cukup untuk merusak seluruh hasil.
  2. Baris 4 (mean(suhu(mask))): mask memilih hanya 24.5, 25.1, 24.8, 26.0 → rata-rata 100.4/4 = 25.1.
  3. Baris 5 (mean(suhu, 'omitnan')): opsi 'omitnan' (MATLAB R2015b ke atas; juga didukung Octave 10) memerintahkan mean melewatkan NaN secara internal — hasilnya sama dengan pola mask.

Mengganti Missing dengan Nilai Pengganti #

Setelah data valid terkumpul, kita bisa mengisi lubang dengan nilai pengganti — di sini rata-rata data valid:

matlab
bersih = suhu;
bersih(isnan(bersih)) = mean(suhu(mask));

fprintf('bersih        : %.1f %.1f %.1f %.1f %.1f %.1f\n', bersih);

Output yang Dihasilkan:

text
bersih        : 24.5 25.1 25.1 24.8 25.1 26.0

Mari kita bedah baris-baris kode di atas:

  1. Baris 1 (bersih = suhu): salinan dibuat lebih dulu agar data asli suhu tetap utuh sebagai bukti.
  2. Baris 2 (bersih(isnan(bersih)) = ...): logical indexing di sisi kiri assignment menyeleksi posisi NaN sebagai target pengisian — dua posisi lubang diganti 25.1.

Inf, -Inf, dan Data Nyata #

Nilai tak hingga muncul dari operasi yang melampaui jangkauan bilangan: 1/0 menghasilkan Inf, log(0) menghasilkan -Inf. Keduanya juga bukan bilangan hingga sehingga isfinite mengembalikan 0 — sama seperti NaN:

matlab
fprintf('1/0    = %g\n', 1/0);
fprintf('log(0) = %g\n', log(0));
fprintf('isinf(Inf)   : %d\n', isinf(Inf));
fprintf('isinf(-Inf)  : %d\n', isinf(-Inf));
fprintf('isfinite(Inf): %d\n', isfinite(Inf));
fprintf('isfinite(25) : %d\n', isfinite(25));
fprintf('isfinite(NaN): %d\n', isfinite(NaN));

Output yang Dihasilkan:

text
1/0    = Inf
log(0) = -Inf
isinf(Inf)   : 1
isinf(-Inf)  : 1
isfinite(Inf): 0
isfinite(25) : 1
isfinite(NaN): 0

Terakhir, satu catatan praktis: pada data nyata, missing values biasanya bukan hasil 0/0, melainkan baris atau sel kosong yang otomatis terbaca sebagai NaN ketika kita mengimpor file — mekanisme pembacaan data dibahas pada Section Import dan Export Data, dan strategi pembersihan menyeluruh pada Chapter Missing Data di Section Pengolahan Data.

Ringkasan #

NaN menandai hasil tak terdefinisi (0/0, Inf-Inf), tidak pernah sama dengan nilai apa pun, dan menular ke seluruh perhitungan yang menyentuhnya — tetapi max/min justru mengabaikannya secara default. Deteksi wajib memakai isnan (beserta isinf dan isfinite), lalu pola mask x(~isnan(x)) menjadi senjata portabel untuk statistik yang bersih. Berkas contoh.m pada bagian bawah halaman menguji seluruh sifat NaN dan Inf di atas secara utuh.