BAB I PENDAHULUAN

1.1 Latar Belakang Masalah

Perkembangan teknologi informasi telah mendorong pemanfaatan data dalam berbagai bidang untuk mendukung proses pengambilan keputusan dan menghasilkan prediksi yang akurat. Salah satu teknologi yang banyak digunakan dalam pengolahan data adalah machine learning, yaitu bagian dari kecerdasan buatan yang mempelajari bagaimana komputer dapat belajar dari data yang diberikan. Berbeda dengan pemrograman konvensional yang mengharuskan komputer mengikuti instruksi secara terperinci, machine learning memungkinkan komputer menemukan pola dari data dan menggunakan pola tersebut sebagai dasar untuk mengambil keputusan atau membuat prediksi (Hartono, 2024).

Dalam penerapannya, keberhasilan machine learning tidak hanya ditentukan oleh algoritma yang digunakan, tetapi juga dipengaruhi oleh kualitas data yang diolah. Data mentah sering kali memiliki format yang beragam, mengandung informasi yang kurang relevan, atau belum sesuai dengan kebutuhan pemodelan. Oleh karena itu, diperlukan proses pengolahan data untuk memastikan bahwa informasi yang digunakan dapat membantu algoritma mengenali pola secara optimal. Salah satu tahapan penting dalam proses tersebut adalah feature engineering.

Feature engineering merupakan serangkaian langkah untuk mengubah data mentah menjadi fitur-fitur yang dapat digunakan dalam algoritma Machine Learning. Proses ini bertujuan untuk menyederhanakan dan mempercepat transformasi data sekaligus meningkatkan akurasi model yang dihasilkan (Fransiska, 2026). Tahapan feature engineering dapat mencakup pemilihan fitur yang relevan, transformasi variabel, pengubahan data kategorik menjadi bentuk numerik, serta pembentukan fitur baru berdasarkan informasi yang tersedia. Melalui tahapan tersebut, data dapat disesuaikan dengan kebutuhan algoritma sehingga informasi yang terkandung di dalamnya dapat dimanfaatkan secara lebih efektif. Oleh karena itu pada praktikum kali ini dibahas mengenai “Feature Engineering”.

1.2 Rumusan Masalah

  1. Bagaimana konsep dari berbagai jenis feature engineering pada RStudio?
  2. Bagaimana cara 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 Machine Learning

Machine Learning adalah bagian dari kecerdasan buatan yang mempelajari bagaimana komputer bisa belajar sendiri dari data yang diberikan. Bedanya dengan pemrograman biasa, komputer di sini tidak diberi tahu langkah demi langkah harus melakukan apa. Sebaliknya, pada machine learning komputer justru dilatih untuk menemukan pola tertentu dari data, kemudian menggunakan pola tersebut sebagai dasar untuk mengambil keputusan atau membuat prediksi (Hartono, 2024).

Secara umum, machine learning dapat dipahami sebagai bidang keilmuan yang memungkinkan sistem komputer meningkatkan kinerjanya secara bertahap melalui pengalaman, tanpa perlu diprogram ulang secara khusus untuk setiap tugas yang dihadapi. Pandangan serupa juga dikemukakan oleh Arthur Samuel, salah satu tokoh yang pertama kali memperkenalkan istilah ini, yang menyatakan bahwa machine learning adalah kemampuan komputer untuk belajar tanpa diberikan instruksi secara eksplisit untuk setiap tugas tertentu. Dari kedua pandangan tersebut dapat disimpulkan bahwa inti dari machine learning terletak pada sifat adaptifnya, yaitu kemampuan sistem untuk terus menyesuaikan dan memperbaiki performanya seiring bertambahnya data yang diproses (Bintoro, dkk., 2024).

