BAB I PENDAHULUAN

1.1 Latar Belakang Masalah

Feature engineering (rekayasa fitur) adalah sebuah proses fundamental dalam machine learning yang berfokus pada transformasi data mentah menjadi representasi fitur yang informatif dan sesuai untuk algoritma pemodelan. Proses ini tidak hanya bersifat teknis, tetapi juga memerlukan kombinasi antara pemahaman domain, analisis data, dan intuisi untuk mengekstrak pola yang paling relevan. Dalam banyak konteks, seperti analisis sentimen, pemilihan fitur yang tepat melalui feature engineering terbukti krusial untuk menghasilkan model yang akurat dan dapat diinterpretasi. (Sibaroni & Fauzi, 2021). Kualitas fitur yang dihasilkan sering kali memiliki dampak yang lebih besar terhadap hasil akhir daripada kecanggihan algoritma yang digunakan.

Penerapan feature engineering secara langsung bertujuan untuk meningkatkan performa dan akurasi model. Banyak penelitian telah menunjukkan bahwa data mentah yang digunakan tanpa melalui proses rekayasa fitur sering kali gagal memberikan hasil yang optimal. Sebagai contoh, dalam tugas klasifikasi, teknik spesifik seperti feature scaling (misalnya perbandingan antara metode Standard Scaler dan Min-Max Scaler) telah terbukti secara signifikan memengaruhi kinerja algoritma, di mana pemilihan metode yang tepat dapat meningkatkan akurasi klasifikasi secara substansial (Utama & Hartati, 2023). Tanpa rekayasa fitur yang cermat, model dapat didominasi oleh variabel dengan rentang nilai yang besar atau menjadi bias terhadap data yang tidak relevan.

Dalam praktiknya, feature engineering mencakup berbagai macam teknik untuk mengatasi tantangan umum dalam data. Ini termasuk strategi untuk menangani data yang hilang (missing values), mengelola variabel dengan kardinalitas tinggi, menangani data pencilan (outliers), dan melakukan encoding pada data kategorikal. Salah satu tantangan yang paling sering dibahas dan berdampak signifikan adalah penanganan imbalanced dataset (dataset tidak seimbang), di mana satu kelas jauh lebih dominan daripada kelas lainnya. Mengatasi ketidakseimbangan ini merupakan bagian integral dari rekayasa fitur untuk mencegah model menjadi bias dan tidak efektif dalam memprediksi kelas minoritas (He & Garcia, 2009).

1.2 Rumusan Masalah

  1. Bagaimana memahami konsep dari berbagai jenis feature engineering pada RStudio?
  2. Bagaimana melakukan teknik feature engineering di program RStudio?

1.3 Tujuan

  1. Mahasiswa memahami konsep dari berbagai jenis feature engineering pada RStudio.
  2. Mahasiswa dapat melakukan teknik feature engineering di program RStudio.

BAB II TINJAUAN PUSTAKA

2.1 Feature Engineering

Feature engineering merupakan proses mengidentifikasi dan menentukan kandidat fitur yang digunakan untuk merepresentasikan data dalam bentuk vektor fitur (feature vector) pada pembelajaran mesin. Fitur-fitur tersebut berasal dari atribut data yang dianggap memiliki pengaruh terhadap keluaran atau hasil prediksi model. Pemilihan fitur yang tepat menjadi bagian penting dalam pembelajaran mesin karena representasi data yang digunakan dapat memengaruhi kemampuan model dalam mempelajari pola dan menghasilkan prediksi (Putra, 2020).

Feature Engineering adalah langkah-langkah untuk mengubah data mentah menjadi fitur-fitur yang dapat digunakan dalam algoritma machine learning. Selama proses feature engineering, variabel/fitur yang paling berpengaruh dipilih dan direkayasa untuk pemodelan. Feature engineering memerlukan pemahaman yang baik karena melibatkan kombinasi analisis data, pengetahuan tentang data, dan sedikit intuisi. Tujuan dari feature engineering adalah menyederhanakan dan mempercepat transformasi data sekaligus meningkatkan akurasi model. kualitas fitur jauh lebih penting daripada seberapa canggih algoritma yang dipilih. Berikut merupakan beberapa jenis feature engineering yang harus dilakukan (Fransiska, 2026):

A. Handling Missing Value

