Data kategorikal adalah jenis data yang paling sering kita temui: metode pembayaran, kanal pesanan, jenis minuman, tingkat kepuasan pelanggan. Membuat grafiknya tampak mudah — tinggal hitung lalu gambar — tetapi keputusan-keputusan kecilnya menentukan apakah grafik itu membantu atau justru menyesatkan pembaca. Pada chapter ini kita hitung jumlah dan proporsi kategori, atur urutannya dengan sadar, tentukan kapan pie chart masih layak dipakai, lalu susun komposisi beberapa kategori dalam satu batang lewat stacked bar.

Menghitung Kategori: Jumlah dan Proporsi #

Seluruh grafik kategorikal berdiri di atas dua hitungan: count (berapa banyak tiap kategori muncul) dan proporsi (berapa persen bagiannya dari total). pandas menyediakan keduanya sekaligus lewat value_counts(). Kita pakai 100 transaksi Toko Kopi Kita:

python
import pandas as pd

transaksi = (["QRIS"] * 46 + ["tunai"] * 28 + ["kartu debit"] * 12
             + ["e-wallet"] * 9 + ["voucher"] * 5)
metode = pd.Series(transaksi, name="metode pembayaran")

jumlah = metode.value_counts()
porsi = (metode.value_counts(normalize=True) * 100).round(1)

print("Jumlah transaksi per metode:")
print(jumlah.to_string())
print()
print("Porsi transaksi per metode (%):")
print(porsi.to_string())

Output yang Dihasilkan:

text
Jumlah transaksi per metode:
metode pembayaran
QRIS           46
tunai          28
kartu debit    12
e-wallet        9
voucher         5

Porsi transaksi per metode (%):
metode pembayaran
QRIS           46.0
tunai          28.0
kartu debit    12.0
e-wallet        9.0
voucher         5.0

Mari kita telaah baris-barisnya:

  1. Baris 3-5: 100 transaksi disusun lewat pengulangan list — 46 transaksi QRIS, 28 tunai, dan seterusnya — lalu dibungkus menjadi satu Series; dalam data nyata, kolom seperti ini datang dari berkas transaksi mentah.
  2. Baris 7 (value_counts()): menghitung frekuensi tiap kategori sekaligus mengurutkannya dari yang terbanyak.
  3. Baris 8 (value_counts(normalize=True)): menghitung proporsi alih-alih jumlah; dikali 100 dan dibulatkan satu desimal agar terbaca sebagai persen. Karena totalnya genap 100, angka porsi dan jumlah kebetulan sama — pada data lain keduanya tentu berbeda.

Urutan Kategori: Frekuensi atau Urutan Alami #

Grafik jumlah yang baik mengurutkan kategori secara sadar. Untuk kategori tanpa urutan bawaan seperti metode pembayaran, urutan terbaik adalah menurun menurut frekuensi. seaborn menyediakan countplot() yang menghitung sekaligus menggambar, dan argumen order= mengatur urutannya:

python
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

transaksi = (["QRIS"] * 46 + ["tunai"] * 28 + ["kartu debit"] * 12
             + ["e-wallet"] * 9 + ["voucher"] * 5)
metode = pd.Series(transaksi, name="metode")

sns.countplot(x=metode, order=metode.value_counts().index, color="tab:blue")
plt.title("Metode Pembayaran 100 Transaksi")
plt.xlabel("Metode pembayaran")
plt.ylabel("Jumlah transaksi")
plt.show()

Gambar yang muncul memuat lima batang tegak yang menurun dari kiri: QRIS tertinggi dengan 46, diikuti tunai (28), kartu debit (12), e-wallet (9), dan voucher terpendek dengan 5. Urutan batang persis mengikuti metode.value_counts().index — daftar kategori terurut frekuensi — sehingga pembaca menangkap peringkatnya seketika tanpa perlu membandingkan tinggi batang satu per satu.

Kategori lain justru memiliki urutan alami yang tidak boleh dirusak. Tingkat kepuasan “kecewa”, “cukup”, “puas”, “sangat puas” membentuk tangga yang bermakna; mengurutkannya menurut frekuensi membuat grafik sulit dibaca dan ceritanya terpotong. pandas menyediakan pd.Categorical untuk mengunci urutan seperti itu:

python
import pandas as pd

rating = pd.Series(["puas", "cukup", "sangat puas", "puas", "kecewa",
                    "puas", "sangat puas", "cukup", "puas", "kecewa"],
                   name="rating")

print("value_counts() apa adanya (urut jumlah):")
print(rating.value_counts().to_string())
print()

tingkat = ["kecewa", "cukup", "puas", "sangat puas"]
rating_rapi = pd.Categorical(rating, categories=tingkat, ordered=True)

print("value_counts(sort=False) pada kategori berurut:")
print(pd.Series(rating_rapi).value_counts(sort=False).to_string())

Output yang Dihasilkan:

text
value_counts() apa adanya (urut jumlah):
rating
puas           4
cukup          2
sangat puas    2
kecewa         2

value_counts(sort=False) pada kategori berurut:
kecewa         2
cukup          2
puas           4
sangat puas    2

Tabel pertama mengurutkan berdasarkan jumlah: “puas” tampil paling atas karena paling banyak, dan tiga level sisanya berhamburan tanpa makna. Tabel kedua tampil rapi mengikuti tangga kepuasan dari “kecewa” sampai “sangat puas” — urutan yang membuat grafiknya bisa dibaca sebagai tangga: banyaknya pelanggan naik dari kecewa (2) menuju puas (4) lalu turun lagi di sangat puas (2). Dua baris kuncinya: pd.Categorical(..., categories=tingkat, ordered=True) mendaftarkan urutan resmi kategori, dan sort=False mematikan pengurutan menurut jumlah sehingga urutan kategorilah yang dipakai.