Machine Learning secara umum dikategorikan menjadi tiga tipe utama, yaitu Supervised Learning, Unsupervised Learning, dan Reinforcement Learning. Ketiganya memiliki karakteristik, prinsip kerja, serta bidang penerapan yang berbeda satu sama lain. Jenis ini didasarkan pada bagaimana model belajar dari data dan bagaimana umpan balik diberikan selama proses pelatihan (Kelleher, 2020; Russell & Norvig, 2021).

  1. Supervised learning merupakan jenis pembelajaran mesin yang menggunakan dataset berlabel, artinya setiap data yang dimasukkan sudah disertai jawaban yang benar.

  2. Unsupervised learning bekerja pada data yang tidak memiliki label, sehingga model harus menemukan sendiri pola, struktur, atau hubungan tersembunyi di dalam data tanpa adanya jawaban yang menjadi acuan.

  3. Reinforcement learning adalah jenis pembelajaran mesin di mana sebuah agen belajar melalui interaksi langsung dengan lingkungannya. Agen tersebut melakukan suatu tindakan, kemudian menerima umpan balik berupa reward (imbalan) atau penalty (hukuman), dan memanfaatkan umpan balik itu untuk memperbaiki tindakannya di masa mendatang.

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

  1. 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. Data yang tidak lengkap adalah masalah yang tidak terhindarkan dalam menangani sebagian besar sumber data.

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

  3. Splitting 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. Rasio yang umum digunakan adalah 80% untuk training dan 20% untuk testing. Namun, rasio ini dapat disesuaikan tergantung pada ukuran dataset.

  4. 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 (missinput), 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.

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

  6. Encoding

    Feature encoding adalah proses mengubah fitur kategoris atau non numerik 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 One Hot Encoding dan Ordinal Encoding.

  7. 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 pada penelitian ini adalah data kuantitatif. Data kuantitatif adalah jenis data yang berbentuk angka atau bilangan dan dapat diukur atau dihitung secara langsung. Laporan ini memiliki satu batasan masalah yang menggunakan sumber data sekunder. Data sekunder adalah data yang diperoleh secara tidak langsung melalui media perantara. Data didapatkan dari Asisten Praktikum.

3.2 Variabel Penelitian

Variabel penelitian adalah karakter atau segala sesuatu yang menjadi perhatian dalam suatu penelitian. Pada batasan masalah terdapat lima variabel. Variabel tersebut adalah hujan, suhu, kelembapan, keadaan cuaca, dan kecepatan angin.

3.3 Langkah-langkah Analisis

  1. Input data
  2. Lakukan pengecekan dan penanganan missing value
  3. Lakukan pengurangan kardinalitas pada variabel kategorik menggunakan fungsi binning
  4. Bagi data menjadi data latih (training data) dan data uji (testing data) menggunakan metode shuffle splitting
  5. Lakukan pengecekan dan penanganan outlier menggunakan metode trimming dan capping
  6. Lakukan pemeriksaan kemencengan distribusi (skewness) dan penerapan scaling menggunakan metode robust scaler
  7. Lakukan transformasi variabel kategorik menjadi variabel numerik menggunakan metode One-Hot Encoding
  8. Melakukan balancing data menggunakan SMOTE

BAB IV HASIL DAN PEMBAHASAN

4.1 Library