Missing values atau missing data, terjadi ketika tidak ada data / tidak ada nilai yang tersimpan untuk observasi tertentu dalam suatu variabel. Missing data adalah kejadian yang umum dan dapat berdampak signifikan pada pemodelan machine learning. Data yang tidak lengkap adalah masalah yang tidak terhindarkan dalam menangani sebagian besar sumber data.

B. Kardinalitas

Kardinalitas merujuk pada jumlah nilai unik, atau label, yang terdapat dalam suatu variabel kategoris. Konsep ini digunakan untuk mengukur granularitas atau keunikan data dalam sebuah fitur. Kardinalitas dapat diklasifikasikan dalam spektrum, namun umumnya dibedakan menjadi kardinalitas rendah (low cardinality) dan kardinalitas tinggi (high cardinality). Pengaruh kardinalitas, sangat krusial terhadap performa model dan efisiensi komputasi. Pertama, variabel high cardinality dapat menyebabkan curse of dimensionality jika ditransformasi menggunakan metode encoding standar seperti One-Hot Encoding. Metode ini akan menciptakan banyak fitur biner baru (sesuai jumlah label), membuat data menjadi sangat jarang dan secara drastis meningkatkan kompleksitas komputasi. Kedua, kardinalitas secara signifikan meningkatkan risiko overfitting. Hal ini terjadi karena banyak label mungkin hanya muncul beberapa kali dalam set data latih, sehingga model cenderung menghafal pola spesifik yang terkait dengan label langka tersebut, alih-alih mempelajari pola umum yang dapat digeneralisasi ke data yang belum pernah terlihat.

C. Splitting Data

Splitting data merupakan strategi fundamental dalam machine learning untuk membagi himpunan data menjadi bagian terpisah: data training dan data testing. Pembagian ini krusial untuk membangun model yang robust dan dapat digeneralisasi dengan baik pada data baru. Proporsi pembagian data bersifat subjektif dan fleksibel. Rasio yang umum digunakan adalah 80% untuk training dan 20% untuk testing. Namun, rasio ini dapat disesuaikan tergantung pada ukuran dataset.

D. Handling Outlier

Outlier, atau dikenal sebagai pencilan, merupakan observasi atau titik data yang menunjukkan deviasi ekstrem dan berbeda secara signifikan dari sebagian besar data lain dalam suatu set data. Keberadaan outlier dapat diatribusikan ke berbagai sumber, mulai dari kesalahan pengukuran, kesalahan entri data (misinput), kontaminasi data, hingga representasi sah dari kejadian langka atau variabilitas inheren dalam populasi. Dalam analisis statistik dan pemodelan machine learning, outlier menuntut perhatian khusus karena memiliki potensi untuk memberikan pengaruh yang tidak proporsional (disproportionate influence) terhadap hasil.

E. Scaling Data

Scaling data adalah salah satu langkah pra-pemrosesan dalam analisis data untuk mentransformasi variabel data ke dalam rentang skala yang sama. Tujuannya adalah untuk memastikan bahwa tidak ada satu variabel independen pun yang mendominasi proses pembelajaran hanya karena memiliki rentang nilai yang lebih besar dibandingkan variabel independen lainnya. Sebagaimana dinyatakan oleh Singh dan Singh (2020), normalisasi data sering kali dapat meningkatkan performa model prediktif secara signifikan, terutama untuk algoritma yang sensitif terhadap skala input.

F. Encoding

Feature encoding adalah proses mengubah fitur kategoris atau nonnumerik menjadi format numerik yang dapat digunakan sebagai input untuk algoritma machine learning. Banyak algoritma machine learning membutuhkan input numerik. Ada beberapa teknik umum untuk feature encoding, seperti OneHot Encoding dan Ordinal Encoding.

G. Imbalanced Dataset

Imbalanced Dataset adalah sebuah dataset di mana distribusi kelas atau kategorinya tidak setara. Kelas-kelas yang mencakup proporsi besar dari set data disebut kelas mayoritas, sedangkan kelas-kelas yang mencakup proporsi lebih kecil disebut kelas minoritas. Dalam praktiknya, akan lebih sering menjumpai data yang tidak seimbang daripada yang seimbang. Hal ini tidak serta merta menjadi masalah jika variabel target hanya memiliki sedikit ketidakseimbangan. Sayangnya, kenyataannya tidak selalu demikian dan variabel target Anda mungkin sangat tidak seimbang, sebagai contoh, dengan rasio 10:1.

