BelajarKoding Logobelajarkoding

Platform belajar web development Indonesia. Artikel, cheat sheets, roadmap, dan code challenges untuk developer Indonesia.

Navigasi

  • Artikel
  • Cheat Sheets
  • Roadmap
  • Challenges
  • Pricing
  • Search

Produk Lain

  • JagoHermes
  • KelasClaude
  • KilatKoding
  • BelajarVibeCoding
  • JualanKoding

Support

  • Privacy Policy
  • Terms of Service
  • Email

© 2026 BelajarKoding. All rights reserved.

Galih PratamaBagian dari ekosistem Galih Pratama
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade

Daftar Isi

Mengapa feature engineeringFondasi yang sering dilupakanEncoding kategoriTarget encodingMenangani nilai kosongFitur waktuFitur numerik turunanFitur teksInteraksi dan polinomialBinning dan kategorisasiSeleksi fiturData leakage dan urutan yang benarSpline dan fitur basisFitur geospasialChecklist feature engineeringGlosarium
Machine LearningData ScienceFeature EngineeringPython

Feature Engineering Cheat Sheet

Referensi cepat feature engineering untuk machine learning tabular. Scaling, encoding kategori, imputasi, fitur waktu, interaksi, seleksi fitur, dan pencegahan data leakage.

Python12 min read2.204 kata
Silakan login atau daftar untuk membaca cheat sheet ini.

#Mengapa feature engineering

Kualitas fitur sering menentukan batas atas performa model. Model yang sama akan memberi hasil jauh beda pada dua tabel dengan informasi berbeda. Feature engineering berarti mengubah data mentah menjadi representasi yang bisa dimanfaatkan algoritma pembelajaran.

Sebagian besar teknik di cheat sheet ini pakai scikit-learn dan pandas. Jangan menganggap semua teknik harus diterapkan. Setiap transformasi harus diuji dengan validasi. Fitur baru yang tidak menaikkan skor hanya menambah kerumitan.

#Fondasi yang sering dilupakan

Scaling bukan aksesori. Model linear, SVM, KNN, PCA, dan banyak model neural mengasumsikan fitur numerik berada pada skala yang sebanding. Model pohon tidak peduli, tetapi begitu kamu mencampur model, konsistensi preprocessing tetap penting.

python
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
 
X = pd.DataFrame(
    {
        "umur": [21, 35, 29, 42, 31],
        "pendapatan": [4_000_000, 8_000_000, 6_500_000, 12_000_000, 7_000_000],
        "transaksi": [2, 5, 3, 9, 4],
    }
)
 
standard = StandardScaler().fit_transform(X)
minmax = MinMaxScaler().fit_transform(X)
robust = RobustScaler().fit_transform(X)

Pilih scaler berdasarkan distribusi dan outlier.

ScalerRumus intiKapan dipakai
StandardScaler(x - mean) / stdFitur mendekati normal, model linear dan SVM.
MinMaxScaler(x - min) / (max - min)Rentang tetap, misalnya fitur citra atau input jaringan saraf.
RobustScaler(x - median) / IQRAda outlier ekstrem.
MaxAbsScalerx / max(abs(x))Data sparse, nilai sudah berpusat di nol.

Perhatikan bahwa MinMaxScaler mempelajari min dan max dari train. Nilai baru yang lebih ekstrem akan dipetakan ke luar rentang. Ini wajar, tetapi pastikan pipeline kamu tidak diasumsikan selalu menghasilkan nilai pada rentang tertentu.

#Encoding kategori

Data kategori tidak bisa langsung dimasukkan ke kebanyakan model sebagai teks. Cara encoding bergantung pada tipe kategori dan estimator.

python
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder
 
X = pd.DataFrame(
    {
        "warna": ["merah", "biru", "hijau", "merah"],
        "ukuran": ["S", "M", "L", "S"],
        "tier": ["reguler", "pro", "basic", "pro"],
    }
)
 
one_hot = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
X_encoded = one_hot.fit_transform(X[["warna"]])
print(one_hot.get_feature_names_out(["warna"]))

OrdinalEncoder memetakan kategori ke angka berurutan. Ia cocok hanya bila urutan punya arti nyata, seperti ukuran baju. Jangan pakai untuk kategori nominal seperti warna. Angka yang muncul dari ordinal encoding akan dianggap bermakna oleh model linear.