Tuliskan terlebih dahulu library yang akan digunakan pada laporan ini. Selanjutnya input data yang akan digunakan, yaitu data curah hujan.

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.3     ✔ 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("C:/Users/Asus/Downloads/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 output di atas ditampilkan enam data pertama. Kemudian dapat juga dilihat struktur data yang akan digunakan. Data tersebut memiliki 743 baris dan 5 variabel pengamatan, yaitu hujan, suhu, kelembapan, keadaan cuaca, dan kecepatan angin. Seluruh variabel bertipe numerik, tetapi nilai pada variabel kecepatan_angin memiliki data hilang (missing value) yang ditandai dengan adanya NA. Oleh karena itu, perlu dilakukan pemeriksaan dan penanganan data hilang sebelum data digunakan dalam proses feature engineering dan pemodelan machine learning.

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
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 dengan Imputasi Mean
df_imp <- data
df_imp$Keadaan_Cuaca[is.na(df_imp$Keadaan_Cuaca)] <- mean(df_imp$Keadaan_Cuaca, na.rm = TRUE)
df_imp$Kecepatan_Angin[is.na(df_imp$Kecepatan_Angin)] <- mean(df_imp$Kecepatan_Angin, na.rm = TRUE)

# Cek Missing Value Setelah Imputasi
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0               0

Setelah dilakukan pengecekan, terdapat sebanyak 9 data hilang pada variabel keadaan cuaca dan 314 data hilang pada variabel kecepatan angin. Penanganan data hilang yang digunakan adalah imputasi mean. Imputasi mean mengisi setiap data kosong dengan nilai rata-rata dari variabel tersebut.

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            6.66
##  2     1  24           90             1            6.66
##  3     1  26.8         77             1            6.66
##  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.00000  1.00000  2.00000  3.00000 15.10763 14.00000 60.00000 61.00000
##  [9] 21.00000 29.00000 10.00000 16.00000 62.00000 63.00000 65.00000 15.00000
## [17] 17.00000 13.00000 95.00000 91.00000 97.00000
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
labels <- 0:9

df_imp$Keadaan_Cuaca_reduced <- cut(
  df_imp$Keadaan_Cuaca,
  breaks = bins,
  labels = labels,
  right = TRUE,
  include.lowest = TRUE)

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.6         83             3            6.66 0                    
##  2     2  28           82             2            5    0                    
##  3     2  27.2         86             2            6    0                    
##  4     2  24           97            17            6.66 1                    
##  5     2  28.8         78            15            6    1                    
##  6     2  29.2         68             3            5    0                    
##  7     2  26.8         87            21            5    2                    
##  8     1  22.9         97            61            6.66 6                    
##  9     2  31.1         63             2           10    0                    
## 10     1  23.6         88             1            6.66 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    : 21
cat('Jumlah kategori di "Keadaan_Cuaca_reduced" :', length(unique(df_imp$Keadaan_Cuaca_reduced)), "\n")
## Jumlah kategori di "Keadaan_Cuaca_reduced" : 6
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
## Levels: 0 1 2 3 4 5 6 7 8 9

Berdasarkan output di atas, variabel Keadaan_Cuaca awalnya memiliki 21 nilai unik, termasuk nilai desimal yang kemungkinan muncul akibat imputasi mean. Selanjutnya, dilakukan pengelompokan nilai menggunakan fungsi cut() dengan interval 10 sehingga jumlah kategori unik yang teramati berkurang menjadi 6 kategori.

4.4 Splitting Data

set.seed(200) 
split_shuffle <- initial_split(df_imp, prop = 0.8)

X_train <- training(split_shuffle) %>% select(-Hujan)
X_test  <- testing(split_shuffle)  %>% select(-Hujan)
y_train <- training(split_shuffle)$Hujan
y_test  <- testing(split_shuffle)$Hujan
dim(X_train)
## [1] 594   5
## samakan level Keadaan_Cuaca_reduced
all_levels <- levels(df_imp$Keadaan_Cuaca_reduced)

X_train$Keadaan_Cuaca_reduced <- factor(X_train$Keadaan_Cuaca_reduced, levels = all_levels)
X_test$Keadaan_Cuaca_reduced  <- factor(X_test$Keadaan_Cuaca_reduced,  levels = all_levels)

Selanjutnya dilakukan pembagian data atau splitting data menggunakan shuffle splitting yang membagi data secara acak menjadi data training sebesar 80% dan data testing sebesar 20%. Hasil pembagian menunjukkan bahwa data training memiliki 594 pengamatan dan 5 variabel prediktor setelah variabel Hujan dipisahkan sebagai variabel target. Selanjutnya, level kategori pada variabel keadaan cuaca disamakan antara data training dan testing agar struktur kategorinya konsisten. Pembagian ini bertujuan menyiapkan data untuk proses pelatihan dan evaluasi model machine learning.

4.5 Handling Outlier

## Handling Outlier
list_num <- c("Suhu", "Kelembapan", "Kecepatan_Angin")

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)
  
  total_outliers <- num_outliers_lower + num_outliers_upper
  list_outlier <- c(list_outlier, total_outliers)
}

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.4        35.8
## 2      Kelembapan              0        46.5       122.5
## 3 Kecepatan_Angin             50         2.0        10.0
df_num <- X_train[, list_num]
nilai_skew <- c()
nilai_skew_normal <- c()

