MA1420 · DATA SAINS · SESI 10

Transformasi Data:
Scaling, Normalisasi & Feature Engineering

Data yang sudah bersih belum tentu siap dianalisis atau dimasukkan ke model. Transformasi mengubah bentuk dan skala data agar algoritma bisa belajar lebih baik, distribusi lebih sesuai asumsi, dan fitur baru yang informatif bisa diciptakan.

1. Mengapa Data Perlu Ditransformasi?

💡 ILUSTRASI — LOMBA LARI TIDAK ADIL

Bayangkan lomba lari di mana sebagian peserta berlari dalam meter dan sebagian lain dalam kilometer. Peserta yang berlari "5000" (meter) terlihat jauh lebih jauh dari yang berlari "5" (kilometer) — padahal jaraknya sama.

Begitu pula di machine learning: fitur tinggi badan (150–185 cm) dan gaji (3.000.000–20.000.000 rupiah) memiliki skala sangat berbeda. Algoritma seperti KNN atau regresi akan "berpikir" gaji jauh lebih penting hanya karena nilainya lebih besar — bukan karena kontribusinya pada model. Transformasi menyetarakan lapangan bermain.

⚖️
Scaling
Mengubah rentang nilai fitur agar setara
→ Min-Max, Standard
📐
Normalisasi
Mengubah distribusi mendekati normal
→ Log, Box-Cox, Sqrt
🔨
Feature Engineering
Menciptakan fitur baru yang informatif
→ Interaksi, ekstraksi, binning
📊
Agregasi
Meringkas data per grup/kelompok
→ GroupBy, pivot, resample

2. Scaling dan Normalisasi Fitur

Dua metode scaling paling umum: Min-Max Scaling (Normalisasi) dan Standard Scaling (Standardisasi). Keduanya berbeda tujuan dan karakteristik.

MIN-MAX SCALING (Normalisasi) x' = (x − x_min) / (x_max − x_min) Hasil: nilai dalam rentang [0, 1]
Memetakan semua nilai ke [0,1]. Nilai minimum → 0, nilai maksimum → 1.
✓ Cocok saat distribusi tidak normal
✓ Wajib untuk neural network, image pixel
✗ Sangat sensitif terhadap outlier
✗ Rentang berubah jika ada data baru di luar min/max
STANDARD SCALING (Standardisasi) z = (x − μ) / σ Hasil: mean=0, std=1 (z-score)
Menggeser mean ke 0 dan skala std ke 1. Tidak ada batas atas/bawah.
✓ Robust terhadap outlier (lebih baik dari Min-Max)
✓ Wajib untuk PCA, SVM, regresi linear
✗ Asumsi distribusi mendekati normal untuk interpretasi

Ilustrasi Visual: Efek Scaling pada Data

CONTOH: NILAI SEBELUM SCALING (skala berbeda)
tinggi (cm)
170
berat (kg)
65
gaji (juta)
7.500.000

⚠️ Gaji mendominasi karena nilainya jutaan — algoritma jarak (KNN, K-Means) akan bias!

SETELAH MIN-MAX SCALING (semua [0, 1])
tinggi
0.67
berat
0.50
gaji
0.55

✓ Semua fitur berkontribusi setara — algoritma bisa belajar dengan adil!

3. Transformasi Log untuk Distribusi Miring

Data seperti pendapatan, harga properti, atau jumlah pengunjung web sering memiliki distribusi sangat skewed kanan (ekor panjang ke kanan). Transformasi log mengubah distribusi ini menjadi lebih simetris.

💡 ILUSTRASI — SKALA RICHTER GEMPA

Skala Richter gempa bumi adalah skala logaritmik: gempa magnitudo 7 bukan "dua kali lebih kuat" dari magnitudo 6 — tapi 10 kali lebih kuat. Skala log mengompresi rentang nilai yang sangat lebar menjadi skala yang bisa dipahami dan dianalisis.