BAB III METODE PENELITIAN

3.1 Sumber Data

Jenis data yang digunakan pada penelitian ini adalah data kategorik dan numerik. Data kategorik adalah data yang menunjukkan kategori atau kelompok tertentu dan digunakan untuk membedakan karakteristik suatu objek sedangkan data numerik adalah data berbentuk angka yang menunjukkan nilai atau jumlah dan dapat digunakan dalam perhitungan matematis. Sumber data yang diperoleh dalam penelitian ini adalah data sekunder. Data sekunder adalah sekumpulan informasi yang telah ada sebelumnya dan digunakan sebagai pelengkap kebutuhan data penelitian, di mana pada praktikum ini data sekundernya adalah data yang berasal dari Asisten Praktikum.

3.2 Variabel Penelitian

Variabel penelitian adalah segala sesuatu yang akan menjadi objek pengamatan penelitian. Pada laporan ini terdapat lima variabel yang digunakan pada data. Variabel tersebut, yaitu hujan, suhu, kelembapan, keadaan cuaca, dan kecepatan angn

3.3 Langkah-langkah Analisis

  1. Input data
  2. Pengecekan dan penanganan missing value menggunakan mode imputation dan interpolasi
  3. Pengurangan kardinalitas variabel kategorik menggunakan fungsi binning
  4. Pembagian data latih dan data uji menggunakan metode stratified splitting
  5. Pengecekan dan penanganan outlier menggunakan metode capping
  6. Pemeriksaan skewness dan penerapan scaling menggunakan Standard Scaler
  7. Transformasi variabel kategorik menjadi numerik menggunakan One-Hot Encoding
  8. Penanganan ketidakseimbangan data menggunakan SMOTE

BAB IV HASIL DAN PEMBAHASAN

4.1 Library

langkah pertama adalah memanggil library yang akan digunakan setelah itu memanggil data

library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(readxl)
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.3
## Warning: package 'ggplot2' was built under R version 4.5.3
## Warning: package 'readr' was built under R version 4.5.3
## Warning: package 'purrr' was built under R version 4.5.3
## Warning: package 'dplyr' was built under R version 4.5.3
## Warning: package 'forcats' was built under R version 4.5.1
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.5.1
## ✔ ggplot2   4.0.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(rsample)
## Warning: package 'rsample' was built under R version 4.5.3
library(DescTools)
## Warning: package 'DescTools' was built under R version 4.5.1
library(recipes)
## 
## Attaching package: 'recipes'
## 
## The following object is masked from 'package:stringr':
## 
##     fixed
## 
## The following object is masked from 'package:stats':
## 
##     step
library(themis)
## Warning: package 'themis' was built under R version 4.5.3
library(readxl)
data_curah_hujan <- read_excel("data curah hujan (1).xlsx")
data <- data_curah_hujan
head(data)
## # A tibble: 6 × 5
##   Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
##   <dbl> <dbl>      <dbl>         <dbl>           <dbl>
## 1     1  23           95             5              NA
## 2     1  24           90             1              NA
## 3     1  26.8         77             1              NA
## 4     1  29.6         62             2               2
## 5     1  30.8         56             1               7
## 6     1  31           55             1               7
str(data)
## tibble [743 × 5] (S3: tbl_df/tbl/data.frame)
##  $ Hujan          : num [1:743] 1 1 1 1 1 1 1 2 2 2 ...
##  $ Suhu           : num [1:743] 23 24 26.8 29.6 30.8 31 30.4 30.9 30.2 29.7 ...
##  $ Kelembapan     : num [1:743] 95 90 77 62 56 55 57 58 62 62 ...
##  $ Keadaan_Cuaca  : num [1:743] 5 1 1 2 1 1 3 2 2 2 ...
##  $ Kecepatan_Angin: num [1:743] NA NA NA 2 7 7 9 10 8 7 ...

