Urutan alfabetis sering tidak mencerminkan maksud kita: ukuran L tersusun sebelum M, padahal secara logika L lebih besar daripada M. Untuk nilai berjenjang seperti ukuran, tingkat keanggotaan, atau tahap pesanan, pandas menyediakan kategori terurut (ordered categorical): daftar kategori yang urutannya kita definisikan sendiri, lalu dipakai oleh perbandingan, sort_values(), min(), dan max(). Chapter ini membangun urutan ukuran S, M, L, XL dengan CategoricalDtype, menguji perbandingan dan pengurutan, lalu memperbaiki urutan kategori yang sudah jadi.
Kapan Urutan Alfabetis Menyesatkan #
import pandas as pd
ukuran = pd.Series(["S", "M", "L", "XL", "M"])
print((ukuran < "M").tolist())
urut = pd.api.types.CategoricalDtype(
categories=["S", "M", "L", "XL"],
ordered=True,
)
ukuran_cat = ukuran.astype(urut)
print(ukuran_cat.cat.ordered)
print(ukuran_cat.min(), ukuran_cat.max())
print((ukuran_cat < "L").tolist())
print(ukuran_cat.sort_values().tolist())
df = pd.DataFrame({"ukuran": ukuran_cat, "stok": [12, 30, 25, 8, 30]})
print(df.sort_values("ukuran").to_string(index=False))
tanpa_urut = ukuran.astype("category")
try:
print(tanpa_urut.min())
except TypeError as exc:
print(str(exc).splitlines()[0])
susun = tanpa_urut.cat.reorder_categories(["XL", "L", "M", "S"], ordered=True)
print(susun.cat.categories.tolist())
print(susun.min())Output yang Dihasilkan:
[False, False, True, False, False]
True
S XL
[True, True, False, False, True]
['S', 'M', 'M', 'L', 'XL']
ukuran stok
S 12
M 30
M 30
L 25
XL 8
Categorical is not ordered for operation min
['XL', 'L', 'M', 'S']
XLMari kita telaah bagian penting skrip di atas:
- Baris 3-4: perbandingan
ukuran < "M"pada kolomstrbekerja leksikografis per baris, dan hasilnya[False, False, True, False, False]—Ldianggap lebih kecil daripadaMkarena urut huruf. - Baris 6-9:
CategoricalDtypedidefinisikan dengancategories=["S", "M", "L", "XL"]danordered=True; urutan list itulah urutan logisnya. - Baris 10-11:
astype(urut)mengonversi kolom, dan.cat.orderedkini bernilaiTrue. - Baris 12-14:
min()mengembalikanS,max()mengembalikanXL, perbandinganukuran_cat < "L"menghasilkan[True, True, False, False, True]yang sesuai logika ukuran, dansort_values()tersusunS, M, M, L, XL.
Bandingkan kedua hasil perbandingan itu: pola leksikografis menilai L < M bernilai True, sedangkan kategori terurut menilai M < L yang benar. Inilah alasan memakai CategoricalDtype untuk data berjenjang — perbandingan memakai posisi dalam daftar kategori, bukan urutan huruf. Dtype CategoricalDtype juga bisa dipakai ulang antar kolom: definisikan satu kali dalam sebuah variabel, lalu panggil di beberapa astype() agar seluruh kolom berjenjang dalam proyek berbagi urutan yang sama.
Mengurutkan DataFrame Mengikuti Kategori #
Baris 16-17 membawa urutan kategori ke level tabel: df.sort_values("ukuran") menyusun baris mengikuti urutan S, M, L, XL tanpa perlu daftar sort key manual. Baris dengan ukuran sama mempertahankan urutan aslinya, dan kolom stok ikut berpindah bersama barisnya. Urutan kategori juga dihormati oleh groupby() dan value_counts(), sehingga laporan distribusi tersusun logis tanpa pengurutan tambahan.
Urutan kategori ini bukan fitur yang berdiri sendiri; section Transformasi Data sebelumnya sebenarnya sudah menemukannya tanpa diberi nama. pd.cut() menghasilkan kolom kategori terurut dari rentang angka — label seperti Murah, Sedang, Mahal — dengan urutan yang ditentukan batas bin. Perbedaannya ada pada sumber urutan: di chapter itu urutan datang otomatis dari angka, sementara di sini kita mendefinisikannya sendiri untuk label yang tidak punya angka di belakangnya.
Kategori Tanpa Urutan dan Memperbaikinya #
Baris 19-20 menguji kolom tanpa_urut hasil astype("category") biasa. Pemanggilan min() ditolak dengan TypeError: Categorical is not ordered for operation min — tanpa urutan yang didefinisikan, nilai minimum tidak bermakna. Baris 25-27 memperbaikinya dengan reorder_categories(["XL", "L", "M", "S"], ordered=True): urutan kategori dibalik menjadi XL terkecil, dan min() kini mengembalikan XL. Method ini menuntut daftar kategori yang isinya sama persis dengan yang lama; untuk menambah atau mengurangi kategori sekaligus mengubah urutan, gunakan set_categories() dari chapter sebelumnya.
Status ordered juga menentukan siapa yang boleh membandingkan. Perbandingan >= pada kategori terurut menghasilkan mask boolean yang siap dipakai untuk filter — mengambil baris ukuran L ke atas cukup dengan df[df["ukuran"] >= "L"]. Pada kategori tanpa urutan, perbandingan semacam itu ditolak dengan TypeError yang sama seperti min() di atas; pandas menolak menebak urutan yang tidak kita nyatakan.
Dokumentasi resmi yang relevan: pandas.CategoricalDtype , pandas.Series.cat.reorder_categories , dan User Guide: Categorical data .
Dengan urutan yang bermakna, distribusi kategori bisa dibaca langsung dari rendah ke tinggi. Chapter berikutnya menghitung distribusi itu secara konkret dengan value_counts() dan groupby().