python
ukuran_order = ["S", "M", "L"]
ordinal = OrdinalEncoder(categories=[ukuran_order])
X_ukuran = ordinal.fit_transform(X[["ukuran"]])
print(X_ukuran.ravel())

OneHotEncoder menambah banyak kolom saat kategori punya kardinalitas tinggi. Gunakan min_frequency untuk mengelompokkan kategori langka, atau max_categories untuk membatasi kolom output. Kategori yang terlalu jarang sering lebih baik dijadikan kategori lainnya.

#Target encoding

Target encoding mengganti kategori dengan statistik target. Berguna untuk kategori kardinalitas tinggi seperti kode produk atau kota. Resiko leakage sangat tinggi bila diterapkan tanpa cross-fitting. Di scikit-learn, TargetEncoder menangani cross-fitting secara internal.

python
import pandas as pd
from sklearn.preprocessing import TargetEncoder
 
X = pd.DataFrame({"produk": ["A", "B", "A", "C", "B", "A", "C", "C"]})
y = [1, 0, 1, 0, 1, 0, 1, 0]
 
encoder = TargetEncoder(smooth="auto")
X_encoded = encoder.fit_transform(X, y)
print(X_encoded)

Untuk target multiclass, output TargetEncoder menjadi n_features * n_classes kolom karena setiap kelas punya probabilitas kondisional sendiri. Perhatikan bahwa fit(X, y).transform(X) tidak selalu sama dengan fit_transform(X, y). Cross-fitting di fit_transform berbeda dengan transformasi langsung pada data yang sama.

#Menangani nilai kosong

Nilai kosong muncul karena sensor gagal, form tidak lengkap, atau data yang digabung tidak selaras. Jangan buru-buru menghapus baris. Hapus dulu hanya kolom yang hampir seluruhnya kosong, lalu imputasi sisanya.

python
import numpy as np
from sklearn.impute import SimpleImputer, KNNImputer
 
X_missing = np.array(
    [
        [1.0, 2.0, 100.0],
        [np.nan, 3.0, 120.0],
        [7.0, np.nan, 90.0],
        [4.0, 5.0, np.nan],
    ]
)
 
mean_imputer = SimpleImputer(strategy="mean")
X_mean = mean_imputer.fit_transform(X_missing)
 
knn_imputer = KNNImputer(n_neighbors=2)
X_knn = knn_imputer.fit_transform(X_missing)

SimpleImputer menawarkan mean, median, most_frequent, dan constant. Untuk data miring, median lebih tahan outlier. most_frequent bekerja untuk string dan kategori.

KNNImputer mengisi nilai dengan rata-rata tetangga terdekat. Ia bergantung pada skala fitur, jadi scaling harus diterapkan lebih dulu di dalam pipeline. KNNImputer juga lebih lambat pada data besar.

IterativeImputer memperkirakan setiap fitur dari fitur lain memakai model regresi, mirip pola imputasi MICE. Masih berlabel experimental di scikit-learn dan perlu impor enable_iterative_imputer.

python
from sklearn.experimental import enable_iterative_imputer  # noqa
from sklearn.impute import IterativeImputer
 
iterative = IterativeImputer(max_iter=10, random_state=42)
X_iterative = iterative.fit_transform(X_missing)

Terkadang keberadaan nilai kosong itu sendiri adalah sinyal. MissingIndicator menambah kolom biner yang menandai apakah suatu nilai hilang.

python
from sklearn.impute import MissingIndicator
 
indicator = MissingIndicator(features="all")
X_flags = indicator.fit_transform(X_missing)

#Fitur waktu

Waktu adalah sumber fitur yang sering disia-siakan. Timestamp mentah biasanya tidak berguna sebagai angka karena epoch time tidak linear terhadap pola harian. Pecah menjadi komponen yang bisa dibaca model.

python
import pandas as pd
 
df = pd.DataFrame(
    {
        "tanggal": pd.to_datetime(
            ["2024-01-01 09:15:00", "2024-06-15 22:40:00", "2024-12-31 08:05:00"]
        )
    }
)
 
