Analisis data yang terarah dimulai dari hal yang tampak paling sederhana: memeriksa satu variabel sampai tuntas. Analisis univariat adalah pemeriksaan satu kolom pada satu waktu — profilnya, bentuk sebarannya, nilai yang menonjol, hingga pola nilai kosongnya. Langkah ini terasa biasa, tetapi hampir semua kesalahan analisis yang serius berakar pada satu kolom yang belum dipahami: rata-rata yang ditarik nilai ekstrem, kategori yang luput tercatat, atau persentase yang dihitung dari data yang sebagian kosong. Pada chapter ini kita menyusun prosedur baku untuk menganalisis satu variabel, lalu menjalankannya tuntas pada satu dataset kecil.
Kerangka Pertanyaan untuk Satu Kolom #
Analisis univariat bukan sekadar memanggil satu fungsi, melainkan mengajukan daftar pertanyaan yang sama ke setiap kolom. Lima pertanyaan berikut membentuk kerangka kerja yang bisa kita pakai ulang di dataset apa pun:
| Pertanyaan | Untuk kolom numerik | Untuk kolom kategorikal |
|---|---|---|
| Di mana nilai berkumpul? | mean, median | kategori terbanyak (modus) |
| Seberapa lebar sebarannya? | simpangan baku, kuartil | jumlah kategori |
| Bagaimana bentuk sebarannya? | kemiringan (skewness) | proporsi kategori dominan |
| Ada nilai yang menonjol? | nilai minimum, maksimum, pencilan | kategori yang sangat jarang |
| Ada nilai yang kosong? | jumlah dan letak NaN | kategori “tidak tercatat” |
Rumus tendensi sentral dan penyebaran telah kita bahas pada chapter Ukuran Tendensi Sentral dan Ukuran Penyebaran , dan latihan praktisnya sudah kita cicipi pada Analisis Data Numerik . Peran chapter ini berbeda: kita menyusun seluruh pemeriksaan menjadi satu prosedur yang berurutan dan bisa direproduksi — profil numerik, profil kategorikal, kemiringan, lalu pola kosong — sebelum kita berani menyentuh hubungan antar variabel.
Dataset Catatan Transaksi Toko Kopi Kita #
Kita bekerja pada 40 transaksi dari Toko Kopi Kita yang memuat tiga kolom substantif: menu (kategorikal), nilai_ribu (nilai transaksi dalam ribuan rupiah), dan menunggu_menit (lama pesanan disiapkan). Kolom id hanyalah penomoran baris. Dataset ini sengaja memuat lima sel kosong dan satu pesanan katering seharga 150 ribu rupiah agar setiap pertanyaan pada kerangka di atas punya jawaban yang nyata:
id,menu,nilai_ribu,menunggu_menit
1,kopi susu,22,5
2,kopi susu,18,4
3,kopi susu,26,6
4,kopi susu,21,5
5,kopi susu,19,7
6,kopi susu,24,4
7,kopi susu,20,5
8,kopi susu,23,6
9,kopi susu,19,8
10,kopi susu,25,5
11,kopi susu,150,8
12,kopi susu,21,4
13,kopi susu,22,6
14,kopi susu,24,5
15,kopi hitam,17,6
16,kopi hitam,19,5
17,kopi hitam,16,4
18,kopi hitam,20,6
19,kopi hitam,18,5
20,kopi hitam,17,7
21,kopi hitam,,5
22,kopi hitam,,6
23,kopi hitam,,4
24,espresso,20,4
25,espresso,24,5
26,espresso,22,6
27,espresso,21,5
28,espresso,23,3
29,espresso,22,5
30,espresso,21,6
31,matcha latte,32,8
32,matcha latte,36,7
33,matcha latte,30,6
34,matcha latte,38,8
35,matcha latte,34,7
36,matcha latte,33,6
37,teh tawar,16,3
38,teh tawar,15,3
39,,21,5
40,,19,4Profil Numerik dengan describe() #
Fungsi describe() merangkum delapan statistik dalam satu panggilan. Kita menerapkannya pada dua kolom numerik substantif — kolom id sengaja dikeluarkan karena penomoran baris bukan variabel yang dianalisis:
import pandas as pd
transaksi = pd.read_csv("transaksi.csv")
print(transaksi[["nilai_ribu", "menunggu_menit"]].describe().round(2))
print()
print(transaksi.describe(include="object"))Output yang Dihasilkan:
nilai_ribu menunggu_menit
count 37.00 40.00
mean 26.16 5.42
std 21.68 1.38
min 15.00 3.00
25% 19.00 4.75
50% 21.00 5.00
75% 24.00 6.00
max 150.00 8.00
menu
count 38
unique 5
top kopi susu
freq 14Mari kita baca hasilnya per bagian:
count:nilai_ributerhitung 37 dari 40 baris — tiga sel kosong otomatis dilewati, dan selisih40 - 37adalah informasi, bukan sekadar keterbatasan.menunggu_menitlengkap 40.meanvs50%(median): padanilai_ribu, mean 26,16 berada jauh di atas median 21,00 — sinyal awal sebaran yang miring ke kanan. Padamenunggu_menit, mean 5,42 dan median 5,00 hampir berimpitan — sebaran yang relatif seimbang.maxvs kuartil: tiga perempat transaksi bernilai 24 ribu ke bawah, tetapimaxmelonjak ke 150 — pesanan katering itu sendirian di ekor kanan, sementarastd21,68 ikut membengkak karenanya.describe(include="object"): profil ringkas kolom kategorikal — 38 nilai tercatat, 5 kategori unik, kategori terbanyakkopi susudengan 14 kemunculan.
Profil Kategorikal dengan value_counts() #
Untuk kolom kategorikal, value_counts() adalah padanan describe(): ia menghitung frekuensi setiap kategori. Dua argumen membuat hasilnya jujur — dropna=False agar kategori “tidak tercatat” ikut tampil, dan normalize=True agar kita sekaligus memperoleh proporsi:
import pandas as pd
transaksi = pd.read_csv("transaksi.csv")
jumlah = transaksi["menu"].value_counts(dropna=False)
proporsi = transaksi["menu"].value_counts(dropna=False, normalize=True)
print(pd.DataFrame({"jumlah": jumlah, "proporsi": proporsi.round(3)}))Output yang Dihasilkan:
jumlah proporsi
menu
kopi susu 14 0.350
kopi hitam 9 0.225
espresso 7 0.175
matcha latte 6 0.150
teh tawar 2 0.050
NaN 2 0.050Bedah hasilnya:
- Modus terbaca langsung:
kopi susumendominasi 35% transaksi — menu andalan yang sehat untuk stok, tetapi juga menandai ketergantungan pada satu produk. NaNtampil sebagai baris: dua transaksi (5%) tidak mencatat menunya. Tanpadropna=False, baris ini diam-diam hilang dan tabel terlihat lebih bersih daripada kenyataannya.- Kategori langka tetap penting:
teh tawarhanya 5% — terlalu kecil untuk disimpulkan sendirian, tetapi cukup untuk menandainya saat kita membandingkan kelompok pada analisis berikutnya.
Membaca Kemiringan Sebaran #
Selisih mean dan median pada nilai_ribu tadi mengundang pertanyaan: seberapa miring sebarannya? Koefisien kemiringan (skew()) menjawab dengan satu angka — positif berarti ekor memanjang ke kanan, negatif berarti ekor memanjang ke kiri:
import pandas as pd
transaksi = pd.read_csv("transaksi.csv")
for kolom in ["nilai_ribu", "menunggu_menit"]:
s = transaksi[kolom]
print(f"{kolom:15s} skew {s.skew():6.2f} | mean {s.mean():6.2f} | median {s.median():6.2f}")Output yang Dihasilkan:
nilai_ribu skew 5.46 | mean 26.16 | median 21.00
menunggu_menit skew 0.23 | mean 5.42 | median 5.00Sebagai bahasa bersama, patokan berikut lazim dipakai untuk membaca angka kemiringan:
| Nilai skewness | Bentuk sebaran | Konsekuensi praktis |
|---|---|---|
| -0,5 sampai 0,5 | hampir simetris | mean dan median sama-sama layak dipakai |
| -1 sampai -0,5 atau 0,5 sampai 1 | miring moderat | utamakan median saat meringkas |
| di bawah -1 atau di atas 1 | miring ekstrem | periksa pencilan sebelum meringkas |
nilai_ribu mencatat 5,46 — jauh di wilayah ekstrem karena satu pesanan katering 150 ribu menarik ekor kanan sejauh itu. menunggu_menit bernilai 0,23, hampir simetris. Bentuknya bisa kita lihat langsung pada histogram berikut:
import matplotlib.pyplot as plt
import pandas as pd
transaksi = pd.read_csv("transaksi.csv")
plt.hist(transaksi["nilai_ribu"].dropna(), bins=12, edgecolor="white")
plt.xlabel("Nilai transaksi (ribu rupiah)")
plt.ylabel("Jumlah transaksi")
plt.title("Distribusi nilai transaksi Toko Kopi Kita")
plt.show()Histogram yang tergambar menampilkan satu dinding batang yang tinggi dan rapat di sisi kiri — mayoritas transaksi berkumpul pada kisaran 15 sampai 38 ribu — lalu sebaran tipis menurun, dan satu batang tunggal berdiri terpisah jauh di ujung kanan pada kisaran 150 ribu. Bentuk seperti inilah wujud visual kemiringan +5,46: kerumunan di kiri, ekor panjang ke kanan. Untuk menunggu_menit, histogram akan menampilkan batang yang naik lalu turun secara berimbang di sekitar nilai 5.
Membedah Pola Nilai Kosong #
Pertanyaan terakhir pada kerangka kita menuntut prosedur tiga langkah: hitung nilai kosong per kolom, temukan baris yang memuatnya, lalu duga mekanismenya. Ketiganya dijalankan satu blok kode:
import pandas as pd
transaksi = pd.read_csv("transaksi.csv")
print(transaksi.isna().sum())
print()
print("Baris dengan sel kosong:", transaksi.isna().any(axis=1).sum(), "dari", len(transaksi))
print()
print(transaksi[transaksi.isna().any(axis=1)])Output yang Dihasilkan:
id 0
menu 2
nilai_ribu 3
menunggu_menit 0
dtype: int64
Baris dengan sel kosong: 5 dari 40
id menu nilai_ribu menunggu_menit
20 21 kopi hitam NaN 5
21 22 kopi hitam NaN 6
22 23 kopi hitam NaN 4
38 39 NaN 21.0 5
39 40 NaN 19.0 4Temuan dari pola tersebut:
- Kosong tidak tersebar merata: lima sel kosong berkumpul pada lima baris, dan tiga di antaranya (transaksi 21-23) semuanya bermenu
kopi hitamdengannilai_ribuyang kosong. Pola berkelompok seperti ini biasanya menandakan sumber masalah yang sama — misalnya satu sesi pencatatan yang gagal — bukan kecelakaan acak per sel. - Dampaknya sudah terukur: rata-rata
nilai_ribuuntukkopi hitamkelak hanya dihitung dari enam transaksi, bukan sembilan. Setiap ringkasan per kelompok perlu menyertakancountagar pembaca tahu dasar hitungnya. - Mekanisme kosong menentukan penanganan: kosong yang benar-benar acak (missing completely at random) relatif aman diabaikan, sedangkan kosong yang berkaitan dengan kategori tertentu (missing at random) berpotensi membuat kelompok itu tampak lebih baik atau lebih buruk dari kenyataannya. Diagnosis seluruh strategi penanganan — mengisi, menandai, atau menimbang — dibahas pada chapter Menangani Missing Values .
Rangkuman #
- Analisis univarat memakai kerangka lima pertanyaan yang sama untuk setiap kolom: pusat, sebaran, bentuk, nilai menonjol, dan nilai kosong.
describe()merangkum kolom numerik dandescribe(include="object")merangkum kolom kategorikal;value_counts(dropna=False, normalize=True)memberi profil frekuensi yang jujur terhadap data tak tercatat.- Kemiringan dibaca lewat
skew()dan diperkuat perbandingan mean vs median; sebaran miring ekstrem membuat median dan kuartil lebih mewakili daripada mean. - Pola nilai kosong diperiksa tiga langkah — jumlah per kolom, baris yang terdampak, dugaan mekanisme — karena mekanisme kosong menentukan penanganan yang sah.
Prosedur ini memberi kita profil utuh untuk setiap kolom, tetapi pertanyaan bisnis nyata hampir selalu menyandingkan dua hal: apakah menu menentukan nilai transaksi? Apakah pelanggan yang menunggu lama bertransaksi lebih kecil? Menyandingkan dua variabel adalah pekerjaan chapter berikutnya, Analisis Bivariat .