Sama halnya dengan gaji: perbedaan antara Rp 3 juta dan Rp 6 juta terasa sangat besar bagi pekerja, sementara perbedaan antara Rp 500 juta dan Rp 503 juta terasa tidak signifikan — meski selisihnya sama secara absolut. Log transform merefleksikan persepsi relatif ini.

SEBELUM LOG — distribusi skewed
3 juta
3M
5 juta
5M
10 juta
10M
50 juta
50M
100 juta
100M

Nilai besar mendominasi sepenuhnya!

SETELAH log1p() — lebih merata
3 juta
14.9
5 juta
15.4
10 juta
16.1
50 juta
17.7
100 juta
18.4

Perbedaan lebih proporsional dan wajar!

💡 LOG vs LOG1P

np.log(x): tidak bisa menangani nilai 0 (log(0) = -∞). Gunakan saat data dijamin > 0.

np.log1p(x) = log(1+x): aman untuk data yang mengandung 0. Lebih umum digunakan untuk data count dan frekuensi. Ini pilihan yang lebih aman secara default.

4. Kapan Menggunakan Metode Transformasi Mana?

Metode
Gunakan ketika...
Jangan ketika...
Min-Max
Neural network, image processing; perlu rentang [0,1] yang pasti; tidak ada outlier signifikan
Ada outlier ekstrem (satu nilai besar akan "menekan" semua nilai lain)
Standard (Z)
PCA, SVM, regresi linear, KNN; distribusi mendekati normal; ada outlier sedang
Distribusi sangat bimodal atau non-normal parah
Log / log1p
Data pendapatan, harga, populasi — distribusi skewed kanan parah; data count
Data yang sudah normal; data dengan nilai negatif (log tidak bisa)
Sqrt
Data count yang moderat skewed; alternatif log yang lebih ringan
Distribusi sudah normal; data dengan nilai negatif
Box-Cox
Ingin transformasi optimal yang menghasilkan distribusi paling normal; mencari λ terbaik
Butuh interpretasi mudah; data mengandung nol/negatif (gunakan Yeo-Johnson)
Robustscaler
Ada banyak outlier — menggunakan IQR bukan mean/std, lebih robust
Data sudah bersih tanpa outlier (overkill)
⚠️ ATURAN EMAS: FIT DI TRAIN, TRANSFORM DI TEST

Saat menggunakan scaling dalam machine learning, scaler harus di-fit hanya pada data training, kemudian hasilnya digunakan untuk men-transform data test.

Jika scaler di-fit pada seluruh dataset (termasuk test), terjadi data leakage — model "melihat" informasi dari data test saat training, membuat evaluasi model tidak valid.

5. Feature Engineering: Menciptakan Fitur Baru

Feature engineering adalah seni menciptakan variabel baru yang lebih informatif dari fitur yang sudah ada. Sering kali model sederhana dengan fitur rekayasa yang baik mengalahkan model kompleks dengan fitur mentah.

EKSTRAKSI DATETIME
Komponen Waktu
Dari: tanggal_transaksi
→ bulan, hari_dalam_seminggu → kuartal, is_weekend → jam (pagi/siang/malam) → selisih hari dari hari ini
INTERAKSI FITUR
Kombinasi Dua Fitur
Dari: berat + tinggi
→ BMI = berat / tinggi² → rasio = fitur_a / fitur_b → selisih = fitur_a - fitur_b → produk = fitur_a × fitur_b
BINNING (Diskretisasi)
Numerik → Kategori
Dari: usia (kontinu)
→ usia_grup: 0-17 = "anak" 18-25 = "muda" 26-60 = "dewasa" 60+ = "senior"
AGREGASI PER GRUP
Statistik Konteks
Dari: nilai per mahasiswa
→ rata_nilai_kelas → rank_dalam_kelas → selisih_dari_rata_kelas → persentil_dalam_angkatan
FLAG / INDIKATOR
Variabel Biner Baru
Dari: nilai_transaksi
→ is_high_value (> 1jt) → is_weekend_purchase → is_first_transaction → is_outlier
TEXT → NUMERIK
Panjang & Hitungan
Dari: kolom_komentar (teks)
→ panjang_komentar → jumlah_kata → jumlah_tanda_seru → sentimen_skor

