Sebelum satu nilaipun diubah, seorang pembersih data yang baik selalu memeriksa lebih dulu. Data hasil ekspor dari aplikasi kasir, formulir, atau penggabungan beberapa sistem hampir selalu membawa masalah tersembunyi: nilai hilang, baris terekam dua kali, kolom angka yang ternyata teks, hingga harga yang salah ketik. Pada chapter ini kita membangun kebiasaan pemeriksaan awal yang sistematis memakai pandas — dari head(), shape, dtypes, info(), describe(), sampai isna() dan duplicated() — sehingga setiap masalah ketahuan sebelum kita memutuskan cara membersihkannya pada chapter-chapter berikutnya.

Berkas Latihan dari Aplikasi Kasir #

Berkas latihan kita adalah penjualan_kotor.csv — ekspor penjualan Toko Kopi Kita selama enam hari pada Januari 2026. Dua belas baris itu terlihat wajar di sekilas, tetapi sesungguhnya menyimpan enam jenis masalah berbeda yang akan kita temukan satu per satu. Aplikasi kasir menandai sel kosong dengan tanda -, sehingga kita mendaftarkan penanda itu lewat na_values sejak pembacaan — persis seperti yang kita pelajari pada chapter Membaca File CSV .

csv
tanggal,produk,jumlah,harga,pelanggan
2026-01-15,kopi susu,3,24000,Budi
2026-01-15,teh tawar,2,20000,Siti
2026-01-16,kopi susu,1,24000,Dewi
2026-01-16,matcha latte,4,28000,Rani
2026-01-17,americano,2,22000,Budi
2026-01-17,teh tawar,-,20000,Agus
2026-01-18,kopi susu ,5,24000,Siti
2026-01-18,americano,1,22000,-
2026-01-19,Americano,2,22000,Rani
2026-01-19,kopi susu,2,240000,Dewi
2026-01-20,matcha latte,2,28000,Agus
2026-01-20,matcha latte,2,28000,Agus

Melihat Cuplikan Data dengan head dan tail #

Langkah pertama adalah melihat wujud data secara langsung. head(7) menampilkan tujuh baris pertama; tail(3) menampilkan tiga baris terakhir. Dua cuplikan pendek ini biasanya cukup untuk mengenali bentuk kolom, gaya penulisan, dan beberapa gejala yang mencurigakan — misalnya nilai NaN atau angka yang tidak wajar.

python
import pandas as pd

df = pd.read_csv("penjualan_kotor.csv", na_values=["-"])
print(df.head(7))
print()
print(df.tail(3))

Output yang Dihasilkan:

text
      tanggal        produk  jumlah  harga pelanggan
0  2026-01-15     kopi susu     3.0  24000      Budi
1  2026-01-15     teh tawar     2.0  20000      Siti
2  2026-01-16     kopi susu     1.0  24000      Dewi
3  2026-01-16  matcha latte     4.0  28000      Rani
4  2026-01-17     americano     2.0  22000      Budi
5  2026-01-17     teh tawar     NaN  20000      Agus
6  2026-01-18    kopi susu      5.0  24000      Siti

       tanggal        produk  jumlah   harga pelanggan
9   2026-01-19     kopi susu     2.0  240000      Dewi
10  2026-01-20  matcha latte     2.0   28000      Agus
11  2026-01-20  matcha latte     2.0   28000      Agus

Mari kita telaah baris-barisnya:

  1. Baris 3 (pd.read_csv(...)): berkas dibaca menjadi DataFrame; setiap - diubah menjadi NaN, penanda nilai hilang milik pandas.
  2. Baris 4 (df.head(7)): tujuh baris pertama tampil dengan rapi. Perhatikan baris berindeks 5: kolom jumlah berisi NaN — di berkas aslinya tertulis -.
  3. Baris 6 (df.tail(3)): tiga baris terakhir menyimpan dua gejala sekaligus: harga 240000 yang jauh di atas harga kopi susu biasanya (24000), dan dua baris berindeks 10-11 yang tampak identik.

Pada tahap ini kita belum menyimpulkan apa pun — kita hanya mencatat dugaan. Pemeriksaan berikutnya bertugas membuktikan apakah dugaan itu benar.

Mengukur Ukuran dan Tipe dengan shape dan dtypes #

Pertanyaan paling dasar tentang sebuah dataset: berapa baris dan kolomnya, serta tipe apa yang tersimpan di tiap kolom. Dua hal itu dijawab oleh atribut shape dan dtypes. Tipe kolom menentukan operasi apa yang sah: kolom object (teks) tidak bisa dihitung rata-ratanya, sedangkan kolom datetime64 bisa diurutkan kronologis. Rujukan tata cara pembacaan berkas dan penentu tipe tersedia di dokumentasi pandas.read_csv .