df["tahun"] = df["tanggal"].dt.year
df["bulan"] = df["tanggal"].dt.month
df["hari"] = df["tanggal"].dt.day
df["hari_dalam_minggu"] = df["tanggal"].dt.dayofweek
df["jam"] = df["tanggal"].dt.hour
df["menit"] = df["tanggal"].dt.minute
df["hari_dalam_tahun"] = df["tanggal"].dt.dayofyear
df["is_weekend"] = df["hari_dalam_minggu"].isin([5, 6]).astype(int)

Jam adalah variabel siklus. Jam 23 dan jam 0 saling berdekatan secara fisik tetapi berjauhan jika ditulis sebagai angka. Transformasi sin dan cos mengembalikan kedekatan itu.

python
import numpy as np
 
df["jam_sin"] = np.sin(2 * np.pi * df["jam"] / 24)
df["jam_cos"] = np.cos(2 * np.pi * df["jam"] / 24)
 
df["bulan_sin"] = np.sin(2 * np.pi * df["bulan"] / 12)
df["bulan_cos"] = np.cos(2 * np.pi * df["bulan"] / 12)

Satu angka waktu tunggal bisa dipecah menjadi banyak fitur. Ini bukan berarti kamu harus membuat semuanya. Pilih yang relevan dengan masalah. Untuk data penjualan ritel, hari dalam minggu dan jam puncak biasanya jauh lebih informatif daripada menit.

#Fitur numerik turunan

Banyak model linier tidak menemukan interaksi sendiri. Kamu bisa membuat fitur baru dari operasi aritmetika, agregasi, dan rasio.

python
import pandas as pd
 
df = pd.DataFrame(
    {
        "harga": [100_000, 250_000, 180_000],
        "jumlah": [2, 1, 3],
        "diskon": [10_000, 0, 15_000],
    }
)
 
df["total"] = df["harga"] * df["jumlah"]
df["harga_per_unit"] = df["harga"] / df["jumlah"]
df["diskon_rasio"] = df["diskon"] / df["harga"]
df["rata_rata_pesanan"] = df.groupby("kategori")["total"].transform("mean")

groupby(...).transform() menghasilkan agregasi dengan panjang yang sama dengan data asal, sehingga aman untuk feature engineering baris per baris. Aggregasi ini harus dihitung dari data training saat model di-deploy, bukan dari seluruh dataset termasuk test.

Untuk distribusi miring, transformasi log mengecilkan rentang dan membantu model linear serta banyak estimator lain.

python
import numpy as np
 
df["pendapatan_log"] = np.log1p(df["pendapatan"])

log1p sama dengan log(1 + x) dan aman untuk nilai nol. Transformasi Box-Cox (PowerTransformer(method="box-cox")) dan Yeo-Johnson (PowerTransformer(method="yeo-johnson")) juga tersedia di scikit-learn. Yeo-Johnson bisa menangani nilai negatif, Box-Cox hanya untuk positif.

#Fitur teks

Untuk kasus sederhana, hitung panjang teks, jumlah kata, dan indikator keberadaan pola. Untuk model, ubah teks menjadi matriks numerik dengan CountVectorizer atau TfidfVectorizer.

python
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
 
texts = [
    "produk bagus dan cepat sampai",
    "kualitas buruk, pengiriman lama",
    "kemasan rapi, sesuai deskripsi",
    "tidak sesuai ekspektasi",
]
 
vectorizer = TfidfVectorizer(
    max_features=1_000,
    ngram_range=(1, 2),
    stop_words=None,
)
X_text = vectorizer.fit_transform(texts)
print(vectorizer.get_feature_names_out()[:10])

ngram_range=(1, 2) menangkap kata tunggal dan pasangan kata. Ini membantu menangkap frasa seperti "cepat sampai" yang artinya beda dari "cepat" dan "sampai" terpisah. Untuk data bahasa Indonesia, daftar stopwords perlu kamu sesuaikan sendiri.

Jika kamu ingin mengubah teks menjadi vektor semantik untuk kemudian masuk ke model tabular, pakai embedding terpisah seperti sentence-transformers. Scikit-learn tidak menyediakan embedding neural. Embedding berdimensi tinggi bisa kamu reduksi dengan TruncatedSVD bila memori jadi masalah.

#Interaksi dan polinomial