6. Agregasi dan GroupBy

Agregasi mengubah data granular (per baris) menjadi ringkasan per kelompok. Ini penting untuk analisis deskriptif, pembuatan fitur kontekstual, dan laporan.

DATA ASLI (per transaksi)
Andi · Makanan45rb
Andi · Transport25rb
Budi · Makanan60rb
Andi · Hiburan120rb
Budi · Transport30rb
Budi · Hiburan80rb
SETELAH groupby('nama').agg()
AndiTotal: 190rb | Mean: 63rb | Count: 3
BudiTotal: 170rb | Mean: 57rb | Count: 3
groupby(['nama','kategori'])
Andi·Makanan45rb
Andi·Transport25rb
...

Demo Interaktif: Kalkulator Scaling

Masukkan data numerik (pisahkan dengan koma) untuk melihat hasil Min-Max dan Z-Score secara langsung:

🔢 KALKULATOR SCALING INTERAKTIF
MIN-MAX [0, 1]
STANDARD SCALING (z-score)

7. Praktik Python: Pipeline Transformasi Lengkap

7.1 Scaling dengan Scikit-learn

PYTHON · SCALING — MIN-MAX & STANDARD
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler

np.random.seed(42)
df = pd.DataFrame({
    'tinggi_cm' : np.random.normal(168, 8, 10),
    'berat_kg'  : np.random.normal(65, 12, 10),
    'gaji_juta' : np.random.exponential(5, 10) + 3  # skewed kanan
})
print("=== DATA ASLI ===")
print(df.round(2).to_string())

# ── Min-Max Scaling ───────────────────────────────
scaler_mm = MinMaxScaler()
df_mm = pd.DataFrame(
    scaler_mm.fit_transform(df),
    columns=[c + '_mm' for c in df.columns]
)

# ── Standard Scaling ──────────────────────────────
scaler_std = StandardScaler()
df_std = pd.DataFrame(
    scaler_std.fit_transform(df),
    columns=[c + '_std' for c in df.columns]
)

print("\n=== STATISTIK SETELAH SCALING ===")
print("\nMin-Max (semua harus [0,1]):")
print(df_mm.describe().loc[['min','max']].round(3))
print("\nStandard (mean≈0, std≈1):")
print(df_std.describe().loc[['mean','std']].round(3))
📤 OUTPUT
=== STATISTIK SETELAH SCALING ===

Min-Max (semua harus [0,1]):
     tinggi_cm_mm  berat_kg_mm  gaji_juta_mm
min           0.0          0.0           0.0
max           1.0          1.0           1.0   ✓ rentang [0,1]

Standard (mean≈0, std≈1):
      tinggi_cm_std  berat_kg_std  gaji_juta_std
mean          -0.0          -0.0           0.00
std            1.0           1.0           1.00   ✓ mean=0, std=1

7.2 Feature Engineering Lengkap

PYTHON · FEATURE ENGINEERING
# Dataset transaksi e-commerce
df_tx = pd.DataFrame({
    'user_id'   : ['U01','U02','U01','U03','U02','U01'],
    'waktu'     : pd.to_datetime([
        '2024-10-01 08:30','2024-10-01 14:00','2024-10-06 21:30',
        '2024-10-07 10:00','2024-10-07 16:00','2024-10-08 09:00'
    ]),
    'jumlah'    : [45000,120000,8000,350000,67000,15000],
    'item_count': [2,5,1,8,3,1]
})

# ── Feature dari datetime ─────────────────────────
df_tx['jam']        = df_tx['waktu'].dt.hour
df_tx['hari_minggu'] = df_tx['waktu'].dt.day_name()
df_tx['is_weekend']  = df_tx['waktu'].dt.dayofweek >= 5
df_tx['sesi'] = df_tx['jam'].apply(lambda h:
    'pagi' if h < 12 else 'siang' if h < 17 else 'malam')