for (i in colnames(df_num)) {
  skew_val <- skewness(X_train[[i]], na.rm = TRUE)
  
  if (skew_val >= -0.5 && skew_val <= 0.5) {
    nilai_skew_normal <- c(nilai_skew_normal, i)
  } else {
    nilai_skew <- c(nilai_skew, i)
  }
}

cat("kolom yang mempunyai nilai skewness sedang :", nilai_skew, "\n")
## kolom yang mempunyai nilai skewness sedang : Kelembapan Kecepatan_Angin
cat("kolom yang mempunyai nilai skewness normal :", nilai_skew_normal, "\n")
## kolom yang mempunyai nilai skewness normal : Suhu
outliers_indexed <- outliers %>% filter(Kolom == "Kecepatan_Angin")
lower_kecepatan <- outliers_indexed$Lower_Bound
upper_kecepatan <- outliers_indexed$Upper_Bound

outliers_KecepAngin <- ifelse(
  X_train$Kecepatan_Angin > upper_kecepatan, TRUE,
  ifelse(X_train$Kecepatan_Angin < lower_kecepatan, TRUE, FALSE)
)

# Trimming
X_train_trimmed1 <- X_train[!outliers_KecepAngin, ]

cat("Size dataset - Before trimming :", dim(X_train), "\n")
## Size dataset - Before trimming : 594 5
cat("Size dataset - After trimming  :", dim(X_train_trimmed1), "\n")
## Size dataset - After trimming  : 544 5
# Capping
X_train_capped <- X_train
X_train_capped$Kecepatan_Angin <- Winsorize(
  X_train$Kecepatan_Angin,
  val = c(lower_bound, upper_bound)
)

X_test_capped <- X_test
X_test_capped$Kecepatan_Angin <- Winsorize(
  X_test$Kecepatan_Angin,
  val = c(lower_bound, upper_bound)
)

diagnostic_plots <- function(df, variable) {
  p1 <- ggplot(df, aes(x = .data[[variable]])) +
    geom_histogram(bins = 30, fill = "#008080", 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)
}

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

Proses handling outlier dilakukan pada variabel suhu, kelembapan, dan kecepatan angin menggunakan metode IQR untuk menentukan batas bawah dan batas atas pencilan. Berdasarkan nilai skewness, variabel suhu memiliki distribusi yang relatif simetris, sedangkan kelembapan dan kecepatan angin menunjukkan distribusi yang lebih menceng. Metode trimming diterapkan pada variabel kecepatan angin, sehingga jumlah data training berkurang dari 594 menjadi 544 pengamatan. Selanjutnya, metode capping menggunakan fungsi Winsorize() diterapkan pada variabel kecepatan angin untuk membatasi nilai ekstrem tanpa menghapus pengamatan. Histogram dan boxplot sebelum serta sesudah capping dibuat untuk ketiga variabel, yaitu suhu, kelembapan, dan kecepatan angin, guna membandingkan perubahan distribusi dan keberadaan pencilan. Namun karena capping hanya diterapkan pada kecepatan angin, sehingga histogram dan boxplot suhu serta kelembapan tidak mengalami perubahan.

4.6 Scalling Data

## Scalling
nilai_skew <- c()
nilai_skew_normal <- c()

for (i in colnames(df_num)) {
  skew_val <- skewness(X_train_capped[[i]], na.rm = TRUE)
  
  if (skew_val >= -0.5 && skew_val <= 0.5) {
    nilai_skew_normal <- c(nilai_skew_normal, i)
  } else {
    nilai_skew <- c(nilai_skew, i)
  }
}

cat("kolom yang mempunyai nilai skewness sedang :", nilai_skew, "\n")
## kolom yang mempunyai nilai skewness sedang : Kelembapan
cat("kolom yang mempunyai nilai skewness normal :", nilai_skew_normal, "\n")
## kolom yang mempunyai nilai skewness normal : Suhu Kecepatan_Angin
# Robust scaler
median_val <- sapply(X_train_capped[nilai_skew], median, na.rm = TRUE)
iqr_val    <- sapply(X_train_capped[nilai_skew], IQR, na.rm = TRUE)

