Encoding Kategori

OneHotEncoder dan OrdinalEncoder untuk fitur non-numerik.

Daftar isi

Objek pemodel (estimator) pada scikit-learn mengonsumsi bilangan, sedangkan data tabular nyata memuat kolom berisi kategori seperti warna sampul berkas, tingkat kesulitan soal, atau grup latihan. Topik ini membahas dua encoder untuk mengubah kolom kategori menjadi angka, yaitu OneHotEncoder untuk kategori nominal dan OrdinalEncoder untuk kategori berurutan. Hasil akhirnya berupa kemampuan menentukan encoder yang tepat beserta penanganan kategori yang belum pernah terlihat.

Kategori nominal dan ordinal#

Data kategorikal memuat nilai dari himpunan pilihan terbatas, dan pemilihannya terbagi menjadi dua jenis. Kategori nominal tidak membawa urutan apa pun, seperti warna sampul berkas yang nilainya merah, hijau, atau biru, karena tidak ada alasan menganggap merah lebih kecil dari hijau. Kategori ordinal membawa urutan yang bermakna, seperti tingkat kesulitan soal yang berurutan dari rendah, menengah, hingga tinggi.

Pembedaan ini menentukan encoder yang digunakan. Kategori nominal ditransformasikan menjadi kolom-kolom biner sehingga tidak ada urutan yang tersirat pada angkanya. Kategori ordinal boleh dipetakan ke bilangan berurutan justru karena urutannya bermakna, dan urutan itu harus dinyatakan secara eksplisit. Kesalahan memilih jenis encoder berarti menyuntikkan asumsi palsu ke dalam data, dan akibatnya dibahas pada bagian OrdinalEncoder.

Kedua encoder bekerja dengan kontrak transformer yang sama, yaitu mempelajari daftar kategori dari data latih melalui fit, kemudian memetakan nilai baru melalui transform. Daftar kategori yang terpelajari dapat diperiksa dan nama fitur hasilnya dapat ditampilkan, sehingga hasil transformasi tetap dapat dibaca manusia.

OneHotEncoder untuk kategori nominal#

OneHotEncoder mengubah satu kolom kategori menjadi satu kolom biner untuk setiap kategori yang teramati. Teknik ini disebut one-hot encoding, yaitu pemberian satu kolom aktif bernilai 1 untuk kategori yang dimiliki sampel. Nilai 0 pada kolom lainnya menandai sampel yang tidak memiliki kategori itu, sehingga tidak ada hubungan lebih besar atau lebih kecil antarkolom. Parameter sparse_output=False membuat keluarannya berupa array NumPy padat yang mudah diperiksa, dan parameter handle_unknown="ignore" membuat kategori baru saat transform tidak memicu error.

Berkas berikut memuat program utuh yang mengubah data nilai latihan dengan kolom warna sebagai kategori nominal dan tingkat sebagai kategori ordinal.

python dua-encoder.py
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder

df = pd.DataFrame({
    "warna": ["merah", "hijau", "biru", "merah", "hijau"],
    "tingkat": ["menengah", "rendah", "tinggi", "rendah", "tinggi"],
    "skor": [72, 55, 91, 60, 88],
})
print("Data asli:")
print(df)

# warna adalah kategori nominal: tanpa urutan yang bermakna
ohe = OneHotEncoder(sparse_output=False, handle_unknown="ignore").fit(df[["warna"]])
print("Hasil OneHotEncoder pada kolom warna:")
print(ohe.transform(df[["warna"]]))
print("Nama fitur OneHotEncoder:")
print(ohe.get_feature_names_out())

# tingkat adalah kategori ordinal: urutannya dinyatakan secara eksplisit
urutan = [["rendah", "menengah", "tinggi"]]
oe = OrdinalEncoder(categories=urutan).fit(df[["tingkat"]])
print("Hasil OrdinalEncoder pada kolom tingkat:")
print(oe.transform(df[["tingkat"]]))
print("Nama fitur OrdinalEncoder:")
print(oe.get_feature_names_out())
text Keluaran
Data asli:
   warna   tingkat  skor
0  merah  menengah    72
1  hijau    rendah    55
2   biru    tinggi    91
3  merah    rendah    60
4  hijau    tinggi    88
Hasil OneHotEncoder pada kolom warna:
[[0. 0. 1.]
 [0. 1. 0.]
 [1. 0. 0.]
 [0. 0. 1.]
 [0. 1. 0.]]
Nama fitur OneHotEncoder:
['warna_biru' 'warna_hijau' 'warna_merah']
Hasil OrdinalEncoder pada kolom tingkat:
[[1.]
 [0.]
 [2.]
 [0.]
 [2.]]
Nama fitur OrdinalEncoder:
['tingkat']

