Perkembangan teknologi informasi menyebabkan jumlah data yang tersedia semakin meningkat dan dapat dimanfaatkan untuk berbagai kebutuhan analisis. Salah satu pemanfaatannya adalah machine learning, yaitu metode yang memungkinkan komputer mempelajari pola dari data untuk menghasilkan prediksi atau klasifikasi. Namun, data yang diperoleh dari berbagai sumber tidak selalu dapat langsung digunakan dalam pemodelan karena memiliki tipe, skala, dan karakteristik yang berbeda. Oleh karena itu, diperlukan proses pengolahan data agar data lebih sesuai untuk digunakan dalam model machine learning (Faiz dkk., 2022).
Salah satu tahapan penting dalam pengolahan data adalah feature engineering atau rekayasa fitur. Feature engineering merupakan proses mengolah fitur yang tersedia atau membentuk fitur baru agar informasi dalam data dapat digunakan dengan lebih baik dalam proses pemodelan. Teknik ini dapat dilakukan melalui transformasi data, pengubahan variabel kategorik menjadi numerik, pembentukan fitur baru, serta pemilihan fitur yang relevan. Faiz dkk (2022) menerapkan feature engineering untuk mengolah fitur dalam pendeteksian serangan DDoS, sedangkan Aryanti dan Mahendra (2023) menerapkan feature engineering berupa TF-IDF pada analisis sentimen dan memperoleh hasil klasifikasi yang baik menggunakan Support Vector Machine.
Berdasarkan hal tersebut, praktikum Feature Engineering dilakukan untuk memahami proses pengolahan dan pembentukan fitur sebelum data digunakan dalam pemodelan machine learning. Praktikum ini dilakukan dengan menerapkan beberapa teknik feature engineering pada data serta mengamati perubahan yang dihasilkan setelah proses pengolahan fitur. Dengan adanya praktikum ini, mahasiswa diharapkan dapat memahami fungsi feature engineering dan pentingnya pengolahan fitur dalam mempersiapkan data sebelum digunakan dalam proses pemodelan machine learning.
Machine learning merupakan bagian dari kecerdasan buatan yang memungkinkan komputer mempelajari pola dari data dan menggunakan pola tersebut untuk menghasilkan prediksi atau keputusan. Dalam penerapannya, kualitas data yang digunakan menjadi salah satu hal penting karena model mempelajari pola berdasarkan fitur yang tersedia pada data. Oleh karena itu, data perlu dipersiapkan sebelum digunakan dalam proses pemodelan (Faiz dkk., 2022). Secara umum, machine learning dapat digunakan untuk berbagai kebutuhan, seperti klasifikasi, regresi, dan pengelompokan. Setiap metode memiliki kebutuhan data yang berbeda sehingga proses persiapan data perlu disesuaikan dengan karakteristik model dan tujuan analisis.
Feature engineering merupakan proses mengubah data mentah menjadi fitur yang dapat digunakan dalam algoritma machine learning. Proses ini dilakukan dengan memilih dan mengolah fitur yang berpengaruh terhadap pemodelan. Tujuannya adalah menyederhanakan proses pengolahan data serta membantu meningkatkan kinerja model (Fransiska., 2026).
Teknik-teknik yang dilakukan agar data lebih sesuai untuk digunakan dalam proses pemodelan machine learning yaitu feature engineering. Teknik feature engineering yang digunakan yaitu sebagai berikut (Frasiska, 2026): 1. Handling missing value, yaitu menangani data yang tidak memiliki nilai. 2. Kardinalitas, yaitu melihat jumlah nilai unik pada variabel kategorik. 3. Splitting data, yaitu membagi data menjadi data training dan testing. 4. Handling outlier, yaitu menangani data yang memiliki nilai sangat berbeda dari sebagian besar data. 5. Scaling data untuk menyamakan skala antarvariabel. 6. Encoding untuk mengubah data kategorik atau nonnumerik menjadi bentuk numerik. 7. Imbalanced dataset untuk menangani kondisi ketika jumlah data antar kelas tidak seimbang.
Jenis data yang digunakan dalam penelitian ini adalah data kuantitatif. Data kuantitatif merupakan data berbentuk angka yang dapat dianalisis. Sumber data dalam penelitian ini yaitu data sekunder. Data sekunder yakni data yang diperoleh secara tidak langsung oleh peneliti. Data penelitian ini yaitu data curah hujan yang diperoleh dari Asisten Praktikum.
Variabel penelitian adalah suatu atribut atau sifat atau nilai dari orang, obyek yang ditetapkan oleh peneliti untuk dipelajari dan ditarik kesimpulannya. Pada penelitian ini terdapat 5 variabel yang digunakan. Variabel tersebut yaitu hujan, suhu, kelembapan, keadaan cuaca dan kecepatan angin dengan jumlah observasi sebanyak 743 observasi.
Pada ahap awal yang dilakukan adalah membuat semua package yang diperlukan untuk membantu proses analisis pada RStudio. Selanjutnya, melaukuan proses import. Kemudian dilakukan pemeriksaan awal terhadap struktur dan karakteristik dataset. Berikut adalah sintaks yang digunakan:
##
## 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 output tersebut, dataset curah hujan memiliki 743 observasi dan 5 variabel, yaitu hujan, suhu, kelembapan, keadaan cuaca, dan kecepatan angin. Variabel hujan memiliki nilai minimum 1 dan maksimum 2 dengan rata-rata 1,779. Variabel suhu memiliki rata-rata 26,54°C, dengan suhu minimum 22,60°C dan maksimum 32°C. Variabel kelembapan memiliki rata-rata 83,88%, dengan nilai minimum 52% dan maksimum 100%. Sementara itu, variabel Keadaan cuaca memiliki nilai minimum 1 dan maksimum 97, dengan rata-rata 15,11.
Permasalahan missing value ditemukan pada variabel Keadaan cuaca sebanyak 9 data dan kecepatan angin sebanyak 314 data. Dengan demikian, variabel kecepatan angin memiliki jumlah missing value terbanyak, yaitu sekitar 42,26% dari keseluruhan observasi. Kondisi ini perlu ditangani melalui proses imputasi sebelum analisis lebih lanjut agar data dapat digunakan secara lebih lengkap.
## 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
df_imp <- data
# Interpolasi pada Keadaan_Cuaca
df_imp$Keadaan_Cuaca <- na.approx(
df_imp$Keadaan_Cuaca,
na.rm = FALSE,
rule = 2
)
# Imputasi modus 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 missing value
colSums(is.na(df_imp)) ## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 0 0
Berdasarkan hasil pemeriksaan tersebut, penanganan nilai hilang dilakukan menggunakan metode yang berbeda sesuai dengan jenis variabelnya. Variabel keadaan cuaca ditangani menggunakan interpolasi (na.approx) dengan memperkirakan nilai yang hilang berdasarkan pengamatan di sekitarnya. Setelah proses tersebut, seluruh nilai hilang pada variabel ini berhasil diatasi. Adapun variabel kecepatan angin ditangani menggunakan imputasi modus sesuai dengan batasan masalah, dengan nilai modus sebesar 3 untuk menggantikan seluruh 314 data yang hilang. Dengan demikian, seluruh variabel tidak lagi memiliki nilai hilang dan data siap digunakan untuk tahap analisis selanjutnya.
## # 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_imp$Keadaan_Cuaca_reduced <- cut(
df_imp$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 30.6 67 2 14 0
## 2 2 23.5 96 2 3 0
## 3 2 26.7 86 61 10 6
## 4 2 31 60 2 7 0
## 5 2 30.3 72 1 10 0
## 6 2 26 92 2 3 0
## 7 2 28.8 71 2 7 0
## 8 2 29.1 68 2 9 0
## 9 2 23.5 97 2 3 0
## 10 2 23.4 98 61 3 6
##
## --- 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 merupakan jumlah kategori unik yang terdapat dalam suatu variabel. Setelah proses interpolasi, variabel Keadaan_Cuaca memiliki 23 kategori unik dengan rentang nilai 1 hingga 97, termasuk nilai pecahan 1,5. Banyaknya kategori tersebut dapat menyulitkan proses pengodean, sehingga dilakukan reduksi kardinalitas menggunakan teknik binning melalui fungsi cut(). Nilai Keadaan_Cuaca dibagi menjadi 10 interval dengan lebar masing-masing 10 dan format (a, b], kemudian diberi label 0 hingga 9. Penggunaan argumen include.lowest = TRUE bertujuan agar nilai batas terendah tetap masuk ke dalam interval pertama. Hasil pengelompokan ini disimpan dalam variabel baru bernama Keadaan_Cuaca_reduced.
Setelah reduksi dilakukan, jumlah kategori yang terisi berkurang menjadi 7, yaitu kategori 0, 1, 2, 4, 5, 6, dan 9. Sementara itu, kategori 3, 7, dan 8 tidak ditemukan karena tidak terdapat pengamatan pada interval tersebut. Kategori 0 menjadi kategori yang paling dominan karena nilai kode asli 1, 2, dan 3 paling sering muncul dalam data. Variabel hasil reduksi tetap bertipe factor dengan 10 level, termasuk kategori yang tidak terisi. Hal ini bertujuan untuk menjaga konsistensi kategori saat proses pengodean pada data training dan data testing.
set.seed(200)
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
Pada tahap berikutnya, data dibagi menjadi data training dan data testing dengan proporsi 80:20 menggunakan fungsi initial_split(). Pembagian dilakukan secara stratified berdasarkan variabel hujan sebagai target, yang kemudian dipisahkan ke dalam objek y_train dan y_test. Hasil pembagian menunjukkan bahwa data training terdiri atas 594 pengamatan, sedangkan data testing berjumlah 149 pengamatan. Proporsi kelas 1 pada data training sebesar 22,05% dan pada data testing sebesar 22,15%. Sementara itu, kelas 2 memiliki proporsi sebesar 77,95% pada data training dan 77,85% pada data testing. Perbedaan proporsi yang kecil menunjukkan bahwa pembagian data berhasil mempertahankan distribusi kelas pada kedua bagian. Namun, distribusi tersebut juga memperlihatkan adanya ketidakseimbangan kelas karena jumlah kelas 2 jauh lebih besar dibandingkan kelas 1. Oleh karena itu, diperlukan penyeimbangan kelas menggunakan metode SMOTE pada tahap selanjutnya.
## 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
# Capping
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))
}
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 pemeriksaan outlier menggunakan metode IQR,
variabel suhu dan kelembapan tidak memiliki nilai pencilan, dengan
jumlah outlier masing-masing sebanyak 0. Variabel suhu memiliki
batas bawah 17,5 dan batas atas 35,9, sedangkan variabel kelembapan
memiliki batas bawah 44 dan batas atas 124. Di sisi lain, variabel
kecepatan angin ditemukan memiliki 5 nilai pencilan, dengan batas bawah
-3 dan batas atas 13. Oleh karena itu, penanganan outlier
dilakukan melalui teknik capping pada variabel kecepatan angin,
yaitu membatasi nilai yang melebihi batas atas menjadi 13. Sementara
itu, batas bawah -3 tidak memerlukan penanganan apabila seluruh nilai
dalam data masih berada di atas batas tersebut.
Hasil visualisasi menunjukkan bahwa perubahan paling jelas terjadi pada variabel Kecepatan_Angin, yang memiliki 5 nilai outlier dengan batas bawah -3 dan batas atas 13. Pada boxplot, nilai yang berada di atas batas atas teridentifikasi sebagai pencilan. Setelah dilakukan capping, 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, teknik capping hanya diterapkan pada variabel Kecepatan_Angin karena terdapat nilai yang melebihi batas IQR. Metode ini membatasi nilai ekstrem tanpa mengurangi jumlah pengamatan dalam data training.
# 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
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]
}
round(sapply(X_train_scale[list_num], mean), 4)## Suhu Kelembapan Kecepatan_Angin
## 26.5579 83.7576 5.0690
## Suhu Kelembapan Kecepatan_Angin
## 2.5572 11.5510 2.9874
Tahap selanjutnya adalah melakukan standardisasi pada variabel numerik, yaitu suhu, kelembapan, dan Kecepatan_Angin, menggunakan metode Standard Scaler. Proses ini dilakukan dengan mengurangi setiap nilai dengan rata-rata, kemudian membaginya dengan simpangan baku yang diperoleh dari data training. Parameter tersebut selanjutnya diterapkan pada data training dan data uji agar proses standardisasi konsisten serta terhindar dari kebocoran informasi. Hasil pemeriksaan menunjukkan bahwa ketiga variabel pada data latih memiliki rata-rata sebesar 0 dan simpangan baku sebesar 1. Hasil ini menandakan bahwa standardisasi berhasil dilakukan. Setelah proses tersebut, nilai setiap variabel menunjukkan jaraknya terhadap rata-rata dalam satuan simpangan baku, sehingga perbedaan skala antarvariabel dapat diseragamkan dan data siap digunakan untuk tahap pemodelan selanjutnya.
## Encoding - One Hot Encoder
list_cat <- c("Keadaan_Cuaca_reduced")
all_levels <- levels(df_imp$Keadaan_Cuaca_reduced)
# Samakan level kategori pada data training dan testing
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_reduce…¹ Keadaan_Cuaca_reduce…²
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 23 95 3 1 0
## 2 24 90 3 1 0
## 3 26.8 77 3 1 0
## 4 29.6 62 2 1 0
## 5 30.8 56 7 1 0
## 6 30.4 57 9 1 0
## # ℹ abbreviated names: ¹Keadaan_Cuaca_reduced_X0, ²Keadaan_Cuaca_reduced_X1
## # ℹ 9 more variables: 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 berikutnya adalah melakukan pengodean (encoding) pada variabel kategorik Keadaan_Cuaca_reduced menggunakan metode One-Hot Encoding. Metode ini mengubah setiap kategori menjadi kolom indikator yang berisi nilai 0 dan 1 agar dapat digunakan dalam pemodelan machine learning. Sebelum proses pengodean, level kategori pada data training dan data testing diseragamkan untuk memastikan konsistensi kategori pada kedua bagian data. Pengodean dilakukan menggunakan fungsi recipe dari paket recipes, dengan tahapan yang disesuaikan berdasarkan data training, kemudian diterapkan pada data training dan data testing. Hasilnya menunjukkan bahwa data training terdiri atas 594 pengamatan dan 14 variabel, sedangkan data testing memiliki 149 pengamatan dan 14 variabel. Kesamaan jumlah variabel tersebut menunjukkan bahwa kedua bagian data memiliki struktur yang konsisten setelah proses encoding, sehingga siap digunakan untuk tahap pemodelan selanjutnya.
# Gabungkan fitur dan target (SMOTE membutuhkan target bertipe factor)
train_full <- X_train_encoded %>%
mutate(Hujan = factor(y_train))
set.seed(200)
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 31 55 7 1
## 2 30.9 58 10 1
## 3 24.6 90 3 1
## 4 23.1 92 3 1
## 5 31.3 59 10 1
## 6 31.2 64 10 1
## 7 27 87 3 1
## 8 25.3 93 3 1
## 9 25 94 3 1
## 10 24.7 94 3 0
## # ℹ 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 penerapan SMOTE, distribusi kelas pada data training menunjukkan ketidakseimbangan yang cukup besar. Kelas 1 sebagai kelas minoritas terdiri atas 131 observasi (22,05%), sedangkan kelas 2 sebagai kelas mayoritas berjumlah 463 observasi (77,95%) dari total 594 observasi. Ketidakseimbangan ini berpotensi menyebabkan model lebih cenderung memprediksi kelas mayoritas dibandingkan kelas minoritas.
Untuk mengatasi permasalahan tersebut, digunakan metode Synthetic Minority Over-sampling Technique (SMOTE) dengan parameter over_ratio = 1 dan neighbors = 5. Metode ini menghasilkan data sintetis untuk kelas minoritas berdasarkan lima tetangga terdekat. Sementara itu, penggunaan set.seed(200) bertujuan agar proses pembangkitan data dapat menghasilkan keluaran yang konsisten ketika dijalankan kembali.
Setelah penerapan SMOTE, jumlah observasi pada kelas 1 dan kelas 2 menjadi seimbang, masing-masing sebanyak 463 observasi dengan proporsi 50%. Proses ini menambahkan 332 observasi sintetis sehingga jumlah data training meningkat dari 594 menjadi 926 observasi. Data hasil penyeimbangan terdiri atas 14 fitur dan satu variabel target, yaitu hujan.
Penerapan SMOTE hanya dilakukan pada data training, sedangkan data testing tetap dipertahankan dalam kondisi aslinya agar evaluasi model dapat dilakukan secara objektif. Pada data testing, variabel target Hujan hanya diubah menjadi tipe factor dengan level yang disesuaikan dengan data training. Dengan demikian, data training yang telah seimbang dan data testing yang tetap merepresentasikan distribusi awal siap digunakan untuk tahap pemodelan dan evaluasi.
Feature engineering merupakan tahapan pengolahan data yang bertujuan untuk meningkatkan kualitas data sebelum digunakan dalam pemodelan machine learning. Tahapan ini mencakup penanganan nilai hilang, pencilan (outlier), standardisasi (scaling), pengodean variabel kategorik (encoding), serta penyeimbangan kelas. Teknik yang digunakan disesuaikan dengan karakteristik data dan permasalahan yang ditemukan selama proses pemeriksaan.
Penerapan feature engineering melalui RStudio dapat dilakukan menggunakan bahasa pemrograman R dengan bantuan paket, seperti dplyr dan recipes. Beberapa teknik yang dapat diterapkan antara lain capping untuk membatasi nilai ekstrem, Standard Scaler untuk menyamakan skala variabel numerik, One-Hot Encoding untuk mengubah variabel kategorik menjadi kolom numerik, serta SMOTE untuk menyeimbangkan distribusi kelas. Setiap tahapan perlu diperiksa untuk memastikan proses pengolahan berjalan dengan baik dan mencegah kebocoran informasi.
Berdasarkan hasil analisis, feature engineering yang diterapkan meliputi capping, standardisasi, encoding, dan SMOTE. Proses tersebut menghasilkan data yang telah melalui penanganan nilai ekstrem, penyamaan skala variabel numerik, pengubahan variabel kategorik menjadi fitur numerik, serta penyeimbangan kelas pada data training hingga masing-masing berjumlah 463 observasi. Dengan demikian, data training dan data testing telah siap digunakan dalam pemodelan machine learning. Data testing tetap dipertahankan tanpa penerapan SMOTE agar evaluasi model dapat mencerminkan kemampuan prediksi pada data yang tidak mengalami penyeimbangan kelas.
Aryanti, P. A. N., & Mahendra, I. B. M. (2023). Analisis Sentimen Opini Berbahasa Indonesia pada Sosial Media Menggunakan TF-IDF dan Support Vector Machine. JELIKU (Jurnal Elektronik Ilmu Komputer Udayana), 12(1), 45–52. 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. Fransiska, H., 2026. Modul Praktimum Machine Learning and Modern Prediction. Bengkulu:Universitas Bengkulu