Pie Chart: Kapan Masih Boleh #

Pie chart sering dipakai lebih luas daripada seharusnya. Kekuatannya hanya satu: menunjukkan porsi beberapa bagian terhadap keseluruhan, dan itu pun hanya efektif bila kategorinya sedikit — dua sampai empat — dengan perbedaan porsi yang mencolok. Di luar itu, persepsi manusia terhadap sudut dan area tergolong lemah: membandingkan juring 12% dengan juring 9% pada dasarnya menebak.

Kita pakai pie chart pada kasus yang memenuhi syaratnya — pembagian tiga kanal pesanan:

python
import matplotlib.pyplot as plt

kanal = ["di tempat", "pesan antar", "ambil sendiri"]
porsi = [45, 35, 20]

fig, ax = plt.subplots(figsize=(5.5, 4))
ax.pie(porsi, labels=kanal, autopct="%1.0f%%", startangle=90,
       colors=["tab:blue", "tab:orange", "tab:green"])
ax.set_title("Porsi Transaksi per Kanal Pesanan")
plt.show()

Gambar yang dihasilkan berupa lingkaran terbagi tiga juring: juring biru “di tempat” hampir separuh lingkaran dengan 45%, juring oranye “pesan antar” 35%, dan juring hijau “ambil sendiri” 20%. Ketiganya berbeda cukup jauh sehingga tidak ada kebutuhan membandingkan juring yang nyaris sama besar; label kategori menempel di tiap juring dan autopct="%1.0f%%" menuliskan persentase di dalamnya sehingga tidak ada informasi yang bergantung pada sudut semata.

Stacked Bar untuk Komposisi #

Pertanyaan komposisi sering berbunyi “bagaimana susunan bagiannya, dan bagaimana susunan itu berubah?”. Stacked bar menjawabnya dengan menumpuk kategori dalam satu batang: panjang segmen adalah nilainya, panjang total adalah jumlahnya. Kita lihat komposisi penjualan minuman kopi dan non-kopi sepekan penuh:

python
import matplotlib.pyplot as plt

hari = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"]
kopi = [55, 58, 60, 62, 65, 70, 72]
non_kopi = [25, 24, 22, 23, 27, 40, 45]

fig, ax = plt.subplots(figsize=(7, 3.5))
ax.bar(hari, kopi, color="tab:brown", label="kopi")
ax.bar(hari, non_kopi, bottom=kopi, color="tab:green", label="non-kopi")
ax.bar_label(ax.containers[0], label_type="center", color="white")
ax.bar_label(ax.containers[1], label_type="center", color="white")
ax.set_title("Komposisi Penjualan per Hari")
ax.set_xlabel("Hari")
ax.set_ylabel("Gelas terjual")
ax.legend(title="Jenis minuman")
plt.show()

Gambar yang muncul memuat tujuh batang dua lapis: segmen cokelat (minuman kopi) di bawah dengan nilai 55 di Senin sampai 72 di Minggu, dan segmen hijau (non-kopi) menumpuk di atasnya dari 25 sampai 45. Panjang total batang memperlihatkan penjualan yang membesar menuju akhir pekan — dari 80 gelas pada Senin sampai 117 pada Minggu — sementara segmen hijau yang menebal pada Sabtu dan Minggu memperlihatkan pergeseran komposisi: di hari kerja non-kopi hanya sekitar sepertiga penjualan, tetapi pada akhir pekan porsinya mendekati empat puluh persen.

Dua mekanisme penting di baliknya: bottom=kopi memberi tahu bar() bahwa segmen kedua mulai digambar dari puncak segmen pertama (inilah yang membuat batang bertumpuk), dan label_type="center" menempatkan nilai di tengah segmen sehingga tiap lapisan terbaca nilainya tanpa legend warna perlu ditebak.

Rangkuman #

  • Grafik kategorikal berdiri di atas dua hitungan: value_counts() untuk jumlah dan value_counts(normalize=True) untuk proporsi.
  • Kategori tanpa urutan bawaan diurutkan menurun menurut frekuensi (argumen order= pada countplot); kategori berurutan seperti tingkat kepuasan dikunci urutannya dengan pd.Categorical(..., ordered=True) plus sort=False.
  • Pie chart hanya layak untuk dua-empat kategori dengan porsi yang mencolok bedanya; kategori kecil digabung menjadi “lainnya” lebih dulu.
  • Stacked bar menunjukkan komposisi sekaligus totalnya; bottom= menumpuk segmen dan label_type="center" menuliskan nilai di tengah tiap lapisan.

Komposisi kopi lawan non-kopi memperlihatkan dua variabel sekaligus dalam satu batang. Namun data nyata kerap membawa tiga, empat, atau lebih variabel yang perlu tampil bersama. Chapter berikutnya, Visualisasi Multivariabel, memperluas kotak peralatan kita dengan warna, ukuran, heatmap, dan panel kecil.

Referensi #

  1. Seaborn — Tutorial — panduan resmi seaborn, termasuk countplot dan plot kategorikal lainnya.
  2. Pandas — Intro Tutorials — tutorial resmi pandas untuk value_counts() dan tipe kategorikal.