Kolom warna menjadi tiga kolom biner sesuai banyaknya kategori, dengan urutan kolom mengikuti susunan alfabetis kategori yang teramati, yaitu biru, hijau, kemudian merah. Baris pertama yang berwarna merah menjadi 0, 0, 1, dan pola itu dapat dibaca kembali melalui get_feature_names_out(). Metode tersebut penting karena hasil transformasi hanya berupa angka tanpa label, sedangkan nama fitur menjaga hasilnya tetap dapat diinterpretasikan.

OrdinalEncoder dan urutan yang eksplisit#

OrdinalEncoder memetakan setiap kategori ke satu bilangan, sehingga satu kolom kategori tetap menjadi satu kolom angka. Pemetaan itu hanya bermakna untuk kategori ordinal, dan urutannya dinyatakan melalui parameter categories sebagaimana terlihat pada kolom tingkat, yaitu rendah menjadi 0, menengah menjadi 1, dan tinggi menjadi 2. Tanpa parameter tersebut, urutan bawaan OrdinalEncoder mengikuti susunan alfabetis, sehingga menengah akan bernilai lebih kecil daripada rendah dan informasi urutannya rusak.

Jumlah kolom hasil kedua encoder juga berbeda jauh. OneHotEncoder memperbanyak kolom sebesar banyaknya kategori, sedangkan OrdinalEncoder menjaga jumlah kolom tetap satu. Data dengan ratusan kategori membuat one-hot encoding mahal, dan keputusan pemilihan kolom pada situasi demikian diulas pada topik Pemilihan Kolom dengan ColumnTransformer.

Kategori yang belum pernah terlihat#

Data baru sering memuat kategori yang tidak ada pada data latih, misalnya sampul berkas berwarna kuning yang muncul setelah model dilatih. Perilaku encoder terhadap kategori semacam itu perlu ditetapkan secara sadar, karena kesalahan pada tahap ini baru terasa saat sistem berjalan. Pengaturannya berupa satu parameter yang dinyatakan saat objek encoder dibuat.

python Contoh: kategori yang belum pernah terlihat
import pandas as pd
from sklearn.preprocessing import OneHotEncoder

df = pd.DataFrame({"warna": ["merah", "hijau", "biru", "merah", "hijau"]})
ohe = OneHotEncoder(sparse_output=False, handle_unknown="ignore").fit(df[["warna"]])
df_baru = pd.DataFrame({"warna": ["kuning"]})
print("Hasil transform kategori baru:")
print(ohe.transform(df_baru[["warna"]]))
text Keluaran
Hasil transform kategori baru:
[[0. 0. 0.]]

Dengan handle_unknown="ignore", kategori kuning ditransformasi menjadi seluruh nol, yang berarti tidak ada kategori pada data latih yang cocok dengannya. Tanpa pengaturan tersebut, encoder memicu error karena kategori yang tidak dikenal tidak dapat dipetakan. Menonaktifkan error bukan berarti masalah selesai, karena baris dengan seluruh nol tetap perlu dipahami sebagai kategori yang baru.

Kesalahan umum#

Kesalahan pertama adalah memberikan kolom satu dimensi kepada encoder. Panduan bentuk scikit-learn menuntut matriks dua dimensi, sehingga df["warna"] memicu pesan error tentang array 1D, sedangkan df[["warna"]] dengan dua kurung siku menghasilkan DataFrame satu kolom yang diterima.

Kesalahan kedua adalah melupakan parameter sparse_output=False. Bawaan OneHotEncoder menghasilkan matriks sparse dari SciPy, yaitu struktur data yang hanya menyimpan nilai bukan nol, sehingga hasilnya tampak sebagai daftar posisi ketika dicetak. Matriks sparse efisien untuk ratusan kategori, tetapi membingungkan apabila keluaran padat memang diharapkan.

Kesalahan ketiga adalah mengurutkan kategori ordinal berdasarkan alfabet. Urutan alfabetis hanya kebetulan cocok pada sebagian kecil kasus, sehingga urutan yang bermakna selalu dinyatakan melalui categories.

Ringkasan#

  • OneHotEncoder menghasilkan satu kolom biner per kategori dan cocok untuk kategori nominal, sedangkan OrdinalEncoder memetakan kategori berurutan ke bilangan sesuai urutan yang dinyatakan.
  • sparse_output=False mengembalikan array padat, dan handle_unknown="ignore" membuat kategori baru tidak memicu error saat transform.
  • Urutan bawaan OrdinalEncoder adalah alfabetis, sehingga urutan yang bermakna dinyatakan eksplisit melalui categories.
  • get_feature_names_out() menghubungkan kolom hasil transformasi dengan nama yang dapat dibaca.

Referensi#