Berdasarkan output yang diperoleh, dataset yang digunakan terdiri dari 743 observasi dan 5 variabel, yaitu Hujan, Suhu, Kelembapan, Keadaan_Cuaca, dan Kecepatan_Angin. Kelima variabel tersebut memiliki tipe data numerik. Hasil pengecekan menunjukkan bahwa terdapat nilai hilang pada variabel Keadaan_Cuaca dan variabel Kecepatan_Angin. Oleh karena itu, penanganan missing value dilakukan melalui interpolasi pada variabel Keadaan_Cuaca dan mode imputation pada variabel Kecepatan_Angin agar data dapat digunakan pada tahapan preprocessing selanjutnya.

4.2 Handling Missing Value

# Cek missing value
colSums(is.na(data))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               9             314
colMeans(is.na(data))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##      0.00000000      0.00000000      0.00000000      0.01211306      0.42261104
# Mode imputation untuk Kecepatan_Angin
mode_value <- names(
  which.max(table(data$Kecepatan_Angin))
)
mode_value <- as.numeric(mode_value)

df_imp4 <- data

df_imp4$Kecepatan_Angin[
  is.na(df_imp4$Kecepatan_Angin)
] <- mode_value

# Interpolasi Keadaan_Cuaca
df_imp4$Keadaan_Cuaca <- na.approx(
  df_imp4$Keadaan_Cuaca,
  na.rm = FALSE
)

# Cek missing value setelah penanganan
colSums(is.na(df_imp4))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0               0

Berdasarkan hasil pemeriksaan missing value, variabel Keadaan_Cuaca memiliki 9 data hilang, sedangkan Kecepatan_Angin memiliki 314 data hilang dari total 743 observasi. Persentase missing value pada Keadaan_Cuaca sebesar 1,21%, sementara pada Kecepatan_Angin mencapai 42,26%. Tidak terdapat missing value pada variabel Hujan, Suhu, dan Kelembapan. Penanganan dilakukan menggunakan mode imputation pada variabel Kecepatan_Angin dan interpolasi pada variabel Keadaan_Cuaca. Mode imputation menggantikan nilai yang hilang dengan nilai yang paling sering muncul pada variabel tersebut. Sementara itu, interpolasi menggunakan nilai di sekitar data yang hilang untuk memperkirakan nilai penggantinya. Setelah kedua metode diterapkan, seluruh variabel memiliki 0 missing value sehingga data dapat dilanjutkan ke tahapan preprocessing berikutnya.

4.3 Kardinalitas

# Melihat nilai Keadaan_Cuaca
head(df_imp4, 10)
## # A tibble: 10 × 5
##    Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
##    <dbl> <dbl>      <dbl>         <dbl>           <dbl>
##  1     1  23           95             5               3
##  2     1  24           90             1               3
##  3     1  26.8         77             1               3
##  4     1  29.6         62             2               2
##  5     1  30.8         56             1               7
##  6     1  31           55             1               7
##  7     1  30.4         57             3               9
##  8     2  30.9         58             2              10
##  9     2  30.2         62             2               8
## 10     2  29.7         62             2               7
unique(df_imp4$Keadaan_Cuaca)
##  [1]  5.0  1.0  2.0  3.0 14.0 60.0 61.0 21.0 29.0 10.0 16.0 62.0 63.0 65.0 15.0
## [16] 17.0 13.0 95.0 91.0 49.0 97.0 56.0  1.5
# Menentukan batas interval dan label
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
labels <- 0:9

# Mengelompokkan nilai menjadi kategori
df_imp4$Keadaan_Cuaca_reduced <- cut(
  df_imp4$Keadaan_Cuaca,
  breaks = bins,
  labels = labels,
  right = TRUE,
  include.lowest = TRUE
)

# Menampilkan hasil
head(df_imp4, 10)
## # A tibble: 10 × 6
##    Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin Keadaan_Cuaca_reduced
##    <dbl> <dbl>      <dbl>         <dbl>           <dbl> <fct>                
##  1     1  23           95             5               3 0                    
##  2     1  24           90             1               3 0                    
##  3     1  26.8         77             1               3 0                    
##  4     1  29.6         62             2               2 0                    
##  5     1  30.8         56             1               7 0                    
##  6     1  31           55             1               7 0                    
##  7     1  30.4         57             3               9 0                    
##  8     2  30.9         58             2              10 0                    
##  9     2  30.2         62             2               8 0                    
## 10     2  29.7         62             2               7 0
# Membandingkan kardinalitas
cat(
  "Jumlah nilai unik sebelum:",
  length(unique(df_imp4$Keadaan_Cuaca)), "\n"
)
## Jumlah nilai unik sebelum: 23
cat(
  "Jumlah kategori setelah:",
  length(unique(na.omit(df_imp4$Keadaan_Cuaca_reduced))), "\n"
)
## Jumlah kategori setelah: 7
unique(df_imp4$Keadaan_Cuaca_reduced)
## [1] 0 1 5 6 2 9 4
## Levels: 0 1 2 3 4 5 6 7 8 9