for (col in nilai_skew) {
  X_train_capped[[col]] <- (X_train_capped[[col]] - median_val[col]) / iqr_val[col]
}
for (col in nilai_skew) {
  X_test_capped[[col]] <- (X_test_capped[[col]] - median_val[col]) / iqr_val[col]
}

X_train_scale <- X_train_capped
X_test_scale <- X_test_capped

Berdasarkan hasil pemeriksaan, seluruh variabel pada data telah terbebas dari missing value, ditunjukkan oleh jumlah nilai hilang sebesar nol pada setiap variabel. Tahap scaling dilakukan dengan mengevaluasi nilai skewness setelah proses capping, sehingga variabel kelembapan termasuk kelompok yang memerlukan robust scaler, sedangkan suhu dan kecepatan angin memiliki nilai skewness dalam rentang −0,5 hingga 0,5. Robust scaler diterapkan pada variabel Kelembapan dengan mengurangi nilai median dan membaginya dengan IQR. Parameter median dan IQR dari data training kemudian digunakan pada data testing untuk menjaga konsistensi transformasi dan mencegah kebocoran informasi. Hasil penskalaan disimpan untuk digunakan pada tahap pemodelan machine learning.

4.7 Encoding

## Encoding - One Hot Encoder
list_cat <- c("Keadaan_Cuaca_reduced")

resep_encode <- recipe(~ Keadaan_Cuaca_reduced, data = X_train_scale) %>%
  step_dummy(all_of(list_cat), one_hot = TRUE) %>%
  prep(training = X_train_scale)

X_train_encoded <- bake(resep_encode, new_data = NULL)
X_test_encoded  <- bake(resep_encode, new_data = X_test_scale)

X_train_encoded
## # A tibble: 594 × 10
##    Keadaan_Cuaca_reduced_X0 Keadaan_Cuaca_reduced_X1 Keadaan_Cuaca_reduced_X2
##                       <dbl>                    <dbl>                    <dbl>
##  1                        0                        0                        0
##  2                        1                        0                        0
##  3                        1                        0                        0
##  4                        1                        0                        0
##  5                        1                        0                        0
##  6                        1                        0                        0
##  7                        0                        0                        0
##  8                        0                        0                        0
##  9                        1                        0                        0
## 10                        1                        0                        0
## # ℹ 584 more rows
## # ℹ 7 more variables: 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>
X_test_encoded
## # A tibble: 149 × 10
##    Keadaan_Cuaca_reduced_X0 Keadaan_Cuaca_reduced_X1 Keadaan_Cuaca_reduced_X2
##                       <dbl>                    <dbl>                    <dbl>
##  1                        1                        0                        0
##  2                        1                        0                        0
##  3                        1                        0                        0
##  4                        1                        0                        0
##  5                        1                        0                        0
##  6                        1                        0                        0
##  7                        1                        0                        0
##  8                        1                        0                        0
##  9                        1                        0                        0
## 10                        1                        0                        0
## # ℹ 139 more rows
## # ℹ 7 more variables: 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>

Tahap selanjutnya adalah encoding menggunakan metode One-Hot Encoding pada variabel kategorik keadaan cuaca. Proses ini mengubah kategori cuaca menjadi beberapa kolom indikator biner agar dapat digunakan oleh algoritma machine learning. Transformasi dilakukan dengan membentuk resep berdasarkan data training, kemudian diterapkan pada data training dan testing untuk menjaga konsistensi kategori.

4.8 Balancing Data

table(y_train)
## y_train
##   1   2 
## 128 466
train_full <- X_train_encoded %>%
  mutate(Hujan = y_train)

train_full$Hujan <- factor(train_full$Hujan)   # SMOTE butuh target berupa factor

set.seed(42)   

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

resep_smote_prep <- prep(resep_smote, training = train_full)

train_balanced <- bake(resep_smote_prep, new_data = NULL)

