Kolom teks yang isinya berulang, seperti tipe pelanggan, kanal pembelian, atau status pesanan, sebenarnya menyimpan label dari daftar nilai yang terbatas. Dengan dtype str, setiap baris menyimpan teks lengkap, sehingga label yang tidak seragam mudah lolos dan penyimpanannya boros memori. Tipe data category menyimpan daftar label terkelola (categories) dan hanya mencatat posisi label pada setiap baris. Pada Chapter ini kita mengubah kolom teks menjadi category, mengganti label lama ke label baru, dan menggabungkan beberapa label sekaligus.

Mengubah Kolom Teks Menjadi category #

Skrip berikut memakai tabel pelanggan kecil. Kolom tipe berisi label yang rapi dan hanya punya dua nilai unik, sedangkan kolom kanal akan disatukan sebagian labelnya. Jalankan skripnya lalu ikuti uraian di bawah.

python
import pandas as pd

pelanggan = pd.DataFrame({
    "id_pelanggan": ["PLG-01", "PLG-02", "PLG-03", "PLG-04"],
    "nama": ["Budi", "Siti", "Dewi", "Andi"],
    "tipe": ["reguler", "member", "reguler", "member"],
    "kanal": ["Toko", "Online", "Marketplace", "Toko"],
})

tipe = pelanggan["tipe"].astype("category")
print(tipe)
print()
print("Daftar kategori:", tipe.cat.categories.tolist())
print("dtype:", tipe.dtype)
print()

tipe_baru = tipe.cat.rename_categories({"reguler": "Reguler", "member": "Member"})
print(tipe_baru)
print()

kanal_baru = pelanggan["kanal"].map(
    {"Toko": "Offline", "Online": "Website", "Marketplace": "Website"}
)
print(kanal_baru)
print()
print("dtype hasil map():", kanal_baru.dtype)
print()

tes = pd.Series(["reguler", "member", "vip"])
print(tes.map({"reguler": "Reguler", "member": "Member"}))
print()

kota = pd.Series(["Jakarta", "Bandung", "Surabaya"] * 10_000)
kota_kategori = kota.astype("category")
print("Memori kolom teks    :", kota.memory_usage(deep=True), "byte")
print("Memori kolom kategori:", kota_kategori.memory_usage(deep=True), "byte")

Output yang Dihasilkan:

text
0    reguler
1     member
2    reguler
3     member
Name: tipe, dtype: category
Categories (2, str): ['member', 'reguler']

Daftar kategori: ['member', 'reguler']
dtype: category

0    Reguler
1     Member
2    Reguler
3     Member
Name: tipe, dtype: category
Categories (2, str): ['Member', 'Reguler']

0    Offline
1    Website
2    Website
3    Offline
Name: kanal, dtype: str

dtype hasil map(): str

0    Reguler
1     Member
2        NaN
dtype: str

Memori kolom teks    : 460132 byte
Memori kolom kategori: 30179 byte

Mari kita telaah apa yang terjadi pada kode di atas:

  1. Baris 10 (tipe = pelanggan["tipe"].astype("category")): method Series.astype() mengubah dtype kolom menjadi category. Pandas mendaftarkan label unik sebagai kategori dan mengurutkannya secara alfabetis, terlihat dari Categories (2, str): ['member', 'reguler'].
  2. Baris 13-14 (tipe.cat.categories): accessor .cat mengekspos properti khusus dtype category. Properti categories berisi daftar label terkelola, dan cetakan dtype: category mengonfirmasi perubahan tipe.
  3. Baris 17 (tipe.cat.rename_categories(...)): method rename_categories() mengganti nama label satu-satu: reguler menjadi Reguler dan member menjadi Member. Jumlah kategori tetap dua, dtype tetap category, dan isi setiap baris ikut berganti.
  4. Baris 21-23 (pelanggan["kanal"].map(...)): map() dengan dictionary mengganti nilai berdasarkan kunci. Di sinilah penggabungan label terjadi: Online dan Marketplace sama-sama dipetakan ke Website. Hasil map() kembali bertipe str, bukan category, seperti ditunjukkan baris 26.
  5. Baris 29-30 (tes.map({...})): nilai vip tidak terdaftar pada dictionary, sehingga map() menggantinya dengan NaN tanpa menimbulkan error. Perilaku ini penting untuk dikenali sebelum memproses data lebih lanjut.

Manfaat dtype category #

Manfaat pertama adalah efisiensi memori. Baris 33-36 skrip di atas membangun Series dengan 30.000 baris yang hanya berisi tiga label kota, lalu membandingkan konsumsi memorinya: 460.132 byte sebagai str dan 30.179 byte sebagai category, sekitar 15 kali lebih hemat. Kolom category menyimpan label sekali saja, lalu mencatat kode posisi untuk setiap baris, sehingga kehematannya makin besar pada data yang makin panjang. Pada tabel empat baris seperti contoh di atas, kehematan ini belum terasa dan itu wajar.

Manfaat kedua adalah konsistensi label. Setelah sebuah kolom menjadi category, pandas menolak penulisan nilai yang belum terdaftar pada daftar kategori dan menimbulkan TypeError: Cannot setitem on a Categorical with a new category (...). Mekanisme ini mencegah label salah ketik seperti Reguler (dengan spasi) masuk ke data secara diam-diam. Panduan lengkap tentang accessor .cat tersedia di user guide Categorical data .

Label yang sudah rapi siap dipakai untuk peringkasan. Namun kategori tidak selalu sudah tersedia di data: nilai numerik kontinu seperti nominal transaksi juga sering perlu dikelaskan menjadi Murah, Sedang, atau Mahal. Chapter berikutnya menunjukkan cara membagi data numerik ke dalam bin dengan pd.cut().