Sebelum reduksi kardinalitas, variabel Keadaan_Cuaca memiliki 23 nilai unik. Setelah nilai tersebut dikelompokkan menggunakan interval 10 satuan melalui fungsi cut(), jumlah kategori yang teramati berkurang menjadi 7 kategori, yaitu 0, 1, 2, 4, 5, 6, dan 9. Reduksi kardinalitas bertujuan menyederhanakan variasi nilai dengan mengelompokkan nilai numerik ke dalam kategori interval tertentu. Dengan demikian, data menjadi lebih ringkas dan dapat lebih mudah diinterpretasikan sebagai kelompok kondisi cuaca. Namun, kategori 3, 7, dan 8 tidak muncul pada hasil karena tidak terdapat observasi yang masuk ke interval tersebut.

4.4 Splitting Data

set.seed(200)

split_stratify <- initial_split(
  df_imp4,
  prop = 0.8,
  strata = Hujan
)

# Membagi data
train_data <- training(split_stratify)
test_data  <- testing(split_stratify)

# Memisahkan fitur dan target
X_train <- train_data %>% select(-Hujan)
X_test  <- test_data %>% select(-Hujan)

y_train <- train_data$Hujan
y_test  <- test_data$Hujan

# Melihat dimensi data
dim(X_train)
## [1] 594   5
dim(X_test)
## [1] 149   5
# Membandingkan proporsi kelas
prop.table(table(y_train))
## y_train
##         1         2 
## 0.2205387 0.7794613
prop.table(table(y_test))
## y_test
##         1         2 
## 0.2214765 0.7785235

Hasil tersebut menunjukkan bahwa proporsi kelas target pada data latih dan data uji relatif sama. Kelas 1 mencakup sekitar 22% data, sedangkan kelas 2 mencakup sekitar 78% data. Hal ini menunjukkan bahwa stratified splitting berhasil mempertahankan distribusi kelas target pada kedua kelompok data. Pembagian ini penting agar evaluasi model pada data uji dilakukan pada distribusi kelas yang relatif menyerupai data latih. Selain itu, pemisahan data dilakukan sebelum capping, scaling, encoding, dan SMOTE agar parameter preprocessing dipelajari dari data latih dan tidak menggunakan informasi statistik dari data uji.

4.5 Handling Outlier

# Variabel numerik
list_num <- c(
  "Suhu",
  "Kelembapan",
  "Kecepatan_Angin"
)

# Wadah hasil deteksi outlier
outliers <- data.frame(
  Kolom = character(),
  Q1 = numeric(),
  Q3 = numeric(),
  IQR = numeric(),
  Lower_Bound = numeric(),
  Upper_Bound = numeric(),
  Jumlah_Outlier = integer()
)

# Deteksi outlier menggunakan IQR
for (col in list_num) {

  Q1 <- quantile(X_train[[col]], 0.25, na.rm = TRUE)
  Q3 <- quantile(X_train[[col]], 0.75, na.rm = TRUE)
  IQR_val <- Q3 - Q1

  lower <- Q1 - 1.5 * IQR_val
  upper <- Q3 + 1.5 * IQR_val

  jumlah <- sum(
    X_train[[col]] < lower |
      X_train[[col]] > upper,
    na.rm = TRUE
  )

  outliers <- rbind(
    outliers,
    data.frame(
      Kolom = col,
      Q1 = Q1,
      Q3 = Q3,
      IQR = IQR_val,
      Lower_Bound = lower,
      Upper_Bound = upper,
      Jumlah_Outlier = jumlah
    )
  )
}

# Menampilkan hasil deteksi
outliers
##                Kolom     Q1   Q3    IQR Lower_Bound Upper_Bound Jumlah_Outlier
## 25%             Suhu 24.325 28.9  4.575     17.4625     35.7625              0
## 25%1      Kelembapan 75.000 94.0 19.000     46.5000    122.5000              0
## 25%2 Kecepatan_Angin  3.000  7.0  4.000     -3.0000     13.0000             12
# Capping
X_train_capped <- X_train
X_test_capped <- X_test

