BAB I PENDAHULUAN

1.1 Latar Belakang

Perkembangan teknologi informasi menyebabkan jumlah data yang tersedia semakin meningkat dengan jenis dan sumber yang beragam. Ketersedian data dalam jumlah besar ini memberikan peluang untuk memperoleh informasi yang bermanfaat sebagai dasar pengambilan keputusan. Salah satu metode yang dapat digunakan untuk mengolah dan memanfaatkan data tersebut adalah machine learning. Machine learning adalah cabang dari kecerdasan buatan yang berfokus pada pengembangan algoritma dan model yang memungkinkan sistem untuk belajar dari data dan pengalaman tanpa perlu deprogram secara eksplisit. Ini melibatkan penggunaan teknik statistik dan matematis untuk mengidentifikasi pola dalam data dan membuat prediksi atau keputusan berdasarkan pola tersebut (Saputri, Firmansyah, & Purnomo, 2025).

Namun, kinerja model machine learning tidak hanya ditentukan oleh pemilihan algoritma, tetapi juga oleh kualitas dan representasi data yang digunakan. Data mentah umumnya tidak langsung siap dimodelkan. Data sering mengandung nilai yang hilang, pencilan (outlier), skala antarvariabel yang berbeda, variabel kategorik yang perlu dikodekan, serta variabel yang kurang relevan atau saling berkorelasi tinggi. Oleh karena itu diperlukan satu tahapan untuk mengatasi masalah tersebut, yaitu feature engineering (Ramdhan dkk., 2026).

Feature Engineering adalah proses membuat, mengubah, atau memilih atribut (fitur) dari dataset mentah untuk meningkatkan kinerja model pembelajaran mesin. Tujuannya adalah menambah informasi yang berguna, mengurangi noise, dan memfasilitasi algoritma belajar untuk menangkap pola data (Nurjaya, 2025). Salah satu software yang dapat membantu proses ini adalah RStudio. Software ini menawarkan banyak library yang memungkinkan penggunanya mengakses banyak fungsi dan kemudahan dalam melakukan proses Feature Engineering.

1.2 Rumusan Masalah

Berdasarkan latar belakang, rumusan masalah yang dapat disimpulkan adalah:

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

1.3 Tujuan

Adapun tujuan penelitian ini yaitu:

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

BAB II TINJAUAN PUSTAKA

2.1 Machine Learning

Machine learning didefinisikan sebagai sebuah tipe dari kecerdasan artifisial yang menyediakan komputer dengan kemampuan untuk belajar tanpa secara eksplisit diprogram. Machine learning berfokus pada pengembangan program-program komputer yang dapat mengajarkan dirinya sendiri untuk tumbuh dan berubah bila diberikan data baru. Tujuan machine learning adalah memprogram komputer untuk menggunakan data pelatihan atau pengalaman masa lalu untuk memecahkan masalah yang diberikan. Secara umum, machine learning dapat dikelompokkan ke tiga tipe, yaitu (Budiharto, Suhartono, & Andreas, 2025):

  1. Pembelajaran terawasi atau supervised learning, di mana data pelatihan terdiri dari pasangan data input dan output.
  2. Pembeljaran tak terawasi atau unsupervised learning, di mana pengguna hanya memberikan data input saja dan sistem yang akan mengklasifikasikan data tersebut.
  3. Reinforcement learning, yaitu dimaksudkan untuk membuat komputer dapat belajar sendiri dan berinteraksi dengan lingkungan melalui sebuah agent.

2.2 Feature Engineering

Feature Engineering adalah langkah-langkah untuk mengubah data mentah menjadi fitur-fitur yang dapat digunakan dalam algoritma machine learning. Selama proses feature engineering, variabel atau fitur yang paling berpengaruh dipilih dan direkayasa untuk pemodelan. Tujuan dari feature engineering adalah menyederhanakan dan mempercepat transformasi data sekaligus meningkatkan akurasi model. Berikut merupakan beberapa jenis feature engineering yang dapat dilakukan (Fransiska, 2026):

a. Handling Missing Value

Missing values atau missing data, terjadi ketika tidak ada data atau 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. Terdapat beberapa cara dalam penanganan missing value, antara lain (Setiawan dkk., 2023):

  1. Membuang record yang mengandung missing data, namun pembuangan record harus memiliki proporsi sangat kecil.
  2. Melakukan imputasi pada missing value. Di mana jika atribut bertipe numerik, maka dapat dilakukan imputasi menggunakan rata-rata atau median. Namun jika atribut bertipe kategori dapat dilakukan imputasi menggunakan modus.

b. Kardinalitas

Kardinalitas merujuk pada jumlah nilai unik, atau label, yang terdapat dalam suatu variabel kategoris. Konsep ini digunakan untuk mengukur keunikan data dalam sebuah fitur. Kardinalitas dapat diklasifikasikan dalam spektrum, namun umumnya dibedakan menjadi kardinalitas rendah dan kardinalitas tinggi. 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, 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. Spliting Data

Splitting data merupakan strategi fundamental dalam machine learning untuk membagi himpunan data menjadi bagian terpisah, yaitu 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 yang 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, 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 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. Berikut adalah formula standarisasi data menggunakan Z-Score Normalization (Valentino, Sipahutar, & Farhan, 2025):

\[ z_{ij} = \frac{x_{ij} - \bar{x}_j}{s_j} \] dengan:

  • \(z_{ij}\) : nilai terstandardisasi pengamatan ke-\(i\) pada variabel ke-\(j\)
  • \(x_{ij}\) : nilai asli pengamatan ke-\(i\) pada variabel ke-\(j\)
  • \(\bar{x}_j\) : rata-rata variabel ke-\(j\)
  • \(s_j\) : simpangan baku variabel ke-\(j\)

f. Encoding

Feature encoding adalah proses mengubah fitur kategoris atau non numerik menjadi format numerik yang dapat digunakan sebagai input untuk algoritma machine learning. Ada beberapa teknik umum untuk feature encoding, seperti One Hot Encoding dan Ordinal Encoding. One hot encoding adalah teknik representasi data kategorikal menjadi vektor biner di mana setiap kategori unik diwakili oleh sebuah kolom dengan nilai 1 pada kolom kategori yang benar dan 0 di kolom lainnya. Sementara, ordinal encoding adalah metode mengubah data kategorikal menjadi angka berdasarkan urutan atau ranking tertentu yang memiliki makna hierarkis (Irwanto, Nurjaya, & Kurniawan, 2025).

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.

BAB III METODE PENELITIAN

3.1 Jenis dan Sumber Data

Jenis data yang digunakan pada penelitian ini adalah data numerik dan data kategorik. Data yang digunakan terdiri atas variabel numerik berupa suhu, kelembapan, dan kecepatan angin, serta variabel kategorik berupa status hujan dan kode keadaan cuaca. Variabel numerik dinyatakan dalam bentuk angka sehingga dapat dianalisis secara statistik, sedangkan variabel kategorik menyatakan kelompok atau kelas dari suatu pengamatan.

Sumber data yang digunakan oleh penulis merupakan data sekunder. Data sekunder adalah sumber data yang diperoleh secara tidak langsung atau melalui media perantara. Data yang digunakan pada batasan masalah laporan ini diperoleh dari modul praktikum Machine Learning and Modern Prediction. Dataset tersebut terdiri atas 743 observasi dan 5 variabel.

3.2 Variabel Penelitian

Variabel penelitian adalah segala sesuatu yang akan menjadi objek penelitian. Pada batasan masalah, variabel yang digunakan terdiri atas lima variabel, yaitu Hujan, Suhu, Kelembapan, Keadaan Cuaca, dan Kecepatan Angin. Variabel Hujan menjadi variabel target dengan tipe kategorik yang memiliki dua kelas, yaitu 1 dan 2. Empat variabel lainnya berfungsi sebagai fitur, di mana Suhu, Kelembapan, dan Kecepatan Angin bertipe numerik, sedangkan Keadaan Cuaca bertipe kategorik yang direpresentasikan dalam bentuk kode angka.

3.3 Analisis Data

  1. Input data
  2. Pemeriksaan dan melakukan imputasi modus untuk data hilang
  3. Reduksi kardinalitas
  4. Stratified split data
  5. Capping untuk pencilan
  6. Penskalaan dengan Standard Scaler
  7. Pengodean dengan One-Hot Encoding
  8. Penyeimbangan kelas dengan SMOTE
  9. Output
  10. Interpretasi

BAB IV HASIL DAN PEMBAHASAN

4.1 Library dan Import Data

# Library
library(zoo)
library(readxl)
library(tidyverse)
library(rsample)
library(e1071)
library(DescTools)
library(dplyr)
library(ggplot2)
library(gridExtra)
library(recipes)
library(themis)
library(caret)

# Import Data
data <- read_excel("data curah hujan.xlsx")

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 ...

Pada tahap awal analisis ini adalah memuat semua library yang diperlukan, lalu mengimpor data curah hujan ke dalam RStudio. Package readxl dipakai untuk membaca file Excel, sementara tidyverse, dplyr, dan ggplot2 mendukung manipulasi serta visualisasi data. Untuk proses feature engineering dan pemodelan, rsample digunakan untuk membagi data, recipes untuk penskalaan dan pengodean, themis untuk menyeimbangkan kelas melalui SMOTE, serta caret dan e1071 untuk pemodelan dan evaluasi. Sementara itu, zoo, DescTools, dan gridExtra membantu pengolahan data dan penyajian grafik.

Fungsi head() dan str() kemudian dipakai untuk melihat isi dan struktur data. Di mana Hasil str() menunjukkan 743 pengamatan dan 5 variabel, yakni Hujan, Suhu, Kelembapan, Keadaan_Cuaca, dan Kecepatan_Angin. Seluruh variabel terbaca bertipe numerik. Tipe ini sesuai untuk Suhu, Kelembapan, dan Kecepatan_Angin, namun Hujan dan Keadaan_Cuaca merupakan variabel kategorik berkode angka sehingga perlu diubah menjadi factor. Selain itu, ditemukan nilai hilang (NA)pada Kecepatan_Angin, yang akan diperiksa dan ditangani pada tahap berikutnya.

4.2 Penanganan 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
# Lihat baris yang kosong di Keadaan_Cuaca
data %>% filter(is.na(Keadaan_Cuaca))
## # A tibble: 9 × 5
##   Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
##   <dbl> <dbl>      <dbl>         <dbl>           <dbl>
## 1     2  26           92            NA              NA
## 2     1  23.8         98            NA               5
## 3     1  23.3         97            NA              NA
## 4     2  28.8         79            NA              12
## 5     2  24.6         92            NA              NA
## 6     1  22.8         98            NA               4
## 7     2  25.5         96            NA              NA
## 8     2  27           80            NA               4
## 9     2  31           57            NA               6
# Penanganan Missing Value
df_imp <- data

# Interpolasi pada Keadaan_Cuaca
# rule = 2 agar NA di awal/akhir data tetap terisi
df_imp$Keadaan_Cuaca <- na.approx(df_imp$Keadaan_Cuaca, na.rm = FALSE, rule = 2)
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0             314
# Mode Imputation pada Kecepatan_Angin
mode_value <- Mode(df_imp$Kecepatan_Angin, na.rm = TRUE)[1]
mode_value
## [1] 3
df_imp$Kecepatan_Angin[is.na(df_imp$Kecepatan_Angin)] <- mode_value

# Verifikasi tidak ada missing value tersisa
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0               0

Hasil pemeriksaan menunjukkan bahwa dari 743 pengamatan, nilai hilang hanya terdapat pada dua variabel. Variabel Keadaan_Cuaca memiliki 9 nilai hilang, sedangkan Kecepatan_Angin memiliki 314 nilai hilang. Variabel Hujan, Suhu, dan Kelembapan lengkap tanpa nilai hilang. Nilai proporsinya yang sangat kecil, nilai hilang pada Keadaan_Cuaca ditangani dengan interpolasi (na.approx), yaitu mengisi nilai hilang berdasarkan nilai pengamatan di sekitarnya. Setelah interpolasi, jumlah nilai hilang pada variabel ini menjadi 0. Sementara itu, Kecepatan_Angin ditangani dengan imputasi modus sesuai dengan batasan masalah. Nilai modus yang diperoleh adalah 3, sehingga seluruh 314 nilai hilang diisi dengan angka tersebut. Hasil akhir menunjukkan bahwa tidak ada lagi nilai hilang pada seluruh variabel, sehingga data siap diproses ke tahap berikutnya.

4.3 Kardinalitas

head(df_imp, 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_imp$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
# Tentukan batas bin
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

# Tentukan label untuk setiap bin (10 label: 0 s/d 9)
labels <- 0:9

# Terapkan cut()
df_imp$Keadaan_Cuaca_reduced <- cut(
  df_imp$Keadaan_Cuaca,
  breaks = bins,
  labels = labels,
  right = TRUE,            # interval (a, b]
  include.lowest = TRUE    # nilai batas paling bawah (0) tetap terhitung
)

# Verifikasi
cat("--- Hasil Perbandingan ---\n")
## --- Hasil Perbandingan ---
print(df_imp[sample(nrow(df_imp), 10), ])
## # A tibble: 10 × 6
##    Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin Keadaan_Cuaca_reduced
##    <dbl> <dbl>      <dbl>         <dbl>           <dbl> <fct>                
##  1     2  24.8         92             5               3 0                    
##  2     2  27.2         89             2               3 0                    
##  3     2  25.3         90             2               3 0                    
##  4     2  25.6         79             2               4 0                    
##  5     2  26.2         92             2               3 0                    
##  6     2  30           74             2              12 0                    
##  7     2  25.1         95            61               3 6                    
##  8     1  27.2         77             2               4 0                    
##  9     1  29.8         72             2               3 0                    
## 10     2  31           71             1              15 0
cat("\n--- Pengecekan Kardinalitas ---\n")
## 
## --- Pengecekan Kardinalitas ---
cat('Jumlah kategori di "Keadaan_Cuaca" asli    :', length(unique(df_imp$Keadaan_Cuaca)), "\n")
## Jumlah kategori di "Keadaan_Cuaca" asli    : 23
cat('Jumlah kategori di "Keadaan_Cuaca_reduced" :', length(unique(df_imp$Keadaan_Cuaca_reduced)), "\n")
## Jumlah kategori di "Keadaan_Cuaca_reduced" : 7
cat("\nKategori unik yang baru (reduced):\n")
## 
## Kategori unik yang baru (reduced):
print(unique(df_imp$Keadaan_Cuaca_reduced))
## [1] 0 1 5 6 2 9 4
## Levels: 0 1 2 3 4 5 6 7 8 9

Kardinalitas adalah banyaknya kategori unik pada suatu variabel. Hasil interpolasi membuat variabel Keadaan_Cuaca bernilai sangat beragam, yaitu 23 kategori unik dengan rentang kode dari 1 sampai 97, termasuk nilai pecahan 1,5 yang muncul dari proses interpolasi. Kardinalitas yang tinggi ini menyulitkan tahap pengodean. Untuk mengatasinya, dilakukan reduksi kardinalitas dengan teknik binning menggunakan fungsi cut(). Nilai Keadaan_Cuaca dikelompokkan ke dalam 10 interval dengan lebar masing-masing 10, berformat (a, b], lalu diberi label 0 sampai 9. Argumen include.lowest = TRUE memastikan nilai batas bawah, yaitu 0, tetap masuk ke interval pertama. Hasilnya disimpan sebagai variabel baru, Keadaan_Cuaca_reduced.

Setelah reduksi, jumlah kategori turun dari 23 menjadi 7, yaitu kategori 0, 1, 2, 4, 5, 6, dan 9. Kategori 3, 7, dan 8 tidak muncul karena tidak ada pengamatan pada rentang tersebut. Kategori 0 mendominasi karena kode asli 1, 2, dan 3 paling sering muncul pada data. Variabel hasil reduksi bertipe factor dengan 10 level, sehingga seluruh level tetap tersimpan meskipun sebagian tidak terisi. Hal ini menjaga konsistensi kategori antara data latih dan data uji saat pengodean.

4.4 Splitting Data

# Splitting Data (Stratify)
set.seed(46)
split_stratify <- initial_split(df_imp, prop = 0.8, strata = Hujan)

X_train <- training(split_stratify) %>% select(-Hujan)
X_test  <- testing(split_stratify)  %>% select(-Hujan)
y_train <- training(split_stratify)$Hujan
y_test  <- testing(split_stratify)$Hujan

dim(X_train)
## [1] 594   5
dim(X_test)
## [1] 149   5
# Cek proporsi kelas pada data latih dan data uji
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

Tahap selanjutnya, data dibagi menjadi data latih dan data uji dengan perbandingan 80:20 menggunakan fungsi initial_split(). Pembagian dilakukan secara stratified di mana variabel Hujan dipisahkan sebagai target ke dalam objek y_train dan y_test.

Hasil menunjukkan bahwa data latih terdiri atas 594 pengamatan dan data uji 149 pengamatan. Pada data latih, kelas 1 berjumlah 22,05% dan 22,15% pada data uji, sedangkan kelas 2 berjumlah 77,95% pada data latih dan 77,85% pada data uji. Proporsi pada kedua bagian hampir sama, sehingga stratified split berjalan dengan baik. Data juga tergolong tidak seimbang, karena kelas 2 jauh lebih banyak daripada kelas 1. Hal ini menjadi alasan perlunya penyeimbangan data dengan SMOTE pada tahap berikutnya.

4.5 Handling Outlier

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

# Hitung batas IQR untuk setiap kolom (berdasarkan data latih)
list_outlier     <- c()
list_lower_bound <- c()
list_upper_bound <- c()

for (i in list_num) {
  Q1      <- quantile(X_train[[i]], 0.25, na.rm = TRUE)
  Q3      <- quantile(X_train[[i]], 0.75, na.rm = TRUE)
  IQR_val <- Q3 - Q1

  lower_bound <- Q1 - 1.5 * IQR_val
  upper_bound <- Q3 + 1.5 * IQR_val

  list_lower_bound <- c(list_lower_bound, lower_bound)
  list_upper_bound <- c(list_upper_bound, upper_bound)

  num_outliers_lower <- sum(X_train[[i]] < lower_bound, na.rm = TRUE)
  num_outliers_upper <- sum(X_train[[i]] > upper_bound, na.rm = TRUE)

  list_outlier <- c(list_outlier, num_outliers_lower + num_outliers_upper)
}

outliers <- data.frame(
  Kolom          = list_num,
  Jumlah_Outlier = list_outlier,
  Lower_Bound    = list_lower_bound,
  Upper_Bound    = list_upper_bound
)

outliers
##             Kolom Jumlah_Outlier Lower_Bound Upper_Bound
## 1            Suhu              0        17.5        35.9
## 2      Kelembapan              0        44.0       124.0
## 3 Kecepatan_Angin              5        -3.0        13.0

Berdasarkan hasil pemeriksaan outlier, variabel Suhu dan Kelembapan masing-masing memiliki jumlah outlier sebanyak 0, sehingga tidak ditemukan pengamatan yang berada di luar batas IQR. Variabel Suhu memiliki batas bawah sebesar 17,5 dan batas atas sebesar 35,9, sedangkan variabel Kelembapan memiliki batas bawah sebesar 44 dan batas atas sebesar 124. Sementara itu, variabel Kecepatan_Angin memiliki 5 outlier, dengan batas bawah sebesar -3 dan batas atas sebesar 13. Oleh karena itu, penanganan outlier melalui capping dilakukan pada variabel Kecepatan_Angin, yaitu dengan membatasi nilai yang melebihi batas atas menjadi 13. Adapun batas bawah -3 tidak menjadi masalah apabila seluruh nilai kecepatan angin dalam data berada di atas batas tersebut.

# Capping (Winsorize) untuk setiap fitur numerik
# Batas dihitung dari data latih, lalu diterapkan ke data latih dan data uji
X_train_capped <- X_train
X_test_capped  <- X_test

for (i in list_num) {
  batas <- outliers %>% filter(Kolom == i)
  lower <- batas$Lower_Bound
  upper <- batas$Upper_Bound

  X_train_capped[[i]] <- Winsorize(X_train[[i]], val = c(lower, upper))
  X_test_capped[[i]]  <- Winsorize(X_test[[i]],  val = c(lower, upper))
}

# Fungsi plot diagnostik
diagnostic_plots <- function(df, variable) {

  p1 <- ggplot(df, aes(x = .data[[variable]])) +
    geom_histogram(bins = 30, fill = "#7FDBB6", color = "black") +
    ggtitle("Histogram") +
    theme_minimal()

  p2 <- ggplot(df, aes(y = .data[[variable]])) +
    geom_boxplot(fill = "#7FDBB6") +
    ggtitle("Boxplot") +
    theme(axis.text.x = element_blank(),  
          axis.ticks.x = element_blank())

  grid.arrange(p1, p2, ncol = 2)
}
diagnostic_plots(X_train, "Suhu")
Gambar 4.1 Histogram dan boxplot variabel Suhu sebelum capping

Gambar 4.1 Histogram dan boxplot variabel Suhu sebelum capping

diagnostic_plots(X_train_capped, "Suhu")
Gambar 4.2 Histogram dan boxplot variabel Suhu setelah capping

Gambar 4.2 Histogram dan boxplot variabel Suhu setelah capping

diagnostic_plots(X_train, "Kelembapan")
Gambar 4.3 Histogram dan boxplot variabel Kelembapan sebelum capping

Gambar 4.3 Histogram dan boxplot variabel Kelembapan sebelum capping

diagnostic_plots(X_train_capped, "Kelembapan")
Gambar 4.4 Histogram dan boxplot variabel Kelembapan setelah capping

Gambar 4.4 Histogram dan boxplot variabel Kelembapan setelah capping

diagnostic_plots(X_train, "Kecepatan_Angin")
Gambar 4.5 Histogram dan boxplot variabel Kecepatan_Angin sebelum capping

Gambar 4.5 Histogram dan boxplot variabel Kecepatan_Angin sebelum capping

diagnostic_plots(X_train_capped, "Kecepatan_Angin")
Gambar 4.6 Histogram dan boxplot variabel Kecepatan_Angin setelah capping

Gambar 4.6 Histogram dan boxplot variabel Kecepatan_Angin setelah capping

Berdasarkan Gambar 4.1, variabel Suhu tidak menunjukkan adanya outlier, dengan nilai berkisar antara 22,5 hingga 31,5 °C dan median sekitar 26 °C. Hal serupa ditemukan pada variabel Kelembapan(Gambar 4.3), yang memiliki nilai berkisar antara 52 hingga 100 dan median sekitar 86. Histogram variabel ini menunjukkan bahwa sebagian besar pengamatan terkonsentrasi pada nilai tinggi, terutama sekitar 96–97, sehingga distribusinya cenderung miring ke kiri. Karena tidak terdapat nilai yang melewati batas outlier berdasarkan metode IQR, kedua variabel tersebut tidak mengalami perubahan setelah capping, sebagaimana ditunjukkan pada Gambar 4.2 dan Gambar 4.4.

Berbeda dengan kedua variabel tersebut, Kecepatan_Angin memiliki 5 outlier, dengan batas bawah sebesar -3 dan batas atas sebesar 13. Pada Gambar 4.5, nilai yang berada di atas batas atas teridentifikasi sebagai outlier. Setelah capping (Gambar 4.6), nilai yang melebihi batas atas dibatasi menjadi 13. Sementara itu, histogram menunjukkan bahwa nilai 3 merupakan nilai yang paling sering muncul, dengan frekuensi sekitar 290 pengamatan.

Secara keseluruhan, capping hanya diterapkan pada variabel Kecepatan_Angin karena memiliki nilai yang melewati batas IQR. Penanganan ini membatasi nilai ekstrem tanpa mengurangi jumlah pengamatan dalam data latih.

4.6 Scaling Data

# Standard Scaler
mean_val <- sapply(X_train_capped[list_num], mean, na.rm = TRUE)
sd_val   <- sapply(X_train_capped[list_num], sd,   na.rm = TRUE)

X_train_scale <- X_train_capped
X_test_scale  <- X_test_capped

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

# transform pada data uji (memakai parameter data latih)
for (col in list_num) {
  X_test_scale[[col]] <- (X_test_capped[[col]] - mean_val[col]) / sd_val[col]
}

# Verifikasi: mean data latih ~ 0 dan sd ~ 1
round(sapply(X_train_scale[list_num], mean), 4)
##            Suhu      Kelembapan Kecepatan_Angin 
##               0               0               0
round(sapply(X_train_scale[list_num], sd), 4)
##            Suhu      Kelembapan Kecepatan_Angin 
##               1               1               1

Selanjutnya, dilakukan standardisasi data menggunakan metode Standard Scaler pada variabel numerik, yaitu Suhu, Kelembapan, dan Kecepatan_Angin. Proses ini dilakukan dengan mengurangi setiap nilai dengan rata-rata (mean) dan membaginya dengan simpangan baku (standard deviation) yang dihitung berdasarkan data latih. Parameter tersebut kemudian digunakan untuk mentransformasikan data latih dan data uji agar proses standardisasi tetap konsisten tanpa menyebabkan kebocoran informasi (data leakage). Hasil verifikasi menunjukkan bahwa ketiga variabel pada data latih memiliki rata-rata sebesar 0 dan simpangan baku sebesar 1. Hal ini menunjukkan bahwa proses standardisasi telah berhasil dilakukan. Setelah standardisasi, nilai setiap variabel menunjukkan posisi relatifnya terhadap rata-rata data latih, sehingga perbedaan skala antarvariabel dapat dikurangi dan data siap digunakan pada tahap pemodelan.

4.7 Encoding

# One Hot Encoder
list_cat   <- c("Keadaan_Cuaca_reduced")
all_levels <- levels(df_imp$Keadaan_Cuaca_reduced)

# Samakan level kategori pada data latih dan data uji
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)

# Buat resep encoding (fit dari data latih)
resep_encode <- recipe(~ ., data = X_train_scale[, c(list_num, list_cat)]) %>%
  step_unknown(all_of(list_cat)) %>%
  step_dummy(all_of(list_cat), one_hot = TRUE)

resep_encode_prep <- prep(resep_encode, training = X_train_scale[, c(list_num, list_cat)])

# Terapkan encoding (fit_transform pada data latih, transform pada data uji)
X_train_encoded <- bake(resep_encode_prep, new_data = X_train_scale[, c(list_num, list_cat)])
X_test_encoded  <- bake(resep_encode_prep, new_data = X_test_scale[, c(list_num, list_cat)])

head(X_train_encoded)
## # A tibble: 6 × 14
##      Suhu Kelembapan Kecepatan_Angin Keadaan_Cuaca_reduced_X0
##     <dbl>      <dbl>           <dbl>                    <dbl>
## 1 -1.39       0.963           -0.701                        1
## 2  0.0906    -0.581           -0.701                        1
## 3  1.18      -1.87            -1.04                         1
## 4  1.73      -2.47             0.654                        1
## 5  1.49      -2.30             1.33                         1
## 6 -0.143     -0.0660          -0.701                        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>
dim(X_train_encoded)
## [1] 594  14
dim(X_test_encoded)
## [1] 149  14

Tahap selanjutnya adalah melakukan encoding pada variabel kategorik Keadaan_Cuaca_reduced menggunakan metode One-Hot Encoding. Proses ini mengubah setiap kategori cuaca menjadi kolom indikator bernilai 0 dan 1 agar dapat digunakan dalam pemodelan machine learning. Sebelum encoding dilakukan, level kategori pada data latih dan data uji diseragamkan untuk menjaga konsistensi representasi kategori. Proses encoding menggunakan recipe dari paket recipes, dengan parameter yang disiapkan berdasarkan data latih dan kemudian diterapkan pada data latih maupun data uji. Hasilnya menunjukkan bahwa data latih memiliki 594 pengamatan dan 14 variabel, sedangkan data uji memiliki 149 pengamatan dan 14 variabel. Kesamaan jumlah kolom menunjukkan bahwa kedua data memiliki struktur variabel yang konsisten setelah proses encoding, sehingga dapat digunakan pada tahap pemodelan selanjutnya.

4.8 Balancing Data (SMOTE)

# Distribusi kelas sebelum SMOTE
table(y_train)
## y_train
##   1   2 
## 131 463
prop.table(table(y_train))
## y_train
##         1         2 
## 0.2205387 0.7794613
# Gabungkan fitur dan target (SMOTE membutuhkan target bertipe factor)
train_full <- X_train_encoded %>%
  mutate(Hujan = factor(y_train))

set.seed(46)

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

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
prop.table(table(train_balanced$Hujan))
## 
##   1   2 
## 0.5 0.5
dim(train_balanced)
## [1] 926  15
# Data uji tidak di-SMOTE, hanya disiapkan targetnya
test_final <- X_test_encoded %>%
  mutate(Hujan = factor(y_test, levels = levels(train_full$Hujan)))
test_final
## # A tibble: 149 × 15
##       Suhu Kelembapan Kecepatan_Angin Keadaan_Cuaca_reduced_X0
##      <dbl>      <dbl>           <dbl>                    <dbl>
##  1 -1.00       0.535           -0.701                        1
##  2  1.65      -2.38             0.654                        1
##  3 -0.0262     0.0198          -0.701                        1
##  4 -0.611      0.449           -0.701                        1
##  5  0.792     -1.27            -1.04                         1
##  6 -0.104      0.620           -0.701                        1
##  7 -0.221      0.706           -0.701                        1
##  8 -0.650      1.22            -0.701                        0
##  9  0.246      0.106           -1.04                         1
## 10  1.18      -0.838            0.654                        1
## # ℹ 139 more rows
## # ℹ 11 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>, Hujan <fct>

Sebelum dilakukan SMOTE, distribusi kelas pada data latih menunjukkan ketidakseimbangan. Kelas 1 sebagai kelas minoritas berjumlah 131 observasi (22,05%), sedangkan kelas 2 sebagai kelas mayoritas berjumlah 463 observasi (77,95%), dari total 594 observasi. Kondisi ini dapat menyebabkan model cenderung lebih mengenali kelas mayoritas dibandingkan kelas minoritas.

Untuk mengatasi ketidakseimbangan tersebut, diterapkan metode Synthetic Minority Over-sampling Technique (SMOTE) dengan parameter over_ratio = 1 dan neighbors = 5. Metode ini membangkitkan observasi sintetis pada kelas minoritas berdasarkan lima tetangga terdekatnya. Penggunaan set.seed(46) bertujuan agar proses pembangkitan data dapat direproduksi.

Setelah dilakukan SMOTE, jumlah observasi pada kelas 1 dan kelas 2 masing-masing menjadi 463, dengan proporsi sebesar 50% untuk setiap kelas. Sebanyak 332 observasi sintetis ditambahkan sehingga jumlah data latih meningkat dari 594 menjadi 926 observasi. Data hasil SMOTE terdiri atas 14 fitur dan satu variabel target, yaitu Hujan.

SMOTE hanya diterapkan pada data latih, sedangkan data uji tidak mengalami penyeimbangan kelas. Variabel target Hujan pada data uji hanya dikonversi menjadi tipe factor dengan level yang disesuaikan dengan data latih. Dengan demikian, data latih dan data uji siap digunakan untuk pemodelan.

BAB V PENUTUP

5.1 Kesimpulan

Feature engineering merupakan proses pengolahan data untuk meningkatkan kualitas dan kesesuaian fitur sebelum digunakan dalam pemodelan machine learning. Teknik yang dapat digunakan meliputi penanganan nilai hilang, pencilan (outlier), standardisasi (scaling), pengubahan variabel kategorik (encoding), serta penanganan ketidakseimbangan kelas. Pemilihan teknik tersebut disesuaikan dengan karakteristik dan permasalahan yang ditemukan pada data.

Penerapan feature engineering di RStudio dapat dilakukan menggunakan bahasa pemrograman R dengan bantuan berbagai paket, seperti dplyr dan recipes. Setiap teknik diterapkan sesuai kebutuhan, misalnya capping untuk membatasi nilai ekstrem, Standard Scaler untuk menyamakan skala variabel numerik, One-Hot Encoding untuk mengubah variabel kategorik menjadi numerik, dan SMOTE untuk menyeimbangkan kelas. Hasil setiap tahapan perlu diperiksa untuk memastikan pengolahan data berjalan dengan tepat dan menghindari kebocoran informasi (data leakage).

Berdasarkan hasil analisis, proses feature engineering yang dilakukan meliputi capping, standardisasi, encoding, dan SMOTE. Hasilnya menunjukkan bahwa data berhasil disiapkan melalui pembatasan nilai ekstrem, standardisasi variabel numerik, transformasi variabel kategorik menjadi 14 fitur, serta penyeimbangan kelas data latih menjadi masing-masing 463 observasi. Oleh karena itu, data telah siap digunakan untuk tahap pemodelan machine learning, dengan data uji tetap dipertahankan tanpa proses SMOTE agar evaluasi model lebih representatif.

5.2 Saran

Dalam melakukan pengolahan data menggunakan RStudio, diperlukan ketelitian dalam menuliskan sintaks dan menjalankan program agar dapat meminimalkan kesalahan serta menghasilkan output yang sesuai. Selain itu, diperlukan pemahaman terhadap konsep dan tahapan analisis agar setiap proses yang dilakukan dapat diinterpretasikan dengan tepat. Penulisan laporan juga perlu memperhatikan kaidah KBBI, penggunaan huruf tebal, dan format penulisan yang konsisten agar laporan tersusun dengan baik dan mudah dipahami.

DAFTAR PUSTAKA

Budiharto, W., Suhartono, D., & Andreas, V. (2025). Deep Learning Konsep dan Penerapannya. Yogykarta: Penerbit ANDI.

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

Irwanto, D., Nurjaya, & Kurniawan, Y. (2025). Langkah Mudah Membangun Model Machine Learning. Purbalingga: Eureka Media Aksara.

Nurjaya. (2025). Fundamental Machine Learning. Purbalingga: Eureka Media Aksara.

Ramdhan, W., Trisnawan, A. B., Pratama, A., Nugroho, H., Messe, F. E., Sadli, A., . . . Yel, M. B. (2026). Machine Learning Terapan: Prediksi Bisnis dan Marketing Intelligence. Jambi: Faaslib Serambi Media.

Saputri, T. A., Firmansyah, A. U., & Purnomo, H. (2025). Menguasai Teknik Dasar Machine Learning. Banyumas: Wawasan Ilmu.

Setiawan, Z., Fajar, M., Priyatno, A. M., Putri, A. Y., Aryuni, M., Yuliyanti, S., . . . Wijaya, A. (2023). Buku Ajar Data Mining. Jambi: Sonpedia Publishing Indonesia.

Valentino, M., Sipahutar, Y., & Farhan, M. (2025). Pengelompokan Negara Berdasarkan Indikator Pembangunan Global Menggunakan Metode PCA dan Clustering K-Means Tahun 2000-2020. Jurnal Ilmu Komputer dan Sistem Informasi, 1-16.