Sel kosong adalah masalah data yang paling sering kita temui, dan pandas menanganinya dengan satu penanda khusus bernama NaN. Penanda ini berperilaku tidak biasa dibanding nilai biasa: perbandingannya selalu gagal dan operasi aritmetika ikut tercemar. Chapter ini membahas apa itu missing values, bagaimana None Python berubah menjadi NaN, serta bagaimana pandas 3.0 menandai kekosongan pada tiap tipe data. Pemahaman ini menjadi fondasi sebelum kita menghitung dan membersihkan nilai kosong pada Chapter-Chapter berikutnya.

NaN: Penanda Kekosongan dari NumPy #

NaN adalah singkatan dari Not a Number, nilai khusus dari standar floating-point IEEE 754 yang dipinjam pandas dari NumPy. Meskipun namanya “bukan angka”, NaN bertipe float64, sehingga kehadirannya membuat kolom bilangan bulat berubah menjadi float64. Nilai ini bukan string "NaN" dan bukan None milik Python; ketiganya terlihat serupa di layar tetapi identitasnya berbeda. Ketika kita menulis None di dalam data numerik, pandas mengonversinya menjadi NaN, dan itulah bentuk yang tersimpan di memori.

None dan np.nan di Dua Tipe Kolom #

Skrip berikut membuat dua Series dari dataset pesanan yang sama: satu berisi angka umur dan satu berisi teks nama_pelanggan. Keduanya memuat satu nilai kosong, lalu kita bandingkan cara pandas 3.0 menyimpannya. Perhatikan pula hasil dua perbandingan di bagian bawah output, yang memperlihatkan sifat aneh NaN:

python
import numpy as np
import pandas as pd

umur = pd.Series([29, 34, None, 41])
print(umur)
print("dtype:", umur.dtype)

nama = pd.Series(["Budi", None, "Dewi"])
print(nama)
print("dtype:", nama.dtype)

print("np.nan == np.nan ->", np.nan == np.nan)
print("pd.isna(np.nan)  ->", pd.isna(np.nan))
print("Sel kosong umur  :", umur.isna().sum())
print("Jumlah umur (sum):", umur.sum())

Output yang Dihasilkan:

text
0    29.0
1    34.0
2     NaN
3    41.0
dtype: float64
dtype: float64
0    Budi
1     NaN
2    Dewi
dtype: str
dtype: str
np.nan == np.nan -> False
pd.isna(np.nan)  -> True
Sel kosong umur  : 1
Jumlah umur (sum): 104.0

Mari kita telaah apa yang terjadi pada kode di atas:

  1. Baris 4 (umur = pd.Series([29, 34, None, 41])): kita membuat Series angka dengan satu None di tengah.
  2. Baris 5-6: pandas menampilkan nilai kosong sebagai NaN dan melaporkan dtype float64; angka bulat 29 menjadi 29.0 karena seluruh kolom mengikuti tipe NaN.
  3. Baris 8-10: Series teks dengan satu None menghasilkan dtype str, tipe string bawaan pandas 3.0, dan kekosongan tetap tampil sebagai NaN, bukan pd.NA.
  4. Baris 12-13 (np.nan == np.nan): perbandingan NaN dengan NaN menghasilkan False sesuai aturan IEEE 754; satu-satunya cara mengujinya adalah pd.isna().
  5. Baris 14-15: isna().sum() menghitung satu sel kosong, sedangkan umur.sum() tetap menghasilkan 104.0 karena pandas melewati NaN saat menjumlahkan.

Perilaku Kekosongan pada Tiap Tipe Data #

Satu penanda tidak berlaku seragam untuk semua tipe. Tabel berikut merangkum penanda kekosongan yang dipakai pandas 3.0:

Tipe dataPenanda kosongContoh pada dataset pesanan
float64NaNKolom umur dan total_belanja
strNaNSel kota milik PSC-106
Int64 (nullable)<NA> (pd.NA)Bilangan bulat dengan sel kosong, dibahas pada Chapter Memperbaiki Tipe Data
datetime64NaTTanggal kosong

Perubahan paling penting di pandas 3.0 ada pada kolom teks. Sejak dtype str menjadi bawaan, nilai kosong pada kolom teks tetap NaN, bukan pd.NA; rincian migrasinya dijelaskan pada panduan pembaruan string pandas 3.0 . Konsekuensinya sederhana bagi kita: satu fungsi pd.isna() mampu mendeteksi kekosongan pada hampir semua tipe tanpa perkecualian. Panduan resmi Working with missing data merangkum seluruh perilaku ini beserta tabel konversinya.

Sekarang kita tahu bahwa kekosongan tersimpan sebagai NaN, NaT, atau pd.NA tergantung tipe kolom, dan bahwa perbandingan langsung tidak pernah berhasil. Pertanyaan berikutnya lebih praktis: berapa banyak sel kosong di setiap kolom, dan baris mana saja yang terdampak? Chapter Mendeteksi Nilai Kosong menjawabnya dengan fungsi pandas.isna beserta kebalikannya, notna().