# Pisahkan lagi jadi X dan y
X_train_balanced <- train_balanced %>% select(-Hujan)
y_train_balanced <- train_balanced$Hujan

table(y_train_balanced)
## y_train_balanced
##   1   2 
## 466 466

Tahap terakhir adalah balancing data menggunakan metode Synthetic Minority Over-sampling Technique (SMOTE). Sebelum dilakukan SMOTE, variabel target Hujan memiliki kelas 1 sebanyak 128 observasi dan kelas 2 sebanyak 466 observasi, sehingga distribusi kelas tidak seimbang. SMOTE membangkitkan data sintetis pada kelas minoritas dengan memanfaatkan lima tetangga terdekat hingga jumlah kedua kelas menjadi seimbang. Setelah proses tersebut, data latih dipisahkan kembali menjadi variabel prediktor dan variabel target. Hasil akhirnya menunjukkan bahwa kedua kelas masing-masing memiliki 466 observasi, sehingga data latih menjadi seimbang dan dapat digunakan untuk proses pemodelan klasifikasi selanjutnya.

BAB V KESIMPULAN

5.1 Kesimpulan

Feature engineering merupakan tahapan pengolahan data untuk meningkatkan kualitas fitur sebelum digunakan dalam pemodelan machine learning. Berbagai jenis feature engineering meliputi penanganan missing value melalui imputasi, penanganan outlier menggunakan metode trimming dan capping, penskalaan data (scaling) menggunakan Robust Scaler atau Standard Scaler, serta encoding untuk mengubah variabel kategorik menjadi bentuk numerik. Setiap teknik memiliki fungsi yang berbeda, sehingga pemilihannya perlu disesuaikan dengan karakteristik data dan kebutuhan algoritma yang digunakan.

Teknik feature engineering pada RStudio dapat dilakukan menggunakan berbagai fungsi dari paket seperti dplyr, recipes, ggplot2, dan tidyr. Prosesnya dimulai dengan memeriksa dan menangani missing value, mendeteksi serta menangani outlier, melakukan scaling pada variabel numerik jika diperlukan, dan menerapkan encoding pada variabel kategorik. Selanjutnya, data dibagi menjadi data training dan testing sebelum digunakan dalam pemodelan, dengan memastikan parameter transformasi dihitung dari data training dan diterapkan secara konsisten pada data testing untuk menghindari data leakage.

Feature engineering menunjukkan bahwa pengolahan data merupakan tahap penting sebelum data digunakan dalam pemodelan machine learning. Proses yang dilakukan meliputi penanganan missing value dengan imputasi mean, pengurangan kardinalitas pada variabel kategorik, pembagian data menjadi data latih dan data uji, serta penanganan outlier menggunakan metode trimming dan capping. Selanjutnya, dilakukan pemeriksaan kemencengan distribusi untuk menentukan kebutuhan scaling menggunakan robust scaler serta pengubahan variabel kategorik menjadi numerik melalui one hot encoding. Terakhir, dilakukan penyeimbangan variabel target menggunakan metode SMOTE. Berdasarkan tahapan tersebut, dapat dipahami bahwa setiap teknik feature engineering memiliki fungsi yang berbeda dan perlu diterapkan sesuai karakteristik data agar data lebih siap digunakan dalam pemodelan machine learning.

DAFTAR PUSTAKA

Bintoro, P., Ratnasari, Wihardjo, E., Putri, I. P., & Asari, A. (2024). Pengantar Machine Learning. PT Mafy Media Literasi Indonesia.

Fransiska, H. (2026). Modul Praktikum Machine Learning. Bengkulu: Laboratorium Statistika FMIPA Universitas Bengkulu.

Hartono. (2024). Modul digital Machine Learning. Kementerian Pendidikan Tinggi, Sains, dan Teknologi.

Kelleher, J. D., Namee, B. M., & D’Arcy, A. (2020). Fundamentals Of Machine Learning For Predictive Data Analytics. MIT Press.

Russel, S. J., & Norvig, P. (2022). Artificial Intelligence A Modern Approach Fourth Edition Global Edition.