Idenya
Sebelum menganalisis apa pun, lihat datanya. Setiap analyst berpengalaman menjalankan cek kesehatan singkat yang sama pada dataset baru, karena data hampir tidak pernah sesuai dengan yang dikatakan di email: kolom angka yang disimpan sebagai teks, kota yang kosong untuk sebagian customer, nilai status yang tidak pernah disebut siapa pun, baris header yang terduplikasi di tengah file.
pandas memberimu sekumpulan kecil method untuk pengecekan ini. Semuanya memakan waktu lima menit dan menghemat berjam-jam analisis yang membingungkan di kemudian hari. Kamu akan memakai sales.csv milik Toko Kita, satu baris per produk dalam sebuah order.
import pandas as pd
sales = pd.read_csv("sales.csv")
head dan tail: lihat beberapa baris
Pertanyaan paling pertama tentang dataset apa pun adalah "sebenarnya satu baris ini mewakili apa?". Satu pelanggan, satu pesanan, satu produk dalam sebuah pesanan? Cara tercepat untuk mengetahuinya adalah melihat beberapa baris dari atas dan dari bawah:
print(sales[["order_id", "customer", "product", "status"]].head())
print(sales[["order_id", "customer", "product", "status"]].tail(3))
order_id customer product status
0 1 Kartika Rahma Desk Organizer completed
1 2 Citra Dewi Arabica Gayo 250g completed
2 3 Eka Putri Pour-over Kettle completed
3 4 Citra Dewi Scented Candle completed
4 4 Citra Dewi Throw Pillow completed
order_id customer product status
68 39 Citra Dewi Toraja Kalosi 250g cancelled
69 40 Joko Susilo Arabica Gayo 250g cancelled
70 40 Joko Susilo Robusta Lampung 250g cancelled
.head() menampilkan 5 baris pertama (atau .head(n)), .tail() baris-baris terakhir. Dari sini saja kamu sudah belajar sesuatu: order 4 muncul dua kali, jadi setiap baris adalah baris produk, bukan order. Salah memahami arti satu baris adalah kesalahan analisis yang paling umum.
.sample(5) menampilkan baris acak, yang berguna karena masalah sering bersembunyi di tengah file.
shape, columns dan dtypes
Berikutnya: seberapa besar datanya, kolom apa saja yang dimilikinya, dan menurut pandas setiap kolom berisi jenis data apa? Ketiga atribut ini menjawabnya:
print(sales.shape)
print(list(sales.columns))
print(sales.dtypes)
(71, 12)
['order_id', 'order_date', 'customer', 'city', 'segment', 'product', 'category', 'quantity', 'unit_price', 'revenue', 'channel', 'status']
order_id int64
order_date object
customer object
city object
segment object
product object
category object
quantity int64
unit_price int64
revenue int64
channel object
status object
dtype: object
dtypes adalah baris terpenting dari cek kesehatan:
int64: bilangan bulat.float64: desimal (dan kolom angka apa pun yang punya nilai hilang).object: teks, atau campuran hal yang tidak bisa diberi tipe lebih spesifik oleh pandas.bool,datetime64[ns]dancategorymuncul setelah kamu mengonversi kolom.
Perhatikan order_date bertipe object, teks biasa, bukan tanggal. Kamu tidak bisa memfilter berdasarkan bulan atau menghitung durasi sampai kolom itu dikonversi (modul 10). Dan kalau kolom yang kamu kira berisi angka tampil sebagai object, ada nilai di dalamnya yang bukan angka, mungkin "N/A" atau "1.250.000", dan penjumlahan akan gagal atau, lebih parah, malah menyambung string.
info: ringkasan satu layar
Ada satu method yang mencakup sebagian besar cek kesehatan dalam satu panggilan. Biasanya inilah yang pertama kali dijalankan analyst setelah memuat sebuah file:
sales.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 71 entries, 0 to 70
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 order_id 71 non-null int64
1 order_date 71 non-null object
2 customer 71 non-null object
3 city 67 non-null object
4 segment 71 non-null object
5 product 71 non-null object
6 category 71 non-null object
7 quantity 71 non-null int64
8 unit_price 71 non-null int64
9 revenue 71 non-null int64
10 channel 71 non-null object
11 status 71 non-null object
dtypes: int64(4), object(8)
...
.info() menggabungkan shape, dtypes dan jumlah non-null per kolom. Ada 71 baris, tapi city hanya punya 67 nilai non-null, jadi 4 baris tidak punya kota. Satu angka itu memberi tahu bahwa kolom ini perlu diputuskan penanganannya sebelum kamu melakukan group by berdasarkan kota. (.info() langsung mencetak, jadi kamu memanggilnya tanpa print.) Baris terakhir, memory usage, tergantung komputermu, jadi tidak ditampilkan di atas.
Menghitung nilai yang hilang
Untuk mendapatkan jumlah nilai hilang sebagai data yang bisa kamu pakai, gabungkan .isna() (True di tempat nilainya hilang) dengan .sum() (True dihitung sebagai 1):
print(sales.isna().sum()[lambda counts: counts > 0])
city 4
dtype: int64
Bagian [lambda counts: counts > 0] hanya menyimpan kolom yang punya nilai hilang; kamu akan mempelajari gaya filter ini di modul 5. Kalau dipakai sendiri, sales.isna().sum() menampilkan semua kolom.
describe: angka dalam sekilas
Untuk kolom-kolom angka, kamu ingin tahu di rentang mana nilainya berada, dan apakah ada yang terlihat mustahil. .describe() memberimu ringkasan statistik dari setiap kolom angka sekaligus:
print(sales[["quantity", "unit_price", "revenue"]].describe())
quantity unit_price revenue
count 71.000000 71.000000 71.000000
mean 1.647887 140901.408451 246507.042254
std 0.794599 92952.699942 227977.935852
min 1.000000 38000.000000 38000.000000
25% 1.000000 65000.000000 89500.000000
50% 1.000000 110000.000000 150000.000000
75% 2.000000 185000.000000 320000.000000
max 3.000000 320000.000000 960000.000000
Untuk setiap kolom angka: jumlah data, rata-rata, standar deviasi (sebaran), nilai minimum, persentil ke-25/50/75 dan nilai maksimum. Bacalah seperti detektif:
- min dan max menangkap nilai yang mustahil: quantity negatif, harga 0, umur 200.
- mean vs 50% (median): rata-rata revenue (246.507) jauh lebih tinggi dari median-nya (150.000), jadi beberapa order besar menarik rata-ratanya ke atas. Itu petunjuk untuk melaporkan median juga.
- count yang lebih kecil dari jumlah baris berarti ada nilai yang hilang.
Untuk kolom teks, .describe(include="object") menampilkan jumlah data, banyaknya nilai unik, nilai yang paling sering muncul dan seberapa sering ia muncul.
Kategori: unique dan value_counts
Kolom teks seperti status dan category punya sekumpulan nilai yang terbatas, dan kamu perlu tahu apa saja nilainya sebelum memfilter atau mengelompokkan berdasarkan kolom itu. Status apa saja yang ada? Seberapa sering masing-masing muncul? Ada yang mengejutkan?
print(sales["status"].unique())
print(sales["status"].value_counts())
print(sales["category"].nunique())
['completed' 'cancelled' 'shipped' 'pending']
status
completed 45
cancelled 19
shipped 6
pending 1
Name: count, dtype: int64
5
.value_counts() adalah method favorit para analyst: ia menghitung setiap nilai yang berbeda, diurutkan dari yang paling sering ke yang paling jarang. Di sini terlihat bahwa 19 dari 71 baris dibatalkan, dan itu sangat penting: total revenue apa pun yang tidak menyaring order yang dibatalkan akan terlalu besar. Tambahkan normalize=True untuk mendapat proporsi alih-alih jumlah.
Jalankan value_counts() pada setiap kolom teks yang akan kamu kelompokkan atau filter. Method ini memunculkan typo ("Jakarta" vs "jakarta"), kategori yang tidak terduga, dan seberapa besar peran masing-masing.
Rutinitas cek kesehatan
Gabungkan semuanya dan kamu punya rutinitas untuk setiap file baru:
df.shape # seberapa besar?
df.head() # apa arti satu baris?
df.info() # tipe dan nilai yang hilang
df.describe() # rentang angka, outlier
df["col"].value_counts() # kategori, typo
df.duplicated().sum() # baris yang persis duplikat
df.duplicated() menandai baris yang merupakan salinan persis dari baris sebelumnya; menjumlahkannya akan menghitung banyaknya.
Mengapa ini penting untuk kode yang bersih
Analisis yang dibangun di atas data yang tidak diperiksa hanyalah tebak-tebakan. Menulis cek kesehatanmu sebagai kode (alih-alih menggulir spreadsheet) membuatnya bisa diulang: saat file bulan depan datang, kamu menjalankan ulang pengecekan yang sama dalam hitungan detik dan melihat apa yang berubah. Banyak tim mengubah pengecekan ini menjadi assertion di bagian atas pipeline mereka, seperti assert sales["revenue"].min() > 0, sehingga data yang buruk menghentikan proses alih-alih mengalir ke laporan.
Rangkuman
.head(),.tail(),.sample()menampilkan baris. Pertama, pahami apa yang diwakili oleh satu baris..shape,.columns,.dtypesmendeskripsikan strukturnya. Angka dan tanggal yang bertipe teks perlu dikonversi..info()menampilkan tipe dan jumlah non-null dalam satu tampilan;.isna().sum()menghitung nilai yang hilang..describe()merangkum kolom angka: perhatikan min/max, dan bandingkan mean dengan median..unique(),.nunique(),.value_counts()menjelajahi kategori..duplicated().sum()menghitung baris duplikat. Ubah rutinitas ini menjadi kode yang bisa kamu jalankan ulang.