python
import pandas as pd

df = pd.read_csv("penjualan_kotor.csv", na_values=["-"])
print("Ukuran data (baris, kolom):", df.shape)
print()
print(df.dtypes)

Output yang Dihasilkan:

text
Ukuran data (baris, kolom): (12, 5)

tanggal       object
produk        object
jumlah       float64
harga          int64
pelanggan     object
dtype: object

Mari kita telaah hasilnya:

  1. df.shape: data memuat 12 baris dan 5 kolom — angka yang perlu kita ingat sebagai patokan sebelum dan sesudah pembersihan.
  2. df.dtypes: kolom tanggal bertipe object, padahal isinya tanggal — pandas tidak menebak tanggal secara otomatis, sehingga kolom ini belum bisa diurutkan secara kronologis.
  3. Kolom jumlah bertipe float64: satu nilai NaN memaksa seluruh kolom naik ke tipe desimal, karena tipe bilangan bulat tidak sanggup menyimpan NaN. Kolom harga tetap int64 karena isinya lengkap.

Melihat Kelengkapan Baris dengan info #

info() merangkum tiga pemeriksaan sebelumnya dalam satu cetakan: jumlah baris, nama kolom beserta tipe, dan yang paling berharga — Non-Null Count, yaitu banyaknya baris yang benar-benar berisi nilai pada tiap kolom. Selisih antara jumlah baris dan non-null count adalah jumlah nilai hilang.

python
import pandas as pd

df = pd.read_csv("penjualan_kotor.csv", na_values=["-"])
df.info()

Output yang Dihasilkan:

text
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 12 entries, 0 to 11
Data columns (total 5 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   tanggal    12 non-null     object 
 1   produk     12 non-null     object 
 2   jumlah     11 non-null     float64
 3   harga      12 non-null     int64  
 4   pelanggan  11 non-null     object 
dtypes: float64(1), int64(1), object(3)
memory usage: 612.0+ bytes

Cetakan tersebut memberi tiga temuan. Pertama, RangeIndex: 12 entries mengonfirmasi 12 baris. Kedua, kolom jumlah hanya memiliki 11 nilai non-null — ada satu nilai hilang. Ketiga, kolom pelanggan juga hanya 11 non-null. Bandingkan dengan df.isna() yang akan kita jalankan sebentar lagi: info() memperlihatkan gambaran umum, sedangkan penghitungan eksplisit memudahkan pencatatan.

Ringkasan Statistik dengan describe #

describe() menghitung statistik ringkas untuk semua kolom numerik sekaligus: jumlah nilai (count), rata-rata (mean), simpangan baku (std), nilai terkecil-terbesar, serta kuartil (25%, 50%, 75%). Kuartil adalah nilai batas ketika data diurutkan lalu dibagi empat bagian sama banyak. Panduan penggunaan fungsi agregasi semacam ini tersedia pada pandas user guide .

python
import pandas as pd

df = pd.read_csv("penjualan_kotor.csv", na_values=["-"])
print(df.describe())

Output yang Dihasilkan:

text
          jumlah          harga
count  11.000000      12.000000
mean    2.363636   41833.333333
std     1.206045   62473.024482
min     1.000000   20000.000000
25%     2.000000   22000.000000
50%     2.000000   24000.000000
75%     2.500000   28000.000000
max     5.000000  240000.000000

Mari kita baca angka-angkanya dengan teliti:

  1. Kolom jumlah: count hanya 11 dari 12 baris — bukti lain satu nilai hilang. Rata-rata 2,36 cangkir per transaksi terasa wajar untuk sebuah kafe.
  2. Kolom harga: mean sekitar 41.833, padahal separuh transaksi berada di harga 24.000 ke bawah dan kuartil ketiganya 28.000. Nilai max 240.000 — hampir sembilan kali menu termahal — hampir pasti salah ketik, bukan menu premium.
  3. Pola umumnya: ketika max menjulang jauh di atas kuartil ketiga, curigai pencilan (outlier) atau salah ketik. Kita akan menanganinya khusus pada chapter Menangani Outlier .

Menghitung Nilai Hilang dan Baris Duplikat #

Dugaan dari info() dan describe() perlu angka pasti. Dua perintah berikut menghitungnya: isna().sum() menjumlahkan nilai hilang per kolom, sedangkan duplicated().sum() menghitung baris yang sama persis dengan baris sebelumnya.

python
import pandas as pd

df = pd.read_csv("penjualan_kotor.csv", na_values=["-"])
print("Nilai hilang per kolom:")
print(df.isna().sum())
print()
print("Baris duplikat penuh:", df.duplicated().sum())

Output yang Dihasilkan:

text
Nilai hilang per kolom:
tanggal      0
produk       0
jumlah       1
harga        0
pelanggan    1
dtype: int64

Baris duplikat penuh: 1

Hasilnya lugas: satu nilai hilang di jumlah, satu di pelanggan, dan satu baris tercatat dua kali secara penuh — baris terakhir 2026-01-20 yang tampil kembar pada tail(3) di awal chapter. Tiga temuan ini menjadi pekerjaan utama dua chapter berikutnya.

Memeriksa Nilai Unik Kolom Teks #

Kolom teks menyimpan masalah yang tidak terlihat di describe(): nilai yang tertulis mirip tetapi dianggap berbeda oleh komputer. value_counts() menghitung frekuensi tiap nilai, dan daftar nilai unik hasil sorted(...) memperlihatkan setiap perbedaan sekecil apa pun — termasuk spasi tersembunyi.

python
import pandas as pd

df = pd.read_csv("penjualan_kotor.csv", na_values=["-"])
print(df["produk"].value_counts())
print()
print("Daftar nilai unik (urut abjad):")
print(sorted(df["produk"].unique()))

Output yang Dihasilkan:

text
produk
kopi susu       3
matcha latte    3
teh tawar       2
americano       2
kopi susu       1
Americano       1
Name: count, dtype: int64

Daftar nilai unik (urut abjad):
['Americano', 'americano', 'kopi susu', 'kopi susu ', 'matcha latte', 'teh tawar']

Tabel frekuensi tersebut membuka masalah yang tersembunyi rapi:

  1. 'kopi susu ' dengan spasi di ujung hadir sebagai nilai tersendiri: pada tabel frekuensi, kopi susu tampil dua kali dengan jumlah berbeda (3 dan 1) padahal barisnya tampak sama. Satu transaksi terpisah dari tiga transaksi kopi susu lainnya hanya karena spasi tersembunyi.
  2. 'Americano' berhuruf besar juga dihitung terpisah dari 'americano'.
  3. Akibatnya: penjualan per produk akan melaporkan enam produk padahal sebenarnya hanya ada empat. Perbaikannya menjadi pokok chapter Membersihkan Teks dan Menangani Data Tidak Konsisten .

Daftar Periksa Pemeriksaan Awal #

Pemeriksaan awal yang kita lakukan di atas dapat dirangkum menjadi daftar periksa ringkas. Kolom temuan memuat apa yang sebenarnya kita temukan pada penjualan_kotor.csv — bukti bahwa daftar periksa ini bekerja pada data nyata, bukan sekadar teori.

PertanyaanPerintahTemuan pada berkas latihan
Bagaimana wujud datanya?df.head(), df.tail()Ada NaN; dua baris akhir tampak kembar
Berapa baris dan kolomnya?df.shape12 baris, 5 kolom
Tipe apa di tiap kolom?df.dtypes, df.info()tanggal masih object; jumlah naik ke float64
Berapa nilai yang hilang?df.isna().sum()1 di jumlah, 1 di pelanggan
Ada baris terekam dua kali?df.duplicated().sum()1 baris duplikat penuh
Adakah angka tidak wajar?df.describe()max harga 240.000 jauh di atas kuartil ketiga
Adakah teks bervarian?value_counts(), unique()Spasi di ujung 'kopi susu '; kapital 'Americano'

Rangkuman #

  • Pemeriksaan awal selalu mendahului pembersihan: kita mencatat masalah lebih dulu, baru memutuskan perbaikannya pada chapter yang sesuai.
  • shape dan dtypes menjawab ukuran serta tipe; info() menambahkan non-null count yang mengungkap kolom tidak lengkap.
  • describe() merangkum statistik numerik; jarak besar antara kuartil ketiga dan max adalah penanda pencilan atau salah ketik.
  • isna().sum() dan duplicated().sum() mengubah dugaan menjadi hitungan pasti; value_counts() membongkar variasi teks tersembunyi.
  • Berkas latihan kita terbukti memuat enam masalah: nilai hilang, duplikat, tipe kolom salah, teks bervarian, dan harga salah ketik.

Koleksi masalah telah lengkap, dan urutan pengerjaannya mengikuti urutan daftar periksa di atas. Masalah pertama yang paling sering dijumpai di data nyata adalah nilai hilang — kapan baris boleh dibuang, kapan harus diisi, dan diisi dengan apa. Kita bedah strateginya pada chapter berikutnya, Menangani Missing Values .