# ── Feature interaksi & turunan ───────────────────
df_tx['avg_per_item'] = df_tx['jumlah'] / df_tx['item_count']
df_tx['log_jumlah']  = np.log1p(df_tx['jumlah'])
df_tx['is_besar']    = df_tx['jumlah'] > 100000

# ── Agregasi per user (fitur kontekstual) ─────────
user_stats = df_tx.groupby('user_id')['jumlah'].agg(
    total_belanja='sum', rata_belanja='mean', frekuensi='count'
).reset_index()

df_tx = df_tx.merge(user_stats, on='user_id')
df_tx['pct_dari_total'] = (df_tx['jumlah'] / df_tx['total_belanja'] * 100).round(1)

print("=== FITUR BARU ===")
print(df_tx[['user_id','jumlah','sesi','is_weekend',
             'log_jumlah','avg_per_item','pct_dari_total']].round(2))

print("\n=== RINGKASAN PER USER ===")
print(user_stats)
📤 OUTPUT
=== FITUR BARU ===
  user_id  jumlah    sesi  is_weekend  log_jumlah  avg_per_item  pct_dari_total
0     U01   45000    pagi       False       10.71      22500.0            66.1
1     U02  120000   siang       False       11.70      24000.0            64.2
2     U01    8000   malam        True        8.99       8000.0            11.7
3     U03  350000    pagi        True       12.77      43750.0           100.0
4     U02   67000   siang        True       11.11      22333.3            35.8
5     U01   15000    pagi       False        9.62      15000.0            22.1

=== RINGKASAN PER USER ===
  user_id  total_belanja  rata_belanja  frekuensi
0     U01          68000      22666.7          3
1     U02         187000      93500.0          2
2     U03         350000     350000.0          1

Uji Pemahaman Sesi 10

🧩 PERTANYAAN 1 — SCALING
Dataset berisi fitur "umur" (20–60 tahun) dan "pendapatan" (Rp 2 juta – Rp 50 juta). Akan digunakan untuk algoritma KNN. Transformasi apa yang HARUS dilakukan?
Benar! B. KNN (K-Nearest Neighbors) menghitung jarak antar data poin. Tanpa scaling, fitur pendapatan (2jt–50jt) akan mendominasi perhitungan jarak karena nilainya jutaan kali lebih besar dari umur (20–60). Hasilnya: "tetangga terdekat" ditentukan hampir seluruhnya oleh pendapatan, bukan umur. Scaling menyetarakan kontribusi keduanya.
🧩 PERTANYAAN 2 — DATA LEAKAGE
Peneliti membagi data menjadi 80% train dan 20% test. Kemudian menjalankan scaler.fit_transform() pada seluruh dataset (train+test) sebelum membagi. Apa masalahnya?
Benar! B. Ini adalah data leakage — informasi dari test set "bocor" ke proses training melalui parameter scaler (min, max, mean, std). Aturan yang benar: fit scaler hanya pada train set, kemudian gunakan parameter tersebut untuk transform baik train maupun test. Dengan leakage, model terlihat lebih baik dari kenyataannya saat digunakan di data baru.
🧩 PERTANYAAN 3 — FEATURE ENGINEERING
Dari kolom "tgl_lahir" dan "tgl_pembelian pertama", fitur baru mana yang paling bernilai untuk model prediksi churn pelanggan?
Benar! B. Feature engineering yang baik menciptakan fitur yang secara semantis bermakna untuk masalah yang diprediksi. Untuk churn: umur pelanggan (berapa lama sudah menjadi pelanggan) lebih informatif dari tanggal asli. Lama menjadi pelanggan dan umur saat pertama beli bisa mengungkap pola (pelanggan muda cenderung churn lebih cepat?). Tanggal mentah sebagai integer tidak bermakna untuk model.
📋 Ringkasan Sesi 10