PolynomialFeatures membuat kombinasi polinomial dari fitur numerik. Berguna untuk hubungan nonlinier pada model linear, tetapi jumlah fitur meledak cepat.

python
from sklearn.preprocessing import PolynomialFeatures
 
X = [[1, 2], [3, 4], [5, 6]]
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(X)
print(poly.get_feature_names_out(["a", "b"]))

Dengan degree=2 dan dua fitur, kamu mendapat a, b, a^2, a*b, b^2. Untuk degree=3 atau fitur banyak, pertumbuhannya kombinatorial. Kombinasikan dengan SelectKBest atau regularization agar tidak overfitting.

#Binning dan kategorisasi

Mengubah angka menjadi rentang kategori kadang membantu menangkap efek ambang. KBinsDiscretizer melakukannya dengan strategi uniform, quantile, atau kmeans.

python
from sklearn.preprocessing import KBinsDiscretizer
 
X_umur = [[15], [22], [35], [48], [60], [75]]
discretizer = KBinsDiscretizer(n_bins=3, encode="ordinal", strategy="quantile")
X_binned = discretizer.fit_transform(X_umur)
print(X_binned.ravel())

Binning kehilangan informasi detail, jadi ia bukan transformasi ajaib. Ia cocok saat efek target memang berubah pada ambang tertentu, misalnya kelompok usia. Hati-hati: model pohon sudah menangani ambang dengan sendirinya, sehingga binning sering tidak menambah banyak untuk random forest.

#Seleksi fitur

Menghapus fitur berisik mempercepat training dan mengurangi overfitting. Ada tiga pendekatan utama.

Pertama, filter berdasarkan variansi. Fitur dengan nilai hampir konstan tidak membawa sinyal.

python
from sklearn.feature_selection import VarianceThreshold
 
X = [[0, 1, 0], [0, 1, 1], [0, 1, 0], [1, 0, 0], [1, 0, 1]]
selector = VarianceThreshold(threshold=0.1)
X_filtered = selector.fit_transform(X)

Kedua, seleksi univariat dengan uji statistik.

python
from sklearn.feature_selection import SelectKBest, f_classif
 
X_new = SelectKBest(score_func=f_classif, k=5).fit_transform(X_train, y_train)

Untuk klasifikasi, f_classif, chi2, dan mutual_info_classif tersedia. Untuk regresi, pakai f_regression, r_regression, atau mutual_info_regression. Uji univariat mengabaikan interaksi antar fitur. Dua fitur yang lemah sendiri bisa kuat bersama, dan seleksi univariat bisa membuang keduanya.

Ketiga, seleksi berbasis model seperti SelectFromModel.

python
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.feature_selection import SelectFromModel
 
selector = SelectFromModel(
    ExtraTreesClassifier(n_estimators=200, random_state=42),
    threshold="median",
)
X_selected = selector.fit_transform(X_train, y_train)

Jalankan seleksi fitur di dalam pipeline dan cross-validation. Memilih fitur di seluruh dataset sebelum CV membocorkan informasi test ke pemilihan fitur.

#Data leakage dan urutan yang benar

Leakage terjadi ketika informasi yang seharusnya tidak tersedia saat prediksi bocor ke training. Gejalanya klasik: skor validasi sangat tinggi, lalu model gagal total di produksi. Penyebab paling umum:

  • Scaling atau imputasi dihitung pada seluruh data sebelum split.
  • Fitur dibangun dari kolom target atau dari data masa depan.
  • Encoding kategori memakai seluruh data, termasuk test.
  • groupby agregasi memakai test set.

Cara aman adalah satu Pipeline yang berisi semua preprocessing, lalu hanya fit() pada data training.

python
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
 
numeric_cols = ["umur", "pendapatan"]
categorical_cols = ["kota"]
 
preprocessor = ColumnTransformer(
    [
        ("num", Pipeline([("impute", SimpleImputer(strategy="median")),
                          ("scale", StandardScaler())]), numeric_cols),
        ("cat", Pipeline([("impute", SimpleImputer(strategy="most_frequent")),
                          ("encode", OneHotEncoder(handle_unknown="ignore"))]), categorical_cols),
    ]
)
 
pipeline = Pipeline(
    [
        ("preprocess", preprocessor),
        ("model", LogisticRegression(max_iter=1_000)),
    ]
)

