Perkembangan teknologi informasi menyebabkan jumlah data yang tersedia semakin meningkat. Data tersebut dapat dimanfaatkan untuk berbagai keperluan analisis, tetapi tidak semua data dapat langsung digunakan dalam proses pemodelan. Oleh karena itu, diperlukan tahapan pengolahan data untuk memperbaiki kualitas data dan menghasilkan informasi yang relevan. Salah satu tahapan yang penting dalam proses tersebut adalah feature engineering, yaitu proses mengolah, mentransformasikan, atau membentuk fitur agar data lebih sesuai dengan kebutuhan analisis dan pemodelan.
Feature engineering dapat dimanfaatkan dalam penerapan machine learning untuk membentuk fitur yang mendukung proses deteksi serangan DDoS. Penerapan teknik ini menunjukkan bahwa pengolahan fitur merupakan bagian penting dalam mempersiapkan data untuk proses pembelajaran mesin (Faiz dkk., 2022). Persiapan data memiliki beberapa tahapan, seperti pembersihan data, transformasi data, seleksi fitur, encoding variabel kategorik, dan reduksi dimensi. Tahapan tersebut membantu menyiapkan data agar dapat digunakan dalam proses analisis lebih lanjut (Daniswara dan Nuryana, 2023).
Teknik feature engineering terdiri atas berbagai jenis yang dapat disesuaikan dengan karakteristik data. Beberapa teknik yang dapat diterapkan antara lain feature scaling untuk menyamakan skala variabel numerik, encoding untuk mengubah variabel kategorik menjadi bentuk numerik, feature construction untuk membentuk fitur baru, serta feature selection untuk memilih fitur yang relevan. Rahmadeyan dan Mustakim (2023) menerapkan metode Chi-Square dan Mutual Information dalam seleksi fitur untuk klasifikasi prestasi belajar mahasiswa. Penelitian tersebut menunjukkan bahwa seleksi fitur dapat membantu menentukan fitur yang digunakan dalam pemodelan serta berpotensi meningkatkan kinerja model.
RStudio merupakan bahasa pemrograman R yang dapat digunakan dalam pengolahan dan analisis data. Melalui RStudio, mahasiswa dapat menerapkan berbagai teknik feature engineering dengan memanfaatkan fungsi dan paket yang tersedia. Praktik secara langsung diperlukan agar mahasiswa tidak hanya memahami konsep setiap teknik, tetapi juga mampu mengimplementasikannya sesuai dengan karakteristik dataset. Oleh karena itu, praktikum ini dilakukan untuk memahami berbagai jenis feature engineering serta menerapkan teknik tersebut menggunakan RStudio sebagai salah satu tahapan persiapan data sebelum analisis dan pemodelan statistik.
Berdasarkan latar belakang tersebut, rumusan masalah dalam praktikum ini adalah sebagai berikut.
1. Apa saja konsep dan jenis-jenis teknik feature engineering yang dapat digunakan dalam pengolahan data?
2. Bagaimana cara menerapkan berbagai teknik feature engineering menggunakan RStudio?
Tujuan yang ingin dicapai dalam praktikum ini adalah sebagai berikut:
1. Mahasiswa mampu memahami konsep dan berbagai jenis teknik feature engineering dalam pengolahan data.
2. Mahasiswa mampu menerapkan teknik feature engineering menggunakan RStudio.
Feature engineering merupakan salah satu tahapan dalam pengolahan data yang bertujuan untuk menghasilkan representasi fitur yang sesuai dengan kebutuhan analisis dan pemodelan. Proses ini dilakukan dengan memanfaatkan informasi yang tersedia dalam data melalui transformasi, pembentukan fitur baru, ekstraksi fitur, maupun pemilihan fitur yang relevan. Dalam penerapan machine learning, fitur menjadi komponen penting karena digunakan oleh algoritma untuk mengenali pola dan hubungan dalam data. Oleh karena itu, penerapan feature engineering perlu mempertimbangkan karakteristik dataset serta tujuan pemodelan yang ingin dicapai (Mumuni dan Mumuni, 2025).
Salah satu teknik yang digunakan dalam feature engineering adalah feature scaling, yaitu proses menyamakan atau menyesuaikan skala variabel numerik. Perbedaan rentang nilai antarvariabel dapat memengaruhi proses pembelajaran pada algoritma tertentu, terutama algoritma yang menggunakan perhitungan jarak atau optimasi berbasis nilai numerik. Salah satu metode feature scaling adalah normalisasi Min-Max, yang mengubah nilai data ke rentang tertentu, misalnya 0 sampai 1. Rumus normalisasi Min-Max dituliskan sebagai berikut (Koukaras dan Tjortjis, 2025).
\[ x'=\frac{x-x_{\min}}{x_{\max}-x_{\min}} \]
Keterangan:
Berdasarkan rumus tersebut, nilai minimum akan dipetakan menjadi 0 dan nilai maksimum menjadi 1 apabila nilai minimum dan maksimum berbeda. Nilai lainnya akan berada di antara kedua batas tersebut. Namun, apabila nilai minimum sama dengan nilai maksimum, penyebut pada rumus menjadi nol sehingga diperlukan penanganan khusus. Normalisasi ini dapat membantu menyamakan rentang variabel numerik, tetapi tidak menghilangkan pengaruh pencilan (outlier) yang terdapat dalam data (Koukaras dan Tjortjis, 2025).
Selain normalisasi, terdapat metode standardisasi menggunakan skor-Z (Z-score standardization). Standardisasi dilakukan dengan mengurangi setiap nilai data menggunakan rata-rata, kemudian membaginya dengan standar deviasi. Hasil transformasi menunjukkan posisi relatif suatu nilai terhadap rata-rata data dalam satuan standar deviasi. Rumus standardisasi Z-score adalah sebagai berikut (Koukaras dan Tjortjis, 2025).
\[ z=\frac{x-\mu}{\sigma} \]
Keterangan:
Teknik berikutnya adalah encoding, yaitu proses mengubah variabel kategorik menjadi representasi yang dapat diproses oleh algoritma. Variabel kategorik, seperti jenis layanan, status, atau kategori produk, sering kali perlu diubah menjadi bentuk numerik sebelum digunakan dalam pemodelan. Salah satu metode yang dapat digunakan adalah one-hot encoding, yaitu membentuk kolom indikator untuk setiap kategori. Nilai indikator ditetapkan menjadi 1 apabila suatu observasi termasuk dalam kategori yang bersangkutan dan 0 apabila tidak. Pengubahan variabel kategorik menjadi numerik merupakan salah satu tahapan penting dalam persiapan data untuk analisis machine learning (Daniswara dan Nuryana, 2023).
Secara matematis, one-hot encoding dapat dinyatakan sebagai berikut.
\[ x_{ij}= \begin{cases} 1, & \text{jika observasi } i \text{ termasuk kategori } j,\\ 0, & \text{jika tidak.} \end{cases} \]
Keterangan:
Selain melakukan transformasi terhadap fitur yang telah tersedia, feature engineering juga mencakup feature construction, yaitu pembentukan fitur baru dari satu atau beberapa variabel yang sudah ada. Fitur baru dapat dibentuk melalui operasi aritmetika, penggabungan informasi, atau transformasi yang sesuai dengan konteks permasalahan. Sebagai contoh, apabila tersedia variabel jumlah barang dan harga per barang, variabel total harga dapat dibentuk melalui perkalian kedua variabel tersebut. Pembentukan fitur bertujuan menyediakan representasi tambahan yang berpotensi membantu model menangkap pola yang tidak terlihat secara langsung pada fitur awal (Mumuni dkk., 2025).
Salah satu contoh sederhana pembentukan fitur baru dapat dituliskan dengan rumus berikut.
\[ X_{\text{baru}}=X_1+X_2 \]
Keterangan:
Rumus tersebut merupakan contoh penjumlahan dua fitur, bukan rumus universal untuk seluruh proses feature construction. Operasi yang digunakan harus sesuai dengan makna variabel dan konteks data. Pembentukan fitur yang tidak sesuai dapat menghasilkan variabel yang sulit ditafsirkan atau tidak memberikan informasi tambahan bagi model. Oleh sebab itu, fitur baru perlu dievaluasi berdasarkan relevansi, kualitas, dan kontribusinya terhadap tujuan analisis (Mumuni dan Mumuni, 2025).
Teknik lain yang penting adalah feature selection, yaitu proses memilih sejumlah fitur yang relevan dari keseluruhan fitur yang tersedia. Seleksi fitur dapat digunakan untuk mengurangi fitur yang tidak relevan atau berlebihan, menyederhanakan model, serta mengurangi beban komputasi. Salah satu metode yang digunakan adalah Chi-Square, yaitu metode statistik yang dapat mengukur hubungan antara dua variabel kategorik berdasarkan perbandingan frekuensi observasi dan frekuensi harapan. Rahmadeyan dan Mustakim (2023) menerapkan Chi-Square dan Mutual Information untuk memilih fitur dalam klasifikasi prestasi belajar mahasiswa dan melaporkan hasil yang menunjukkan manfaat seleksi fitur pada kasus yang diteliti (Rahmadeyan dan Mustakim, 2023).
Jenis data yang digunakan dalam penelitian ini berupa data kuantitatif. Data kuantitatif adalah jenis data yang berbentuk angka atau berskala numerik yang dapat dihitung secara langsung. Sumber data yang digunakan adalah data sekunder. Data sekunder adalah data yang diperoleh secara tidak langsung melalui perantara. Data yang digunakan pada penelitian ini adalah data curah hujan yang diberikan oleh Asisten Pratikum.
Variabel penelitian adalah segala sesuatu yang menjadi objek pengamatan dalam suatu penelitian. Pada penelitian ini terdapat 5 variabel. Variabel yaitu hujan, suhu, kelembapan, keadaan cuaca dan kecepatan angin dengan jumlah observasi sebanyak 743 observasi.
Berikut langkah” analisis data pada penelitian ini:
1. Input data. 2. Pemeriksaan dan Penanganan missing value 3. Kardinalitas 4. Stratified split data 5. Capping untuk pencilan 6. Penskalaan dengan Standard Scaler 7. Pengodean dengan One-Hot Encoding 8. Penyeimbangan kelas dengan SMOTE 9. Output 10.Interpretasi.
Library yang digunakan pada pratikum adalah sebagai berikut:
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## ── 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
##
## Attaching package: 'e1071'
##
## The following object is masked from 'package:rsample':
##
## permutations
##
## The following object is masked from 'package:ggplot2':
##
## element
##
## Attaching package: 'gridExtra'
##
## The following object is masked from 'package:dplyr':
##
## combine
##
## Attaching package: 'recipes'
##
## The following object is masked from 'package:stringr':
##
## fixed
##
## The following object is masked from 'package:stats':
##
## step
## 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
## # 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 ...
## Hujan Suhu Kelembapan Keadaan_Cuaca
## Min. :1.000 Min. :22.60 Min. : 52.00 Min. : 1.00
## 1st Qu.:2.000 1st Qu.:24.30 1st Qu.: 75.00 1st Qu.: 2.00
## Median :2.000 Median :26.00 Median : 86.00 Median : 2.00
## Mean :1.779 Mean :26.54 Mean : 83.88 Mean :15.11
## 3rd Qu.:2.000 3rd Qu.:28.90 3rd Qu.: 94.00 3rd Qu.:15.00
## Max. :2.000 Max. :32.00 Max. :100.00 Max. :97.00
## NAs :9
## Kecepatan_Angin
## Min. : 2.000
## 1st Qu.: 4.000
## Median : 6.000
## Mean : 6.655
## 3rd Qu.: 9.000
## Max. :21.000
## NAs :314
Berdasarkan hasil statistik deskriptif, variabel Hujan memiliki rata-rata 1,779, Suhu sebesar 26,54, Kelembapan sebesar 83,88, Keadaan_Cuaca sebesar 15,11, dan Kecepatan_Angin sebesar 6,655. Terdapat 9 data hilang pada variabel Keadaan_Cuaca dan 314 data hilang pada variabel Kecepatan_Angin. Oleh karena itu, diperlukan pemeriksaan dan penanganan data hilang serta pengecekan kode kategori sebelum dilakukan proses feature engineering.
## 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
## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 0 0
# Mode Imputation
get_mode <- function(x) {
nilai <- na.omit(x)
frekuensi <- table(nilai)
as.numeric(names(frekuensi)[which.max(frekuensi)]) }
df_imp1 <- data
modus_angin <- get_mode(df_imp1$Kecepatan_Angin)
df_imp1$Kecepatan_Angin[is.na(df_imp1$Kecepatan_Angin)] <- modus_angin
colSums(is.na(df_imp1))## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 9 0
# Interpolasi
df_imp2 <- data
df_imp2$Keadaan_Cuaca <- na.approx( df_imp2$Keadaan_Cuaca, na.rm = FALSE )
colSums(is.na(df_imp2)) ## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 0 314
# Mode Imputation dan Interpolasi
df_imp4 <- data
df_imp4$Keadaan_Cuaca <- na.approx(
df_imp4$Keadaan_Cuaca, na.rm = FALSE )
modus_angin <- get_mode(df_imp4$Kecepatan_Angin)
df_imp4$Kecepatan_Angin[is.na(df_imp4$Kecepatan_Angin)] <- modus_angin
colSums(is.na(df_imp4)) ## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 0 0
## # 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
Berdasarkan hasil pemeriksaan, terdapat 9 nilai hilang pada variabel Keadaan_Cuaca (1,21%) dan 314 nilai hilang pada variabel Kecepatan_Angin (42,26%). Penanganan dilakukan menggunakan metode mode imputation pada Kecepatan_Angin dan interpolasi pada Keadaan_Cuaca. Hasil penggabungan kedua metode pada dataset df_imp4 menunjukkan bahwa seluruh variabel tidak lagi memiliki nilai hilang, sehingga data siap digunakan untuk tahap preprocessing selanjutnya, yaitu capping, stratified splitting, Standard Scaler, dan SMOTE.
## # 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
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
labels <- 0:9
df_imp4$Keadaan_Cuaca_reduced <- cut(
df_imp4$Keadaan_Cuaca,
breaks = bins,
labels = labels,
right = TRUE,
include.lowest = TRUE
)
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 23.3 98 10 3 0
## 2 2 27 86 60 3 5
## 3 2 23.4 97 1 3 0
## 4 2 23.4 97 2 3 0
## 5 2 25.7 92 13 3 1
## 6 2 28 79 3 5 0
## 7 2 30.6 67 2 14 0
## 8 1 29.4 75 3 7 0
## 9 2 30 69 2 7 0
## 10 2 26.4 89 2 3 0
##
## --- Pengecekan Kardinalitas ---
## Jumlah kategori di "Keadaan_Cuaca" asli : 23
cat('Jumlah kategori di "Keadaan_Cuaca_reduced" :', length(unique(df_imp4$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
Berdasarkan hasil pengecekan kardinalitas, variabel Keadaan_Cuaca memiliki 23 nilai unik sebelum dilakukan pengelompokan. Setelah dilakukan pengurangan kardinalitas menggunakan fungsi cut() dengan interval 10 satuan, jumlah kategori yang teramati berkurang menjadi 7 kategori, yaitu 0, 1, 2, 4, 5, 6, dan 9. Sementara itu, kategori 3, 7, dan 8 tidak muncul pada hasil pengelompokan karena tidak terdapat nilai data yang masuk ke interval tersebut. Dengan demikian, pengelompokan berhasil mengurangi jumlah nilai unik yang teramati pada variabel tersebut.
# Splitting Data dengan Stratified Sampling
set.seed(200)
split_stratify <- initial_split(df_imp4, prop = 0.8, strata = Hujan)
# Memisahkan Variabel Prediktor dan Target
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_test)## [1] 149 5
## samakan level Keadaan_Cuaca_reduced
all_levels <- levels(df_imp4$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)Berdasarkan hasil stratified splitting, data berhasil dibagi menjadi data latih (training) sebesar 80% dan data uji (testing) sebesar 20% dengan mempertahankan proporsi kelas pada variabel target Hujan. Hasil menunjukkan bahwa data uji memiliki 149 observasi dan 5 variabel prediktor. Selanjutnya, level kategori pada variabel Keadaan_Cuaca_reduced disamakan antara data latih dan data uji agar struktur kategorinya tetap konsisten untuk tahap pemodelan berikutnya.
## 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.4625 35.7625
## 2 Kelembapan 0 46.5000 122.5000
## 3 Kecepatan_Angin 12 -3.0000 13.0000
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
## 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
## Size dataset - After trimming : 582 5
# Capping pada semua variabel numerik
X_train_capped <- X_train
X_test_capped <- X_test
for (i in list_num) {
# Menghitung batas IQR berdasarkan data training
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
# Capping data training
X_train_capped[[i]] <- pmax(
lower_bound,
pmin(X_train[[i]], upper_bound) )
# Capping data testing menggunakan batas training
X_test_capped[[i]] <- pmax(
lower_bound,
pmin(X_test[[i]], upper_bound) ) }
# Membandingkan ukuran data sebelum dan sesudah capping
cat("Training sebelum capping:", dim(X_train), "\n") ## Training sebelum capping: 594 5
## Training sesudah capping: 594 5
## Testing sebelum capping: 149 5
## Testing sesudah capping: 149 5
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
Berdasarkan hasil deteksi outlier menggunakan metode Interquartile Range (IQR), variabel Suhu dan Kelembapan tidak memiliki outlier padadata training. Variabel Suhu memiliki batas bawah sebesar 17,4625 dan batas atas sebesar 35,7625, sedangkan variabel Kelembapan memiliki batas bawahsebesar 46,5 dan batas atas sebesar 122,5. Sementara itu, variabel Kecepatan_Angin memiliki 12 outlier dengan batas bawah sebesar -3 dan batas atas sebesar 13. Berdasarkan pemeriksaan skewness, variabel Suhu termasuk kategori normal karena memiliki nilai skewness antara -0,5 hingga 0,5, sedangkan Kelembapan dan Kecepatan_Angin berada di luar rentang tersebut. Pada proses trimming, jumlah observasi training berkurang dari 594 menjadi 582 baris karena 12 observasi pada variabel Kecepatan_Angin dihapus. Selanjutnya, dilakukan capping dengan membatasi nilai yang berada di luar batas IQR tanpa menghapus observasi. Hasilnya menunjukkan bahwa jumlah observasi training tetap sebanyak 594 baris dan testing sebanyak 149 baris. Histogram dan boxplot sebelum serta sesudah capping digunakan untuk membandingkan distribusi data dan perubahan nilai ekstrem pada ketiga variabel numerik.
## *Scalling Standard scaler*
list_num <- c("Suhu", "Kelembapan", "Kecepatan_Angin")
mean_val <- sapply(X_train_capped[list_num], mean, na.rm = TRUE)
sd_val <- sapply(X_train_capped[list_num], sd, na.rm = TRUE)
for (col in list_num) {
X_train_capped[[col]] <-
(X_train_capped[[col]] - mean_val[col]) / sd_val[col]
}
for (col in list_num) {
X_test_capped[[col]] <-
(X_test_capped[[col]] - mean_val[col]) / sd_val[col]
}
X_train_scale <- X_train_capped
X_test_scale <- X_test_cappedPada tahap scaling, dilakukan standardisasi terhadap variabel Suhu, Kelembapan, dan Kecepatan_Angin menggunakan metode Standard Scaler. Proses ini dilakukan dengan mengurangi setiap nilai pengamatan menggunakan rata-rata (mean) data training, kemudian membaginya dengan standar deviasi data training. Parameter yang diperoleh dari data training selanjutnya diterapkan pada data testing agar kedua kelompok data memiliki skala yang konsisten.
## 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 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
## # ℹ 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>
## # 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 0 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 berikutnya adalah encoding menggunakan metode One-Hot Encoding pada variabel kategorik Keadaan_Cuaca_reduced. Proses ini mengubah kategori cuaca menjadi beberapa variabel dummy yang menunjukkan keanggotaan setiap pengamatan pada kategori tertentu. Encoding dilakukan dengan data training, kemudian diterapkan pada data training dan testing. Dengan demikian, variabel kategorik dapat direpresentasikan dalam bentuk numerik untuk mendukung proses analisis dan pemodelan selanjutnya.
## Handling Imbalanced Data - SMOTE
library(themis)
library(recipes)
library(dplyr)
# Menggabungkan hasil encoding dengan target Hujan
data_train_smote <- X_train_encoded %>%
mutate(Hujan = factor(y_train))
# Membuat recipe SMOTE
resep_smote <- recipe(Hujan ~ ., data = data_train_smote) %>%
step_smote(Hujan, over_ratio = 1, seed = 200) %>%
prep(training = data_train_smote)
# Menerapkan SMOTE pada data training
data_train_balanced <- bake(
resep_smote,
new_data = NULL
)
# Distribusi kelas sebelum SMOTE
cat("Distribusi kelas sebelum SMOTE:\n")## Distribusi kelas sebelum SMOTE:
##
## 1 2
## 131 463
##
## Distribusi kelas setelah SMOTE:
##
## 1 2
## 463 463
# Memisahkan prediktor dan target
X_train_smote <- data_train_balanced %>%
select(-Hujan)
y_train_smote <- data_train_balanced$HujanSMOTE dilakukan untuk mengatasi ketidakseimbangan kelas pada variabel target Hujan. Sebelum SMOTE, kelas 1 berjumlah 131 pengamatan, sedangkan kelas 2 berjumlah 463 pengamatan. Setelah SMOTE, kedua kelas menjadi seimbang, masing-masing sebanyak 463 pengamatan, sehingga total data training meningkat dari 594 menjadi 926 pengamatan. Dengan demikian, SMOTE berhasil menyeimbangkan distribusi kelas pada data training.
Berdasarkan batasan masalah dan tahapan preprocessing yang telah dilakukan pada dataset curah hujan, dapat disimpulkan bahwa preprocessing bertujuan untuk meningkatkan kualitas data sebelum digunakan dalam analisis lebih lanjut. Tahapan yang dilakukan meliputi penanganan missing value menggunakan imputasi modus dan interpolasi pada variabel Keadaan_Cuaca, pembagian data menggunakan stratified splitting dengan proporsi 80% data training dan 20% data testing, serta penanganan outlier menggunakan metode capping pada variabel numerik. Selanjutnya, dilakukan standardisasi menggunakan Standard Scaler, encoding pada variabel kategorik, dan penyeimbangan kelas target Hujan menggunakan metode SMOTE. Hasil preprocessing menunjukkan bahwa data telah melalui tahapan penanganan nilai hilang, pembatasan nilai ekstrem, transformasi variabel, dan penyeimbangan kelas sesuai metode yang ditentukan. Dengan demikian, data diharapkan menjadi lebih siap untuk digunakan dalam proses pemodelan atau analisis selanjutnya.
Daniswara, A. A. A., & Nuryana, I. K. D. (2023). Data preprocessing pola pada penilaian mahasiswa program profesi guru. Journal of Informatics and Computer Science, 5(1), 97–100. https://doi.org/10.26740/jinacs.v5n01.p97-100
Faiz, M. N., Somantri, O., & Muhammad, A. W. (2022). Machine learning-based feature engineering to detect DDoS attacks. Jurnal Nasional Teknik Elektro dan Teknologi Informasi, 11(3), 176–182. https://doi.org/10.22146/jnteti.v11i3.3423
Koukaras, P., & Tjortjis, C. (2025). Data preprocessing and feature engineering for data mining: Techniques, tools, and best practices. AI, 6(10), Article 257. https://doi.org/10.3390/ai6100257
Mumuni, A., & Mumuni, F. (2025). Automated data processing and feature engineering for deep learning and big data applications: A survey. Journal of Information and Intelligence, 3(2), 113–153. https://doi.org/10.1016/j.jiixd.2024.01.002
Rahmadeyan, A., & Mustakim. (2023). Seleksi fitur pada supervised learning: Klasifikasi prestasi belajar mahasiswa saat dan pasca pandemi COVID-19. Jurnal Nasional Teknologi dan Sistem Informasi, 9(1), 21–32. https://doi.org/10.25077/TEKNOSI.v9i1.2023.21-32