for (col in list_num) {

  batas <- outliers[outliers$Kolom == col, ]

  X_train_capped[[col]] <- Winsorize(
    X_train[[col]],
    val = c(batas$Lower_Bound, batas$Upper_Bound)
  )

  X_test_capped[[col]] <- Winsorize(
    X_test[[col]],
    val = c(batas$Lower_Bound, batas$Upper_Bound)
  )
}

# Membandingkan data sebelum dan sesudah capping
summary(X_train[list_num])
##       Suhu         Kelembapan     Kecepatan_Angin 
##  Min.   :22.60   Min.   : 52.00   Min.   : 2.000  
##  1st Qu.:24.32   1st Qu.: 75.00   1st Qu.: 3.000  
##  Median :26.00   Median : 86.00   Median : 3.000  
##  Mean   :26.56   Mean   : 83.76   Mean   : 5.098  
##  3rd Qu.:28.90   3rd Qu.: 94.00   3rd Qu.: 7.000  
##  Max.   :32.00   Max.   :100.00   Max.   :15.000
summary(X_train_capped[list_num])
##       Suhu         Kelembapan     Kecepatan_Angin 
##  Min.   :22.60   Min.   : 52.00   Min.   : 2.000  
##  1st Qu.:24.32   1st Qu.: 75.00   1st Qu.: 3.000  
##  Median :26.00   Median : 86.00   Median : 3.000  
##  Mean   :26.56   Mean   : 83.76   Mean   : 5.069  
##  3rd Qu.:28.90   3rd Qu.: 94.00   3rd Qu.: 7.000  
##  Max.   :32.00   Max.   :100.00   Max.   :13.000

Berdasarkan hasil tersebut, tidak ditemukan outlier pada variabel Suhu dan Kelembapan. Sebaliknya, terdapat 12 outlier pada variabel Kecepatan_Angin, yaitu nilai yang berada di luar rentang -3 hingga 13. Selanjutnya, dilakukan capping menggunakan metode Winsorization. Nilai yang melebihi batas atas atau kurang dari batas bawah diganti dengan nilai batas yang sesuai. Hasilnya, nilai maksimum Kecepatan_Angin turun dari 15 menjadi 13 dan rata-ratanya turun dari 5,098 menjadi 5,069. Sementara itu, nilai minimum dan maksimum variabel Suhu serta Kelembapan tidak berubah. Dengan demikian, capping berhasil membatasi nilai ekstrem pada Kecepatan_Angin tanpa menghapus observasi. Batas capping yang dihitung dari data latih juga diterapkan pada data uji agar proses preprocessing tetap konsisten.

4.6 Scalling Data

# Menyalin data setelah capping
X_train_scale <- X_train_capped
X_test_scale <- X_test_capped

# Menghitung mean dan standar deviasi data latih
mean_val <- sapply(
  X_train_capped[list_num],
  mean,
  na.rm = TRUE
)

sd_val <- sapply(
  X_train_capped[list_num],
  sd,
  na.rm = TRUE
)

# Standard Scaler pada data latih
for (col in list_num) {
  X_train_scale[[col]] <-
    (X_train_capped[[col]] - mean_val[col]) / sd_val[col]
}

# Standard Scaler pada data uji
for (col in list_num) {
  X_test_scale[[col]] <-
    (X_test_capped[[col]] - mean_val[col]) / sd_val[col]
}

# Melihat hasil scaling
summary(X_train_scale[list_num])
##       Suhu           Kelembapan      Kecepatan_Angin  
##  Min.   :-1.5477   Min.   :-2.7493   Min.   :-1.0273  
##  1st Qu.:-0.8732   1st Qu.:-0.7582   1st Qu.:-0.6926  
##  Median :-0.2182   Median : 0.1941   Median :-0.6926  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
##  3rd Qu.: 0.9159   3rd Qu.: 0.8867   3rd Qu.: 0.6464  
##  Max.   : 2.1281   Max.   : 1.4062   Max.   : 2.6548
summary(X_test_scale[list_num])
##       Suhu            Kelembapan       Kecepatan_Angin    
##  Min.   :-1.54772   Min.   :-2.48962   Min.   :-1.027332  
##  1st Qu.:-0.88295   1st Qu.:-0.75817   1st Qu.:-0.692589  
##  Median :-0.21817   Median : 0.28071   Median :-0.692589  
##  Mean   :-0.03314   Mean   : 0.05352   Mean   : 0.008347  
##  3rd Qu.: 0.75944   3rd Qu.: 0.88671   3rd Qu.: 0.646379  
##  Max.   : 1.97169   Max.   : 1.40615   Max.   : 2.654832
# Verifikasi data latih
sapply(X_train_scale[list_num], mean, na.rm = TRUE)
##            Suhu      Kelembapan Kecepatan_Angin 
##   -7.045562e-17    5.923146e-16   -7.005936e-17
sapply(X_train_scale[list_num], sd, na.rm = TRUE)
##            Suhu      Kelembapan Kecepatan_Angin 
##               1               1               1

Hasil scaling menunjukkan bahwa rata-rata variabel numerik pada data latih mendekati 0 dan standar deviasinya sebesar 1. Sementara itu, rata-rata dan standar deviasi pada data uji tidak harus sama karena menggunakan parameter dari data latih. Standard scaling bertujuan menyamakan skala variabel numerik agar proses pemodelan machine learning menjadi lebih optimal.

4.7 Encoding

# Menyamakan level kategori train dan test
all_levels <- levels(df_imp4$Keadaan_Cuaca_reduced)

X_train_scale$Keadaan_Cuaca_reduced <- factor(
  X_train_scale$Keadaan_Cuaca_reduced,
  levels = all_levels
)

X_test_scale$Keadaan_Cuaca_reduced <- factor(
  X_test_scale$Keadaan_Cuaca_reduced,
  levels = all_levels
)

# Membuat recipe encoding
resep_encode <- recipe(
  ~ .,
  data = X_train_scale
) %>%
  step_unknown(all_nominal_predictors()) %>%
  step_dummy(
    all_nominal_predictors(),
    one_hot = TRUE
  )

# Menyiapkan recipe berdasarkan data latih
resep_encode_prep <- prep(
  resep_encode,
  training = X_train_scale
)

# Encoding train dan test
X_train_encoded <- bake(
  resep_encode_prep,
  new_data = X_train_scale
)

X_test_encoded <- bake(
  resep_encode_prep,
  new_data = X_test_scale
)

# Melihat hasil encoding
head(X_train_encoded)
## # A tibble: 6 × 15
##      Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin Keadaan_Cuaca_reduced_X0
##     <dbl>      <dbl>         <dbl>           <dbl>                    <dbl>
## 1 -1.39        0.973             5          -0.693                        1
## 2 -1.00        0.540             1          -0.693                        1
## 3  0.0947     -0.585             1          -0.693                        1
## 4  1.19       -1.88              2          -1.03                         1
## 5  1.66       -2.40              1           0.646                        1
## 6  1.50       -2.32              3           1.32                         1
## # ℹ 10 more variables: Keadaan_Cuaca_reduced_X1 <dbl>,
## #   Keadaan_Cuaca_reduced_X2 <dbl>, Keadaan_Cuaca_reduced_X3 <dbl>,
## #   Keadaan_Cuaca_reduced_X4 <dbl>, Keadaan_Cuaca_reduced_X5 <dbl>,
## #   Keadaan_Cuaca_reduced_X6 <dbl>, Keadaan_Cuaca_reduced_X7 <dbl>,
## #   Keadaan_Cuaca_reduced_X8 <dbl>, Keadaan_Cuaca_reduced_X9 <dbl>,
## #   Keadaan_Cuaca_reduced_unknown <dbl>

Pada tahap ini, variabel Keadaan_Cuaca_reduced ditransformasikan menggunakan metode One-Hot Encoding menjadi beberapa kolom indikator, yaitu kategori X0 hingga X9 serta kategori unknown. Setiap kolom bernilai 1 jika observasi termasuk dalam kategori tersebut dan 0 jika tidak. Hasil encoding menghasilkan 15 kolom fitur yang terdiri dari variabel numerik dan variabel indikator. Transformasi ini bertujuan mengubah variabel kategorik menjadi bentuk numerik agar dapat digunakan dalam pemodelan machine learning.

4.8 Imbalanced Data

# Menggabungkan fitur dan target data latih
train_full <- X_train_encoded %>%
  mutate(Hujan = factor(y_train))

# Distribusi kelas sebelum SMOTE
table(train_full$Hujan)
## 
##   1   2 
## 131 463
# Membuat recipe SMOTE
set.seed(42)

resep_smote <- recipe(
  Hujan ~ .,
  data = train_full
) %>%
  step_smote(
    Hujan,
    over_ratio = 1,
    neighbors = 5
  )

# Menjalankan SMOTE
resep_smote_prep <- prep(
  resep_smote,
  training = train_full
)

train_balanced <- bake(
  resep_smote_prep,
  new_data = NULL
)

# Distribusi kelas setelah SMOTE
table(train_balanced$Hujan)
## 
##   1   2 
## 463 463

Sebelum SMOTE, kelas 1 berjumlah 131 observasi (22,05%), sedangkan kelas 2 berjumlah 463 observasi (77,95%), sehingga distribusi kelas tidak seimbang. Setelah SMOTE diterapkan, jumlah kelas 1 meningkat menjadi 463 observasi, sementara kelas 2 tetap 463 observasi. Dengan demikian, SMOTE berhasil menyeimbangkan distribusi kelas pada data latih dengan rasio 1:1, sehingga diharapkan model dapat mempelajari kedua kelas dengan lebih baik.

BAB V KESIMPULAN

5.1 Kesimpulan

Konsep berbagai jenis feature engineering pada RStudio dapat dipahami melalui proses pengolahan data, mulai dari penanganan missing value, pengurangan kardinalitas, pembagian data, penanganan outlier, scaling, encoding, hingga penanganan ketidakseimbangan kelas. Setiap tahapan memiliki tujuan berbeda, yaitu meningkatkan kualitas data, menyederhanakan representasi fitur, dan mempersiapkan data agar sesuai untuk pemodelan machine learning. Dengan memahami fungsi dan penerapan setiap tahapan, proses preprocessing dapat dilakukan secara tepat sehingga mendukung kinerja model dalam menghasilkan prediksi.

Teknik feature engineering di RStudio dilakukan dengan menggunakan berbagai fungsi dan package sesuai tahapan preprocessing yang diperlukan. Prosesnya meliputi penanganan missing value, pengurangan kardinalitas menggunakan fungsi cut(), pembagian data dengan stratified splitting, penanganan outlier menggunakan capping, scaling menggunakan Standard Scaler, transformasi variabel kategorik dengan One-Hot Encoding, serta penanganan ketidakseimbangan data menggunakan SMOTE. Hasil dari setiap tahapan diperiksa untuk memastikan data siap digunakan dalam pemodelan machine learning.

Berdasarkan hasil preprocessing data curah hujan, seluruh missing value berhasil ditangani, jumlah kategori pada variabel Keadaan_Cuaca berhasil dikurangi, dan pembagian data menghasilkan 594 data latih serta 149 data uji. Proses capping berhasil membatasi nilai ekstrem, Standard Scaling menyamakan skala variabel numerik, dan One-Hot Encoding mengubah variabel kategorik menjadi bentuk numerik. Selain itu, SMOTE berhasil menyeimbangkan jumlah kelas pada data latih dari 131 dan 463 observasi menjadi masing-masing 463 observasi sehingga data siap digunakan untuk tahap pemodelan machine learning.

DAFTAR PUSTAKA

Fransiska, H. (2026). Modul Praktikum Machine Learning dan Modern Prediction. Bengkulu: Universitas Bengkulu.

He, H., & Garcia, E. A. (2009). Learning from imbalanced data. IEEE Transactions on Knowledge and Data Engineering, 21(9), 1263-1284.

Sibaroni, K., & Fauzi, M. A. (2021). Feature Engineering pada Analisis Sentimen Kebijakan Merdeka Belajar Menggunakan Metode Naïve Bayes. Jurnal Teknologi Informasi dan Ilmu Komputer (JTIIK), 8(3), 545-552.

Utama, D. P., & Hartati, R. S. (2023). Perbandingan Metode Feature Scaling Min-Max Scaler dan Standard Scaler pada Algoritma K-Nearest Neighbor (KNN) untuk Klasifikasi Penyakit Jantung. Sinkron: Jurnal & Penelitian Teknik Informatika, 8(1), 116–123.