Untuk data urutan waktu, split berdasarkan waktu, bukan acak. Pakai TimeSeriesSplit dan jangan pernah membiarkan model melihat masa depan saat memilih fitur.

python
from sklearn.model_selection import TimeSeriesSplit
 
tscv = TimeSeriesSplit(n_splits=3)

Untuk masalah di mana satu entitas muncul berulang, pakai GroupKFold agar data satu entitas tidak tersebar di train dan test sekaligus. Ini mencegah model menghafal entitas alih-alih belajar pola.

#Spline dan fitur basis

SplineTransformer membuat fitur basis B-spline untuk menangkap hubungan nonlinier halus pada satu variabel numerik. Berbeda dengan polinomial, spline memecah rentang menjadi knot dan merepresentasikan kurva secara lokal, sehingga lebih stabil di tepi rentang.

python
import numpy as np
from sklearn.preprocessing import SplineTransformer
 
X_umur = np.array([[20.0], [30.0], [40.0], [50.0], [60.0]])
spline = SplineTransformer(
    n_knots=4,
    degree=3,
    include_bias=True,
)
X_spline = spline.fit_transform(X_umur)
print(X_spline.shape)

Knot menentukan seberapa fleksibel kurva. Semakin banyak knot, semakin fleksibel tetapi semakin rawan overfitting. Spline cocok untuk model linear yang ingin menangkap efek nonlinier seperti hubungan umur terhadap risiko, tanpa harus membuat banyak kolom polinomial.

#Fitur geospasial

Koordinat lintang dan bujur adalah angka, tetapi jarak antar titik tidak linear. Proyeksikan koordinat ke ruang lokal memakai referensi yang masuk akal sebelum menghitung jarak. Haversine menghitung jarak lingkaran besar untuk Bumi, sedangkan jarak Euclidean pada koordinat mentah hanya mendekati di wilayah sempit.

python
import numpy as np
 
def haversine_km(lat1, lon1, lat2, lon2):
    r = 6371.0
    lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2])
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    a = np.sin(dlat / 2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2) ** 2
    return 2 * r * np.arcsin(np.sqrt(a))
 
print(haversine_km(-6.2, 106.8, -6.9, 107.6))

Fitur seperti jarak ke toko terdekat, jumlah kompetitor dalam radius tertentu, atau densitas populasi sekitar titik sering lebih informatif daripada koordinat mentah. Hitung fitur geospasial ini dari data training saja dan hindari kebocoran posisi test.

#Checklist feature engineering

  • Pisahkan test set sebelum transformasi apa pun.
  • Hitung statistik preprocessing hanya dari data training.
  • Simpan transformer yang sudah di-fit, jangan re-fit pada saat inference.
  • Uji kategori baru, nilai kosong, dan angka ekstrem pada data produksi.
  • Ukur dampak setiap fitur baru lewat cross-validation, bukan asumsi.
  • Hindari fitur yang dibangun dari kolom target atau data masa depan.
  • Dokumentasikan arti dan satuan setiap fitur, terutama rasio dan agregasi.

#Glosarium

IstilahArti praktis
FeatureKolom input yang dipakai model untuk prediksi.
ScalingMenyesuaikan rentang nilai numerik agar fitur sebanding.
One-hot encodingMengubah kategori menjadi kolom biner per nilai kategori.
Ordinal encodingMemetakan kategori ke angka berurutan, cocok bila ada urutan.
Target encodingMengganti kategori dengan statistik target, rentan leakage bila salah.
ImputasiMengisi nilai kosong dengan estimasi tertentu.
CardinalityBanyaknya nilai unik dalam satu kolom kategori.
SiklusPola yang berulang secara periodik, misalnya jam dan bulan.
InteraksiEfek gabungan dua fitur atau lebih terhadap target.
BinningMengubah angka menjadi rentang atau kelompok kategori.
Data leakageInformasi yang tidak seharusnya tersedia saat prediksi masuk ke training.
Cross-validationEvaluasi berulang pada beberapa pembagian data training.
PipelineRangkaian transformer dan estimator yang diperlakukan sebagai satu objek.

Baca Cheat Sheet Lengkap

Login atau daftar akun gratis untuk membaca cheat sheet ini.

LoginDaftar Gratis
Share: