PENDAHULUAN

1.1 Latar Belakang

Perkembangan teknologi informasi telah mendorong peningkatan penggunaan data dalam berbagai bidang, sehingga diperlukan teknik pengolahan data yang tepat untuk menghasilkan informasi yang bermanfaat. Dalam analisis data dan pembelajaran mesin (machine learning), kualitas data serta pemilihan variabel yang digunakan memiliki peran penting dalam menentukan kinerja model. Data yang diperoleh dari berbagai sumber sering kali belum siap digunakan secara langsung karena mengandung nilai yang hilang, format yang tidak sesuai, atau variabel yang belum merepresentasikan informasi secara optimal. Oleh karena itu, diperlukan tahapan pengolahan dan pembentukan fitur untuk meningkatkan kualitas data sebelum dilakukan analisis lebih lanjut.

Salah satu tahapan penting dalam proses tersebut adalah feature engineering, feature engineering adalah proses menggunakan pengetahuan domain untuk mengekstrak atau membuat fitur-fitur baru dari data mentah (Darmawan et al., 2024). Teknik feature engineering dapat mencakup penanganan nilai yang hilang, pengodean variabel kategorik (encoding), normalisasi dan standardisasi, transformasi variabel, pembentukan fitur baru (feature creation), serta seleksi fitur (feature selection). Pemilihan teknik yang tepat perlu disesuaikan dengan karakteristik data dan tujuan analisis karena fitur yang relevan dapat membantu model mengenali pola dalam data secara lebih efektif.

Salah satu perangkat lunak yang dapat digunakan untuk menerapkan teknik feature engineering adalah RStudio, yaitu lingkungan pengembangan yang mendukung penggunaan bahasa pemrograman R untuk pengolahan, analisis, dan visualisasi data. Melalui RStudio, pengguna dapat memanfaatkan berbagai fungsi dan paket, seperti dplyr untuk manipulasi data, tidyr untuk penataan data, serta recipes untuk menyusun tahapan prapemrosesan fitur secara sistematis. Penggunaan perangkat tersebut memungkinkan proses pembentukan dan transformasi fitur dilakukan secara terstruktur, sehingga data dapat dipersiapkan sebelum digunakan dalam analisis statistik maupun pemodelan machine learning.

1.2 Rumusan Masalah*

Berdasarkan latar belakang di atas, adapun rumusan masalah yang dapat disimpulkan sebagai berikut: 1.Bagaimana konsep dari berbagai jenis feature engineering yang dapat diterapkan pada RStudio? 2.Bagaimana penerapan teknik feature engineering menggunakan 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 Feature Engineering

Feature engineering adalah tahap penting dalam pengembangan model prediktif, yang melibatkan transformasi variabel-variabel data menjadi bentuk yang lebih representatif untuk meningkatkan kinerja model (Herdian et al., 2024). Tahap feature engineering dilakukan untuk mengekstraksi pola kritis dari data proses. Feature egineering dirancang berdasarkan hubungan fisik antar variabel dan potensi mekanisme. Pendekatan ini didukung oleh penelitian terbaru yang menunjukkan bahwa teknik feature engineering dapat meningkatkan kinerja model prediksi secara signifikan (Winata et al., 2026).

2.2 Jenis dan data feature

Data dapat dikelompokkan menjadi data numerik dan data kategorik. Data numerik terdiri atas data numerik diskrit dan kontinu, sedangkan data kategorik terdiri atas data kategorik nominal dan ordinal. Data numerik diskrit merupakan data yang nilainya berupa bilangan bulat dan terpisah, sedangkan data numerik kontinu merupakan data yang nilainya berada dalam suatu rentang tertentu. Data kategorik nominal merupakan data yang tidak memiliki urutan, sedangkan data kategorik ordinal merupakan data yang memiliki tingkatan atau urutan tertentu (Fransiska, 2026).

Kardinalitas merujuk pada jumlah nilai unik atau label yang terdapat dalam suatu variabel kategorik yang dapat diklasifikasikan menjadi kardinalitas rendah (low cardinality) dan kardinalitas tinggi (high cardinality). Variabel dengan kardinalitas tinggi dapat menyebabkan curse of dimensionality jika ditransformasi menggunakan metode encoding standar seperti One-Hot Encoding, karena metode ini akan menciptakan banyak fitur biner baru sesuai jumlah label. Kardinalitas juga secara signifikan meningkatkan risiko overfitting karena banyak label mungkin hanya muncul beberapa kali dalam set data training (Fransiska, 2026).

2.3 Teknik Feature Engineering

1. Missing Value Handling Penanganan nilai yang hilang merupakan proses mengatasi data yang tidak memiliki nilai pada variabel tertentu. Nilai yang hilang dapat ditangani dengan menghapus observasi tertentu atau mengganti nilai yang hilang menggunakan metode imputasi, seperti rata-rata (mean), median, atau modus. Pemilihan metode harus mempertimbangkan jenis variabel dan karakteristik data agar tidak menimbulkan bias pada hasil analisis (Hr et al., 2022).

2. Normalisasi dan Standardisasi Normalisasi dan standardisasi merupakan teknik transformasi untuk menyamakan atau menyesuaikan skala variabel numerik. Normalisasi Min-Max mengubah nilai ke rentang tertentu, umumnya 0 sampai 1, sedangkan standardisasi Z-score mengubah data berdasarkan rata-rata dan simpangan baku. Kedua teknik ini penting bagi algoritma yang menggunakan perhitungan jarak, seperti KNN, karena perbedaan skala variabel dapat memengaruhi hasil pemodelan (Hadi et al., 2024).

3. Min-Max Scaling Min-Max Scaling merupakan salah satu teknik scaling data yang digunakan dalam feature engineering. Min-Max Scaling mengubah distribusi data sehingga nilai-nilai berada dalam rentang tertentu, biasanya antara 0 dan 1. Teknik ini berbeda dengan Robust Scaling dan Standard Scaling yang juga digunakan untuk menormalkan data dengan pendekatan yang berbeda (Fransiska, 2026).

4. Label Encoding Label Encoding merupakan teknik feature encoding yang mengubah fitur kategoris atau non-numerik menjadi format numerik yang dapat digunakan sebagai input untuk algoritma machine learning. Label encoder digunakan agar tidak menambah jumlah fitur pada data, berbeda dengan One-Hot Encoding yang akan menambah jumlah fitur sesuai dengan jumlah kategori (Fauzi et al.., 2025). Feature encoding diperlukan karena banyak algoritma machine learning membutuhkan input numerik (Fransiska, 2026).

5. One-Hot Encoding One-Hot Encoding dalam pemrosesan data dan machine learning adalah metode yang digunakan untuk merepresentasikan variabel kategorikal sebagai vektor biner. Setiap kategori atau label dalam metode encoding ini diubah menjadi vektor biner dengan panjang yang sama dengan jumlah total kategori yang berbeda dalam variabel tersebut, di mana semua nilai vektor adalah nol kecuali indeks yang sesuai dengan kategori yang ditandai dengan angka 1. One-Hot Encoding dapat menghasilkan ruang fitur berdimensi tinggi, terutama pada dataset dengan banyak kategori, sehingga perlu pertimbangan hati-hati untuk menyeimbangkan keuntungan representasi dengan kemungkinan peningkatan kompleksitas komputasi (Herdian et al.., 2024).

6. Diskretisasi atau Binning Diskretisasi atau binning merupakan teknik feature engineering yang mengubah data kontinu menjadi data interval (Herdian et al., 2024). Diskretisasi dilakukan dengan membagi rentang nilai kontinu menjadi beberapa interval atau bin berdasarkan kriteria tertentu. Transformasi ini bertujuan untuk menyederhanakan data dan memberikan informasi yang lebih eksplisit kepada model mengenai kategori nilai tertentu (Darmawan et al.., 2026).

7. Feature Creation Feature creation merupakan proses menciptakan fitur-fitur baru yang lebih representatif dari data yang ada. Feature engineering dilakukan untuk membuat fitur baru seperti rasio antara dua variabel, jarak, dan variabel turunan lainnya yang dapat meningkatkan representasi data (Sihombing, 2024). Fitur turunan dibuat sebagai bagian dari strategi feature engineering yang menggabungkan berbagai informasi dari data mentah. Feature creation juga mencakup pembuatan fitur interaksi untuk meningkatkan representasi data (Darmawan et al.., 2026).

8. Feature Selection Seleksi fitur merupakan proses pemilihan fitur yang tepat dalam proses klasifikasi, dengan tujuan untuk mengurangi tingkat kompleksitas dan meningkatkan akurasi dari suatu algoritma klasifikasi serta mampu mengetahui fitur-fitur apa saja yang paling berkontribusi terhadap tingkat akurasi (Budianita, 2023). Information gain adalah metode seleksi fitur dengan memberikan bobot setiap fitur berdasarkan kelas tertentu dengan memaksimalkan nilai entropy (Putri et al.., 2023).

2.4 PACKAGE DAN FUNGSI R UNTUK FEATURE ENGINEERING

Proses pemodelan machine learning dalam RStudio didukung oleh berbagai package yang menyediakan fungsi untuk setiap tahapan analisis data. Package tidyverse digunakan untuk memanipulasi data melalui fungsi drop_na(), fill(), dan is.na() untuk menangani missing value, sedangkan package zoo menyediakan fungsi na.approx() untuk interpolasi data yang hilang. Package rsample menyediakan fungsi initial_split() dan initial_time_split() untuk membagi data, package DescTools menyediakan fungsi Winsorize(), quantile(), dan IQR() untuk menangani outlier, serta package e1071 menyediakan fungsi skewness() untuk mengukur kemencengan distribusi data. Package recipes dan themis digunakan untuk melakukan encoding dan penyeimbangan data melalui fungsi step_dummy() dan step_smote(), sementara package dplyr menyediakan fungsi mutate(), filter(), dan select() untuk manipulasi data. Package ggplot2 dan gridExtra digunakan untuk visualisasi distribusi data, dan package caret digunakan untuk mendukung proses pemodelan dan evaluasi (Fransiska, 2026).

BAB III METODE PENELITIAN

3.1 Jenis dan Sumber Data

Jenis data yang digunakan pada penelitian ini adalah data numerik dan data kategorik. Data numerik merupakan data berbentuk angka yang dapat dianalisis secara statistik, yaitu suhu, kelembapan, dan kecepatan angin. Data kategorik merupakan data yang menyatakan kelompok atau kelas suatu pengamatan, yaitu status hujan dan kode keadaan cuaca.

Sumber data yang digunakan dalam penelitian ini adalah data sekunder. Data sekunder merupakan data yang telah dikumpulkan dan diolah terlebih dahulu oleh pihak lain. Data curah hujan diperoleh dari modul praktikum Machine Learning and Modern Prediction. Dataset tersebut terdiri atas 743 observasi dan 5 variabel.

3.2 Variabel Penelitian

Variabel merupakan karakteristik atau atribut yang dapat diukur maupun diamati dalam suatu penelitian. Penelitian ini menggunakan lima variabel, yaitu Hujan, Suhu, Kelembapan, Keadaan Cuaca, dan Kecepatan Angin. Variabel Hujan berperan sebagai variabel target yang bertipe kategorik dengan dua kelas, yaitu 1 dan 2. Variabel Suhu, Kelembapan, dan Kecepatan Angin bertipe numerik, sedangkan Keadaan Cuaca bertipe kategorik berupa kode keadaan cuaca yang ditulis dalam bentuk angka. Keempat variabel selain Hujan berperan sebagai fitur.

3.3 Analisis Data

Berikut merupakan algoritma penelitian pada batasan masalah:

  1. Input data
  2. Pemeriksaan dan handling missing value
  3. Reduksi kardinalitas
  4. Splitting data dengan metode stratify
  5. Penanganan outlier dengan capping
  6. Scaling data dengan Standard Scaler
  7. Encoding dengan One-Hot Encoding
  8. Penyeimbangan data dengan SMOTE
  9. Output
  10. Interpretasi

BAB IV HASIL DAN PEMBAHASAN

4.1 Library dan Import Data

library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(readxl)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.2     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ 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)
library(e1071)
## 
## Attaching package: 'e1071'
## 
## The following object is masked from 'package:rsample':
## 
##     permutations
## 
## The following object is masked from 'package:ggplot2':
## 
##     element
library(DescTools)
library(dplyr)
library(ggplot2)
library(gridExtra)
## 
## Attaching package: 'gridExtra'
## 
## The following object is masked from 'package:dplyr':
## 
##     combine
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)
library(caret)
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following objects are masked from 'package:DescTools':
## 
##     MAE, RMSE
## 
## The following object is masked from 'package:rsample':
## 
##     calibration
## 
## The following object is masked from 'package:purrr':
## 
##     lift
data<- read_excel("D:/SEMESTER 7/MACHINE LEARNING/LAPRAK/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 ...

Tahapan dimulai dengan memanggil paket yang diperlukan untuk membaca, memanipulasi, menganalisis, memvisualisasikan, dan melakukan prapemrosesan data. Selanjutnya, dataset data curah hujan.xlsx diimpor menggunakan fungsi read_excel(). Fungsi head() digunakan untuk memeriksa enam baris pertama, sedangkan str() digunakan untuk mengetahui struktur dan tipe data setiap variabel. Tahap ini penting sebelum menerapkan feature engineering, karena karakteristik data perlu diketahui terlebih dahulu agar teknik pengolahan yang dipilih sesuai dengan kebutuhan analisis.

4.2 Handling Missing Value

# 2. 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
# 3. Penanganan Missing Value
df_imp <- data

# 3.1 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
# 3.2 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

Berdasarkan batasan masalah, penanganan missing value dilakukan menggunakan metode interpolasi pada variabel Keadaan Cuaca dan mode imputation pada variabel Kecepatan Angin. Hasil pemeriksaan awal menunjukkan bahwa nilai yang hilang hanya ditemukan pada kedua variabel tersebut. Variabel Keadaan Cuaca memiliki 9 nilai hilang, sedangkan variabel Kecepatan Angin memiliki 314 nilai hilang. Sementara itu, variabel Hujan, Suhu, dan Kelembapan tidak memiliki nilai yang hilang.

Penanganan missing value pada variabel Keadaan Cuaca dilakukan menggunakan fungsi na.approx melalui metode interpolasi linear, yaitu memperkirakan nilai yang hilang berdasarkan nilai di sekitarnya. Penggunaan argumen rule = 2 memungkinkan nilai yang hilang pada bagian awal maupun akhir data tetap diisi berdasarkan nilai terdekat yang tersedia. Setelah proses interpolasi dilakukan, seluruh 9 nilai hilang berhasil ditangani sehingga tidak tersisa missing value pada variabel tersebut. Namun, variabel Kecepatan Angin masih memiliki 314 nilai yang hilang sebelum dilakukan imputasi.

Selanjutnya, penanganan nilai hilang pada variabel Kecepatan Angin dilakukan menggunakan metode mode imputation, yaitu mengganti nilai yang hilang dengan nilai yang paling sering muncul dalam data. Berdasarkan hasil perhitungan, nilai modus variabel tersebut adalah 3. Dengan demikian, sebanyak 314 nilai yang hilang digantikan dengan angka 3 sehingga seluruh missing value berhasil diatasi. Metode imputasi ini dipilih karena proporsi nilai hilang pada variabel Kecepatan Angin mencapai 42,26%. Penghapusan baris yang mengandung nilai hilang berpotensi mengurangi jumlah observasi secara signifikan, sehingga imputasi digunakan untuk mempertahankan jumlah data. Meskipun demikian, penggantian seluruh nilai yang hilang dengan angka 3 menyebabkan nilai tersebut semakin dominan dalam distribusi variabel Kecepatan Angin.

4.3 Kardinalitas

# 4. Kardinalitas (Reduksi Kategori Keadaan_Cuaca)
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
# 4.1 Tentukan batas bin
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

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

# 4.3 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
)

# 4.4 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  27.4         86             2               4 0                    
##  2     1  30           64             2               3 0                    
##  3     2  27.6         83             2              10 0                    
##  4     2  23.3         98             1               3 0                    
##  5     2  25.6         78             1               3 0                    
##  6     2  24.8         94             2               3 0                    
##  7     2  31.2         63             2              10 0                    
##  8     2  29.9         69             2               9 0                    
##  9     2  27.3         82             2               2 0                    
## 10     2  24.8         92             2               4 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

Berdasarkan batasan masalah, variabel Keadaan Cuaca diolah menggunakan metode interpolasi yang menghasilkan nilai dengan variasi cukup tinggi, sehingga perlu dilakukan pemeriksaan kardinalitas. Kardinalitas merupakan jumlah nilai atau kategori unik yang terdapat dalam suatu variabel. Hasil pemeriksaan menunjukkan bahwa variabel Keadaan Cuaca memiliki 23 nilai unik, di antaranya 1; 1,5; 2; 5; 14; 60; 95; dan 97. Jumlah kategori yang cukup banyak dapat menyulitkan proses pengodean karena teknik one-hot encoding berpotensi menghasilkan banyak kolom tambahan, yang sebagian besar berisi nilai nol dan dapat meningkatkan kompleksitas model.

Untuk mengurangi jumlah kategori tersebut, dilakukan pengelompokan nilai (binning) menggunakan fungsi cut(). Nilai variabel dibagi ke dalam 10 interval dengan lebar masing-masing 10 satuan, menggunakan format interval (a,b](a,b](a,b], kemudian diberi label kategori 0 hingga 9. Penggunaan argumen include.lowest = TRUE bertujuan memastikan nilai terkecil, yaitu 0, tetap termasuk dalam interval pertama. Hasil pengelompokan tersebut disajikan pada Tabel 4.3.

Setelah proses binning, jumlah kategori yang teramati berkurang dari 23 menjadi 7, yaitu kategori 0, 1, 2, 4, 5, 6, dan 9. Kategori 0 mendominasi data karena nilai asli seperti 1, 2, dan 3 banyak ditemukan dalam pengamatan. Variabel hasil pengelompokan memiliki tipe data factor dengan 10 level yang tetap tersimpan, meskipun beberapa kategori tidak muncul dalam data. Penyimpanan seluruh level tersebut dapat membantu menjaga konsistensi kategori antara data latih dan data uji ketika dilakukan proses pengodean fitur.

4.4 Splitting Data

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

Berdasarkan batasan masalah, pembagian data dilakukan menggunakan metode stratified splitting dengan perbandingan 80% untuk data latih (training data) dan 20% untuk data uji (testing data). Penggunaan set.seed(46) bertujuan agar proses pembagian data menghasilkan hasil yang konsisten ketika dijalankan kembali. Hasil pembagian menunjukkan bahwa data latih terdiri atas 594 observasi, sedangkan data uji terdiri atas 149 observasi, dengan masing-masing memiliki 5 kolom. Selanjutnya, variabel Hujan ditetapkan sebagai variabel target yang dipisahkan ke dalam objek y_train dan y_test.

Metode stratified splitting membagi data dengan mempertahankan proporsi setiap kelas pada variabel target agar distribusi kelas pada data latih dan data uji tetap mendekati distribusi data awal. Berdasarkan hasil, kelas 1 memiliki proporsi sebesar 22,05% pada data latih dan 22,15% pada data uji, sedangkan kelas 2 masing-masing sebesar 77,95% dan 77,85%. Perbedaan proporsi yang relatif kecil menunjukkan bahwa distribusi kelas pada kedua subset data cukup konsisten. Namun, distribusi tersebut juga menunjukkan adanya ketidakseimbangan kelas karena jumlah observasi kelas 2 sekitar empat kali lebih banyak dibandingkan kelas 1. Kondisi ini perlu diperhatikan pada tahap pemodelan dan evaluasi karena model berpotensi lebih cenderung memprediksi kelas mayoritas.

4.5 Handling Outlier

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

# 6.2 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
# 6.3 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))
}

# 6.4 Fungsi plot diagnostik
diagnostic_plots <- function(df, variable) {
  
  p1 <- ggplot(df, aes(x = .data[[variable]])) +
    geom_histogram(bins = 30, fill = "yellow", color = "black") +
    ggtitle("Histogram") +
    theme_minimal()
  
  p2 <- ggplot(df, aes(y = .data[[variable]])) +
    geom_boxplot(fill = "#008080") +
    ggtitle("Boxplot") +
    theme_minimal()
  
  grid.arrange(p1, p2, ncol = 2)
}

# 6.5 Bandingkan sebelum dan sesudah capping
for (col in list_num) {
  cat(col, "- Before Capping\n")
  diagnostic_plots(X_train, col)
  
  cat("\n", col, "- After Capping\n")
  diagnostic_plots(X_train_capped, col)
}
## Suhu - Before Capping

## 
##  Suhu - After Capping

## Kelembapan - Before Capping

## 
##  Kelembapan - After Capping

## Kecepatan_Angin - Before Capping

## 
##  Kecepatan_Angin - After Capping

diagnostic_plots(X_train, "Suhu")
Gambar 4.1 Histogram dan boxplot Suhu sebelum capping

Gambar 4.1 Histogram dan boxplot Suhu sebelum capping

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

Gambar 4.2 Histogram dan boxplot Suhu setelah capping

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

Gambar 4.3 Histogram dan boxplot Kelembapan sebelum capping

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

Gambar 4.4 Histogram dan boxplot Kelembapan setelah capping

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

Gambar 4.5 Histogram dan boxplot Kecepatan_Angin sebelum capping

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

Gambar 4.6 Histogram dan boxplot Kecepatan_Angin setelah capping

Berdasarkan batasan masalah, penanganan outlier pada variabel numerik dilakukan menggunakan metode capping dengan pendekatan Interquartile Range (IQR). Suatu nilai dikategorikan sebagai outlier apabila berada di bawah batas \[Q1−1,5×IQR\] atau di atas batas \[Q3+1,5×IQR\]. Perhitungan batas dilakukan berdasarkan data latih untuk menghindari kebocoran informasi (data leakage) dari data uji. Berdasarkan hasil, variabel Suhu dan Kelembapan tidak memiliki outlier, sedangkan variabel Kecepatan Angin memiliki 5 outlier.

Pada variabel Suhu pada gambar 4.1 dan 4.2, nilai pengamatan berkisar antara 22,5 hingga 31 dengan median sekitar 26. Histogram menunjukkan distribusi data tanpa puncak yang ekstrem, sedangkan boxplot tidak memperlihatkan titik di luar whisker. Karena tidak ditemukan outlier, proses capping tidak mengubah nilai pengamatan sehingga grafik sebelum dan sesudah penanganan tetap sama.

Variabel Kelembapan pada gambar 4.3 dan 4.4 memiliki rentang nilai sekitar 52 hingga 100 dengan median sekitar 86. Distribusinya menceng ke kiri (left-skewed), dengan frekuensi tertinggi berada pada kisaran 95–97. Nilai minimum masih berada di atas batas bawah IQR, yaitu 44, sehingga tidak ditemukan outlier. Oleh karena itu, penerapan capping tidak mengubah data dan menghasilkan grafik yang identik dengan kondisi sebelum penanganan.

Sementara itu, variabel Kecepatan Angin sebelum capping pada gambar 4.5 menunjukkan adanya 5 outlier pada bagian atas distribusi, yang terlihat pada boxplot di sekitar nilai 14 dan 15. Histogram juga memperlihatkan frekuensi yang sangat tinggi pada nilai 3, yaitu sekitar 290 observasi. Kondisi tersebut terjadi karena sebagian besar nilai yang hilang sebelumnya digantikan menggunakan metode mode imputation. Akibatnya, distribusi data menjadi terkonsentrasi pada satu nilai.

Setelah dilakukan capping menggunakan fungsi Winsorize pada gambar 4.6, nilai yang melampaui batas atas 13 dibatasi menjadi 13 sehingga titik outlier tidak lagi terlihat pada boxplot. Sementara itu, batas bawah sebesar −3 tidak memengaruhi data karena nilai minimum pengamatan berada di sekitar 2. Metode capping dipilih karena dapat membatasi nilai ekstrem tanpa menghapus observasi, sehingga jumlah data latih tetap sebanyak 594 observasi. Batas capping yang diperoleh dari data latih selanjutnya diterapkan pada data uji agar proses penanganan outlier tetap konsisten dan tidak menimbulkan kebocoran data.

4.6 Scaling Data

# Parameter mean dan sd dihitung dari data latih saja
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

Berdasarkan batasan masalah, penerapan Standard Scaler dilakukan pada data dengan NPM genap untuk menyeragamkan skala variabel numerik, yaitu Suhu, Kelembapan, dan Kecepatan Angin. Metode ini mentransformasikan setiap nilai menjadi skor standar dengan mengurangi nilai pengamatan menggunakan rata-rata, kemudian membaginya dengan simpangan baku data latih. Penskalaan ini bertujuan menyamakan skala ketiga variabel yang sebelumnya memiliki rentang nilai berbeda, sehingga variabel dengan nilai numerik lebih besar tidak secara otomatis mendominasi proses analisis, khususnya pada algoritma yang sensitif terhadap skala data.

Berdasarkan hasil verifikasi, rata-rata ketiga variabel pada data latih setelah proses standardisasi bernilai mendekati 0, sedangkan simpangan bakunya mendekati 1. Hasil tersebut menunjukkan bahwa proses Standard Scaler telah berjalan dengan baik. Parameter rata-rata dan simpangan baku dihitung berdasarkan data latih, kemudian digunakan untuk mentransformasikan data uji. Prosedur ini memastikan bahwa data uji diperlakukan sebagai data baru dan mencegah kebocoran informasi dari data uji ke proses pelatihan model.

4.7 Encoding

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

Berdasarkan batasan masalah, variabel Keadaan Cuaca_reduced yang telah melalui proses reduksi kategori selanjutnya dikonversi menggunakan metode one-hot encoding. Proses ini diperlukan karena variabel tersebut bertipe factor, sehingga kategori diubah menjadi kolom biner agar dapat digunakan dalam pemodelan. Setiap kolom mewakili satu kategori, dengan nilai 1 menunjukkan bahwa observasi termasuk dalam kategori tersebut dan nilai 0 menunjukkan sebaliknya.

Pada enam observasi pertama, kolom Keadaan_Cuaca_reduced_X0 bernilai 1, yang menunjukkan bahwa observasi tersebut berada pada kategori 0, yaitu rentang nilai asli 0–10. Penggunaan levels = all_levels memastikan kategori yang tersedia pada data latih dan data uji tetap konsisten. Sementara itu, step_unknown menambahkan kolom untuk mengakomodasi kategori yang tidak dikenal. Kolom unknown bernilai 0 pada seluruh observasi karena tidak terdapat nilai yang masuk ke kategori tersebut.

Hasil pengodean menghasilkan 14 kolom fitur, yang terdiri atas 3 variabel numerik hasil standardisasi, 10 kolom dummy untuk kategori 0–9, dan 1 kolom unknown. Data latih memiliki ukuran 594 × 14, sedangkan data uji berukuran 149 × 14. Kesamaan jumlah kolom menunjukkan bahwa struktur fitur kedua data telah konsisten. Resep pengodean terlebih dahulu dipelajari melalui fungsi prep menggunakan data latih, kemudian diterapkan pada data latih dan data uji dengan fungsi bake.

4.8 Balancing Data (SMOTE)

# 9. 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)))

Berdasarkan batasan masalah, penanganan ketidakseimbangan kelas dilakukan menggunakan metode SMOTE (Synthetic Minority Over-sampling Technique). Sebelum penerapan SMOTE, data latih terdiri atas 131 observasi kelas 1 sebagai kelas minoritas dan 463 observasi kelas 2 sebagai kelas mayoritas, sebagaimana ditunjukkan pada hsil sintak. Ketidakseimbangan ini berpotensi menyebabkan model lebih cenderung mengenali kelas mayoritas dibandingkan kelas minoritas.

Metode SMOTE mengatasi permasalahan tersebut dengan menghasilkan observasi sintetis pada kelas minoritas melalui interpolasi antara observasi minoritas dan salah satu dari lima tetangga terdekatnya (neighbors = 5). Parameter over_ratio = 1 digunakan untuk mencapai jumlah observasi yang seimbang antara kedua kelas, sedangkan set.seed(46) memastikan proses dapat direproduksi dengan hasil yang konsisten.

Setelah penerapan SMOTE, jumlah observasi pada kelas 1 dan kelas 2 masing-masing menjadi 463, dengan proporsi sebesar 50% untuk setiap kelas. Sebanyak 332 observasi sintetis berhasil dibangkitkan sehingga ukuran data latih meningkat dari 594 menjadi 926 observasi. Data tersebut terdiri atas 14 fitur dan 1 variabel target, yaitu Hujan. Penerapan SMOTE hanya dilakukan pada data latih, sedangkan data uji tetap dipertahankan pada distribusi aslinya. Hal ini bertujuan agar evaluasi model dapat menggambarkan kinerja pada data yang tidak mengalami penyeimbangan sintetis. Selanjutnya, variabel target Hujan pada data uji diubah menjadi tipe factor agar sesuai dengan kebutuhan tahap pemodelan.

BAB V PENUTUP

5.1 Kesimpulan

Konsep berbagai jenis feature engineering meliputi penanganan nilai yang hilang, normalisasi dan standardisasi, pengodean variabel kategorik, transformasi variabel, pembentukan fitur baru, ekstraksi fitur, serta seleksi fitur. Setiap teknik memiliki fungsi yang berbeda dalam meningkatkan kualitas dan relevansi data sesuai dengan karakteristik serta tujuan analisis.

Penerapan teknik feature engineering menggunakan RStudio dapat dilakukan melalui bahasa pemrograman R dan berbagai paket pendukung untuk mengolah, mentransformasi, membentuk, serta menyeleksi fitur. Penerapan teknik yang tepat diharapkan dapat menghasilkan data yang lebih terstruktur dan mendukung proses analisis statistik maupun pemodelan machine learning secara efektif.

Berdasarkan hasil penerapan metode SMOTE, data latih yang awalnya tidak seimbang, yaitu 131 observasi pada kelas 1 dan 463 observasi pada kelas 2, berhasil diseimbangkan menjadi masing-masing 463 observasi dengan proporsi 50% : 50%. Proses ini menghasilkan 332 observasi sintetis sehingga jumlah data latih meningkat dari 594 menjadi 926 observasi, yang terdiri atas 14 fitur dan 1 variabel target Hujan. Penerapan SMOTE hanya dilakukan pada data latih, sedangkan data uji tetap dipertahankan pada distribusi aslinya agar evaluasi model dapat mencerminkan kinerja pada data yang tidak mengalami penyeimbangan sintetis.

5.1 Saran

Laporan praktikum ini melakukan pemograman R. Dalam hal ini perlu memahami sintak yang diperlukan dalam hal pengerjaannya ini agar tidak terjadi error pada programnya. Dan juga sangat perlu memahami bagaimana machine learning beropasi dan bagaimana cara kerja feature learning dan teknik apa saja yang digunakan kedalam analisis tersebut.

DAFTAR PUSTAKA

Budianita, A. (2023). Information Gain Berbasis Algoritma Naive Bayes Classifier Pada Pemodelan Prediksi Kelulusan Information Gain Based on Naive Bayes Classifier Algorithm in Graduation Prediction Modeling. Jurnal Ilmiah Intech: Information Technology Journal of UMUS, 5(1), 1–10.

Darmawan, R., Yut, I. V., Hernando, A., Handayani, R. I., Pratiwi, L., & Widanengsih, E. (2024). ANALISIS PERAN FEATURE ENGINEERING PADA KINERJA MODEL MACHINE LEARNING UNTUK KLASIFIKASI POTENSI TSUNAMI. 14(1).

Fauzi, N. P. N., Khomsah, S., & Wicaksono, A. D. P. (2025). Penerapan Feature Engineering dan Hyperparameter Tuning untuk Meningkatkan Akurasi Model Random Forest pada Klasifikasi Risiko Kredit. Jurnal Teknologi Informasi dan Ilmu Komputer, 12(2), 251–262. https://doi.org/10.25126/jtiik.2025128472

Fransiska, H. (2026). Modul Praktikum Machine Learning and Modern Prediction. Bengkulu: Laboratorium Matematika Fakultas Matematika dan Ilmu Pengetahuan Alam Universitas Bengkulu.

Hadi, R., Suwirmayanti, N. L. G. P., Kusuma, I. G. N. A., Saryanti, I. G. A. D., & Novayanti, P. D. (2024). Implementasi Metode Normalisasi dan Seleksi Fitur dalam Optimasi Algoritma K-Nearest Neighbor ( KNN ) untuk Klasifikasi Data Bank. 7(5), 1064–1071.

Herdian, C., Kamila, A., Tampinongkol, F. F., Kembau, A. S., & Budidarma, I. G. A. M. (2024). ONE-HOT ENCODING FEATURE ENGINEERING UNTUK LABEL-BASED DATA STUDI KASUS PREDIKSI HARGA MOBIL BEKAS One-Hot Encoding ke dalam prediksi harga. 9, 10–16.

Hr, S. Z., Aziz, A., & Harianto, W. (2022). Optimasi algoritma k-nearest neighbor (knn) dengan normalisasi dan seleksi fitur untuk klasifikasi penyakit liver. 6(2), 439–445.

Putri, D. F. A., Masjkur, M., & Indahwati. (2023). Penerapan Bernoulli Naïve Bayes untuk Analisis Sentimen Pengguna Twitter Terhadap Layanan Online Food Delivery di Indonesia. Xplore: Journal of Statistics, 12(1), 50–62. https://doi.org/10.29244/xplore.v12i1.1110

Sihombing, D. J. C. (2024). Application of Feature Engineering Techniques and Machine Learning Algorithms for Property Price Prediction. JITSI: Jurnal Ilmiah Teknologi Sistem Informasi, 5(2), 72–76. https://doi.org/10.62527/jitsi.5.2.241

Winata, F., Ilham, M., Tresnawan, A., & Wijaya, G. (2026). Integrasi Feature Engineering dan SMOTE pada Algoritma Random Forest untuk Prediksi Kerusakan Chip RFID di Industri Sel Surya. 7(2), 599–609. https://doi.org/10.47065/josh.v7i2.9038