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.
Berdasarkan latar belakang, rumusan masalah yang dapat disimpulkan adalah:
Adapun tujuan penelitian ini yaitu:
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):
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):
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:
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.
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.
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.
# 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
## 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.
## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 9 314
## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0.00000000 0.00000000 0.00000000 0.01211306 0.42261104
## # 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.
## # 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
## [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 ---
## # 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
##
## --- Pengecekan Kardinalitas ---
## 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
##
## Kategori unik yang baru (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.
# 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
## [1] 149 5
## y_train
## 1 2
## 0.2205387 0.7794613
## 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.
# 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)
}Gambar 4.1 Histogram dan boxplot variabel Suhu sebelum capping
Gambar 4.2 Histogram dan boxplot variabel Suhu setelah capping
Gambar 4.3 Histogram dan boxplot variabel Kelembapan sebelum capping
Gambar 4.4 Histogram dan boxplot variabel Kelembapan setelah capping
Gambar 4.5 Histogram dan boxplot variabel Kecepatan_Angin sebelum 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.
# 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
## 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.
# 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>
## [1] 594 14
## [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.
## y_train
## 1 2
## 131 463
## 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
##
## 1 2
## 0.5 0.5
## [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.
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.
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.
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.