Perkembangan teknologi menghasilkan data dalam jumlah besar yang kini dimanfaatkan machine learning untuk menemukan pola dan mendukung pengambilan keputusan. Namun, data mentah jarang berada dalam kondisi siap pakai dan harus diolah dengan baik sebelum dimodelkan. Salah satu masalah yang paling sering muncul adalah missing value, yang dapat memengaruhi hasil analisis sehingga perlu ditangani, misalnya dengan teknik imputasi (Baihaqi dkk., 2023).
Selain itu, distribusi kelas pada data sering tidak seimbang, sehingga jumlah data pada satu kelas jauh lebih sedikit daripada kelas lainnya. Kondisi ini berdampak buruk pada hasil klasifikasi karena model cenderung kurang mengenali kelas minoritas. Penerapan metode SMOTE terbukti dapat meningkatkan akurasi beberapa algoritma klasifikasi pada data yang tidak seimbang (Syukron dkk., 2023).
Data juga perlu disiapkan melalui penanganan outlier, penyamaan skala (scaling), dan pengubahan variabel kategoris menjadi numerik (encoding), yang secara keseluruhan dikenal sebagai feature engineering. Skala fitur yang tidak seimbang dapat menghambat kinerja algoritma sehingga normalisasi data menjadi langkah yang penting (Allorerung dkk., 2024). Oleh karena itu, praktikum ini dilakukan agar mahasiswa memahami konsep sekaligus mampu menerapkan teknik feature engineering menggunakan RStudio.
Missing values adalah permasalahan ketika terdapat data yang tidak lengkap atau hilang. Missing values umum terjadi karena beberapa alasan, seperti kerusakan alat, perhitungan yang tidak akurat, data yang tidak tercatat, dan berbagai kendala teknis lainnya. Data hilang dapat menghambat proses analisis karena menyebabkan hasil analisis menjadi kurang efisien dan menurunkan akurasi (Prasetya dkk., 2023).
Berdasarkan mekanismenya, data hilang dibedakan menjadi tiga jenis, yaitu Missing Completely at Random (MCAR), ketika data hilang sepenuhnya secara acak dan tidak berhubungan dengan atribut lain; Missing at Random (MAR), ketika kehilangan data berhubungan dengan atribut lain yang diamati; serta Missing Not at Random (MNAR), ketika kehilangan data bergantung pada nilai data itu sendiri. Oleh karena itu, pemilihan metode penanganan perlu mempertimbangkan mekanisme data hilang agar hasil analisis tetap dapat diandalkan (Widyawati, 2025). Penanganan missing values dapat dilakukan menggunakan metode konvensional, seperti imputasi rata-rata dan nilai maksimum, maupun metode modern berbasis data mining, seperti K-Nearest Neighbors (KNN) dan Neural Network. Metode konvensional relatif sederhana, tetapi berisiko menimbulkan masalah lain dalam analisis (Prasetya dkk., 2023).
Kardinalitas merupakan jumlah kategori atau nilai unik yang terdapat dalam suatu variabel kategorik. Tingkat kardinalitas perlu diperhatikan dalam proses feature engineering, terutama ketika menerapkan teknik One-Hot Encoding. Penggunaan One-Hot Encoding pada variabel dengan kardinalitas tinggi dapat menghasilkan vektor fitur berdimensi tinggi sehingga meningkatkan jumlah kolom dalam dataset. Oleh karena itu, pengelolaan variabel dengan kardinalitas tinggi diperlukan agar proses pengolahan data lebih efisien sebelum pemodelan (Faqih & Sabita, 2025).
Data splitting merupakan proses pembagian dataset menjadi data pelatihan (training data) dan data pengujian (testing data) untuk mengevaluasi kemampuan model dalam memprediksi data yang belum pernah dipelajari. Proporsi pembagian data umumnya berkisar antara 70–80% untuk data pelatihan dan 20–30% untuk data pengujian. Rasio 80:20 dapat digunakan untuk menyediakan data yang cukup dalam proses pelatihan sekaligus evaluasi model, tetapi pemilihannya tetap perlu disesuaikan dengan karakteristik dan ukuran dataset yang digunakan (Alviona dkk, 2023).
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 (misinput), 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. (Fransiska, 2026).
Data scaling merupakan tahap prapemrosesan yang bertujuan menyamakan skala nilai antarfitur. Proses ini dilakukan agar perbedaan rentang nilai antarfitur tidak memengaruhi proses pembelajaran algoritma secara berlebihan. Metode yang umum digunakan meliputi Min-Max Normalization dan standardisasi Z-Score (Ambarwari dkk., 2020).
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 (Fransiska, 2026).
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 (Fransiska, 2026).
Penelitian ini merupakan penelitian terapan dengan pendekatan kuantitatif. Jenis data yang digunakan adalah data kuantitatif, berupa data hasil pengamatan kondisi cuaca yang terdiri atas variabel suhu, kelembapan, kecepatan angin, keadaan cuaca, dan hujan. Data yang digunakan merupakan data sekunder yang diperoleh dari Asisten Praktikum. Selanjutnya, data dianalisis secara statistik menggunakan program R.
Variabel yang digunakan dalam penelitian ini terdiri dari variabel target dan variabel prediktor. Variabel Hujan merupakan variabel target dengan dua kategori, yaitu kode 1 dan 2. Variabel prediktornya adalah Suhu, Kelembapan, Keadaan_Cuaca, dan Kecepatan_Angin. Suhu menunjukkan suhu udara, Kelembapan menunjukkan tingkat kelembapan udara, Keadaan_Cuaca menunjukkan kondisi cuaca berdasarkan kode yang kemudian dikelompokkan menjadi Keadaan_Cuaca_reduced, sedangkan Kecepatan_Angin menunjukkan kecepatan angin hasil pengamatan.
Berikut merupakan algoritma pengolahan data: 1. Mulai. 2. Impor dan eksplorasi data. 3. Tangani missing value. 4. Reduksi kategori Keadaan_Cuaca. 5. Bagi data training 80% dan testing 20%. 6. Tangani outlier dengan IQR. 7. Lakukan scaling dan one-hot encoding. 8. Terapkan SMOTE pada data training. 9. Selesai.
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## Attaching package: 'recipes'
## The following object is masked from 'package:stats':
##
## step
##
## Attaching package: 'e1071'
## The following object is masked from 'package:rsample':
##
## permutations
##
## Attaching package: 'ggplot2'
## The following object is masked from 'package:e1071':
##
## element
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
## # 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 ...
Interpretasi: Dataset berisi 743 observasi dengan 5 variabel. Seluruh variabel terbaca dengan tipe data numerik. Variabel hujan diubah menjadi faktor karena berperan sebagai target klasifikasi.
## 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
##
## 1 2
## 164 579
##
## 1 2
## 22.07 77.93
Interpretasi: Statistik deskriptif menunjukkan bahwa Keadaan_Cuaca memiliki sebaran menceng ke kanan dan berupa kode kategori. Missing value terdapat pada Keadaan_Cuaca dan Kecepatan_Angin, sedangkan kelas Hujan tidak seimbang, yaitu kelas 2 sebesar 77,93% dan kelas 1 sebesar 22,07%, sehingga diperlukan penanganan missing value dan SMOTE.
## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0 0 0 9 314
## Hujan Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
## 0.00 0.00 0.00 1.21 42.26
## # 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
Interpretasi: Missing value terdapat pada Keadaan_Cuaca sebanyak 9 data (1,21%) dan Kecepatan_Angin sebanyak 314 data (42,26%), sedangkan variabel lainnya lengkap.
# Penanganan Missing Value
data_awal <- data
# 1. Mean Imputation Kecepatan_Angin
mean_angin <- mean(data_awal$Kecepatan_Angin, na.rm=TRUE)
jumlah_na <- sum(is.na(data_awal$Kecepatan_Angin))
data$Kecepatan_Angin[is.na(data$Kecepatan_Angin)] <- mean_angin
cat("Mean Imputasi:", round(mean_angin, 2), "\n")## Mean Imputasi: 6.66
## Jumlah Data Diimputasi: 314
## NA Setelah Imputasi: 0
# 2. Interpolasi Keadaan_Cuaca
na_awal <- sum(is.na(data_awal$Keadaan_Cuaca))
data$Keadaan_Cuaca <- na.approx(data$Keadaan_Cuaca, na.rm=FALSE)
cat("NA Keadaan_Cuaca Sebelum:", na_awal, "\n")## NA Keadaan_Cuaca Sebelum: 9
## NA Keadaan_Cuaca Sesudah: 0
# 3. Dampak Imputasi
hasil <- data.frame(
Kondisi = c("Sebelum", "Sesudah"),
Mean = c(mean(data_awal$Kecepatan_Angin, na.rm=TRUE),
mean(data$Kecepatan_Angin, na.rm=TRUE)),
SD = c(sd(data_awal$Kecepatan_Angin, na.rm=TRUE),
sd(data$Kecepatan_Angin, na.rm=TRUE))
)
print(transform(hasil, Mean=round(Mean, 4), SD=round(SD, 4)))## Kondisi Mean SD
## 1 Sebelum 6.655 3.3527
## 2 Sesudah 6.655 2.5463
Interpretasi: 1. Interpolasi mengisi 9 nilai hilang pada variabel Keadaan_Cuaca hingga tidak ada NA. 2. Mean imputation mengisi 314 nilai hilang pada Kecepatan_Angin menggunakan rata-rata 6,655. 3. Mean tetap, sedangkan simpangan baku turun dari 3,353 menjadi 2,546 karena imputasi mengurangi variasi data.
## # 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
## [1] 1.0 1.5 2.0 3.0 5.0 10.0 13.0 14.0 15.0 16.0 17.0 21.0 29.0 49.0 56.0
## [16] 60.0 61.0 62.0 63.0 65.0 91.0 95.0 97.0
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
labels <- 0:9
df_clean$Keadaan_Cuaca_reduced <- cut(
df_clean$Keadaan_Cuaca,
breaks = bins,
labels = labels,
right = TRUE,
include.lowest = TRUE
)
cat("--- Hasil Perbandingan ---\n")## --- Hasil Perbandingan ---
## # A tibble: 10 × 2
## Keadaan_Cuaca Keadaan_Cuaca_reduced
## <dbl> <fct>
## 1 5 0
## 2 1 0
## 3 1 0
## 4 2 0
## 5 1 0
## 6 1 0
## 7 3 0
## 8 2 0
## 9 2 0
## 10 2 0
##
## Jumlah kategori asli : 23
##
## Jumlah kategori reduced : 7
##
##
## Frekuensi Kategori Reduced:
##
## 0 1 2 3 4 5 6 7 8 9
## 523 48 46 0 1 28 71 0 0 26
Interpretasi: Variabel Keadaan_Cuaca memiliki 20 nilai unik yang dikelompokkan ke dalam interval lebar 10 dan diberi label 0–9. Hasil reduksi menunjukkan 6 kategori terisi, dengan mayoritas observasi berada pada kategori 0 sebanyak 519 data. Beberapa kategori tidak memiliki observasi, sedangkan 9 data bernilai NA karena berada di luar rentang interval yang ditentukan atau memiliki nilai hilan
# 1. Masukkan kolom hasil reduksi ke data
data$Keadaan_Cuaca_reduced <- df_clean$Keadaan_Cuaca_reduced
# 2. Shuffle Split 80:20
set.seed(200)
split_shuffle <- initial_split(data, prop = 0.8)
train <- training(split_shuffle)
test <- testing(split_shuffle)
y_train <- train$Hujan
y_test <- test$Hujan
X_train <- train %>% select(-Hujan)
X_test <- test %>% select(-Hujan)
# 3. Samakan Level Kategori
all_levels <- levels(df_clean$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)
# 4. Ukuran Data dan Distribusi Kelas
cat("Training:", nrow(X_train), "observasi |", ncol(X_train), "variabel\n")## Training: 594 observasi | 5 variabel
## Testing : 149 observasi | 5 variabel
##
## Distribusi Kelas Training (%):
## y_train
## 1 2
## 21.55 78.45
##
## Distribusi Kelas Testing (%):
## y_test
## 1 2
## 24.16 75.84
Interpretasi: Data dibagi secara acak (shuffle
splitting, set.seed(200)) menjadi 594 observasi data latih
dengan proporsi pembagian data latih (80%) dan 149 data uji (20%). Kedua
subset didominasi kelas 2, sehingga ketidakseimbangan kelas ditangani
menggunakan SMOTE. Tahap berikutnya menggunakan parameter dari data
latih untuk menghindari data leakage.
# 1. Deteksi Outlier dengan IQR
list_num <- c("Suhu", "Kelembapan", "Kecepatan_Angin")
batas <- lapply(X_train[list_num], function(x) {
q1 <- quantile(x, 0.25, na.rm = TRUE)
q3 <- quantile(x, 0.75, na.rm = TRUE)
iqr <- q3 - q1
c(Bawah = q1 - 1.5 * iqr, Atas = q3 + 1.5 * iqr)
})
outliers <- data.frame(
Variabel = list_num,
Batas_Bawah = sapply(batas, `[`, 1),
Batas_Atas = sapply(batas, `[`, 2),
Jumlah_Outlier = sapply(seq_along(list_num), function(i) {
x <- X_train[[list_num[i]]]
sum(x < batas[[i]][1] | x > batas[[i]][2], na.rm = TRUE)
})
)
print(outliers)## Variabel Batas_Bawah Batas_Atas Jumlah_Outlier
## Suhu.Bawah.25% Suhu 17.4 35.8 0
## Kelembapan.Bawah.25% Kelembapan 46.5 122.5 0
## Kecepatan_Angin.Bawah.25% Kecepatan_Angin 2.0 10.0 50
# 2. Skewness Sebelum Capping
skew_sebelum <- sapply(X_train[list_num], skewness, na.rm = TRUE)
cat("\nSkewness Sebelum Capping:\n")##
## Skewness Sebelum Capping:
## Suhu Kelembapan Kecepatan_Angin
## 0.279 -0.558 0.837
# 3. Capping pada Data Latih dan Uji
X_train_capped <- X_train
X_test_capped <- X_test
for (i in seq_along(list_num)) {
kol <- list_num[i]
X_train_capped[[kol]] <- Winsorize(X_train[[kol]], val = batas[[i]])
X_test_capped[[kol]] <- Winsorize(X_test[[kol]], val = batas[[i]])
}
cat("\nRingkasan Sebelum Capping:\n")##
## Ringkasan Sebelum Capping:
## Suhu Kelembapan Kecepatan_Angin
## Min. :22.60 Min. : 52 Min. : 2.000
## 1st Qu.:24.30 1st Qu.: 75 1st Qu.: 5.000
## Median :26.00 Median : 86 Median : 6.655
## Mean :26.54 Mean : 84 Mean : 6.642
## 3rd Qu.:28.90 3rd Qu.: 94 3rd Qu.: 7.000
## Max. :31.60 Max. :100 Max. :21.000
##
## Ringkasan Sesudah Capping:
## Suhu Kelembapan Kecepatan_Angin
## Min. :22.60 Min. : 52 Min. : 2.000
## 1st Qu.:24.30 1st Qu.: 75 1st Qu.: 5.000
## Median :26.00 Median : 86 Median : 6.655
## Mean :26.54 Mean : 84 Mean : 6.447
## 3rd Qu.:28.90 3rd Qu.: 94 3rd Qu.: 7.000
## Max. :31.60 Max. :100 Max. :10.000
# 4. Skewness Sesudah Capping
skew_sesudah <- sapply(X_train_capped[list_num], skewness, na.rm = TRUE)
cat("\nPerbandingan Skewness:\n")##
## Perbandingan Skewness:
## Sebelum Sesudah
## Suhu 0.279 0.279
## Kelembapan -0.558 -0.558
## Kecepatan_Angin 0.837 -0.163
# 5. Visualisasi Sebelum dan Sesudah Capping
for (kol in list_num) {
p1 <- ggplot(X_train, aes(x = .data[[kol]])) +
geom_histogram(bins = 30, fill = "#008080", color = "black") +
labs(title = paste(kol, "- Sebelum Capping"), x = kol, y = "Frekuensi") +
theme_minimal()
p2 <- ggplot(X_train_capped, aes(x = .data[[kol]])) +
geom_histogram(bins = 30, fill = "#008080", color = "black") +
labs(title = paste(kol, "- Sesudah Capping"), x = kol, y = "Frekuensi") +
theme_minimal()
print(grid.arrange(p1, p2, ncol = 2))
}## TableGrob (1 x 2) "arrange": 2 grobs
## z cells name grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## TableGrob (1 x 2) "arrange": 2 grobs
## z cells name grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## TableGrob (1 x 2) "arrange": 2 grobs
## z cells name grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
Interpretas 1. Berdasarkan aturan IQR, outlier
ditemukan pada Kecepatan_Angin akibat IQR yang menyempit
setelah imputasi rata-rata pada sekitar 42% data.
Setelah capping, nilai maksimum Kecepatan_Angin
turun dari 21 menjadi 10 dan seluruh outlier berhasil ditangani tanpa
menghapus observasi.
Skewness Kecepatan_Angin berubah dari 0,837 menjadi
−0,163, sedangkan Suhu dan Kelembapan tetap
pada 0,279 dan −0,558.
Boxplot menunjukkan outlier Kecepatan_Angin tidak
lagi muncul setelah capping, sementara histogram Suhu dan
Kelembapan tidak berubah.
# Parameter Robust Scaler dihitung dari data latih
median_val <- sapply(X_train_capped[list_num], median, na.rm = TRUE)
iqr_val <- sapply(X_train_capped[list_num], IQR, na.rm = TRUE)
rbind(Median = median_val, IQR = iqr_val)## Suhu Kelembapan Kecepatan_Angin
## Median 26.0 86 6.655012
## IQR 4.6 19 2.000000
X_train_scale <- X_train_capped
X_test_scale <- X_test_capped
for (col in list_num) {
X_train_scale[[col]] <- (X_train_capped[[col]] - unname(median_val[col])) / unname(iqr_val[col])
X_test_scale[[col]] <- (X_test_capped[[col]] - unname(median_val[col])) / unname(iqr_val[col])
}
head(X_train_scale)## # A tibble: 6 × 5
## Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin Keadaan_Cuaca_reduced
## <dbl> <dbl> <dbl> <dbl> <fct>
## 1 -0.500 0.579 61 0 6
## 2 1.09 -0.947 2 1.67 0
## 3 0.0870 -0.263 3 -0.828 0
## 4 1.15 -1.53 2 1.17 0
## 5 0.674 -0.421 2 0 0
## 6 0.391 -0.368 2 -1.83 0
##
## Median & IQR data latih setelah scaling:
## Suhu Kelembapan Kecepatan_Angin
## Median 0 0 0
## IQR 1 1 1
## Suhu Kelembapan Kecepatan_Angin
## Min. :-0.7391 Min. :-1.7895 Min. :-2.3275
## 1st Qu.:-0.3696 1st Qu.:-0.5789 1st Qu.:-0.8275
## Median : 0.0000 Median : 0.0000 Median : 0.0000
## Mean : 0.1177 Mean :-0.1053 Mean :-0.1041
## 3rd Qu.: 0.6304 3rd Qu.: 0.4211 3rd Qu.: 0.1725
## Max. : 1.2174 Max. : 0.7368 Max. : 1.6725
## Suhu Kelembapan Kecepatan_Angin
## Min. :-0.69565 Min. :-1.6316 Min. :-2.32751
## 1st Qu.:-0.34783 1st Qu.:-0.6842 1st Qu.:-0.32751
## Median :-0.04348 Median : 0.0000 Median : 0.00000
## Mean : 0.11716 Mean :-0.1363 Mean :-0.05804
## 3rd Qu.: 0.65217 3rd Qu.: 0.4211 3rd Qu.: 0.67249
## Max. : 1.30435 Max. : 0.7368 Max. : 1.67249
X_train_scale %>%
dplyr::select(all_of(list_num)) %>%
pivot_longer(everything(), names_to = "Variabel", values_to = "Nilai") %>%
ggplot(aes(x = Variabel, y = Nilai, fill = Variabel)) +
geom_boxplot() +
labs(title = "Boxplot Data Latih Setelah Robust Scaler") +
theme_minimal() +
theme(legend.position = "none")
Interpretasi: 1. Robust Scaler menggunakan median dan
IQR data latih sebagai parameter transformasi, dengan median awal Suhu,
Kelembapan, dan Kecepatan_Angin masing-masing 26, 86, dan 6,655 serta
IQR 4,6, 19, dan 2.
Setelah scaling, median ketiga variabel menjadi 0 dan IQR menjadi 1; nilai negatif menunjukkan data di bawah median, sedangkan nilai positif menunjukkan data di atas median.
Parameter data latih diterapkan pada data uji untuk mencegah data leakage, sementara penggunaan median dan IQR membuat metode ini relatif tahan terhadap outlier.
## 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>
## # 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>
## Dimensi X_train_encoded : 594 10
## Dimensi X_test_encoded : 149 10
## [1] "Keadaan_Cuaca_reduced_X0" "Keadaan_Cuaca_reduced_X1"
## [3] "Keadaan_Cuaca_reduced_X2" "Keadaan_Cuaca_reduced_X3"
## [5] "Keadaan_Cuaca_reduced_X4" "Keadaan_Cuaca_reduced_X5"
## [7] "Keadaan_Cuaca_reduced_X6" "Keadaan_Cuaca_reduced_X7"
## [9] "Keadaan_Cuaca_reduced_X8" "Keadaan_Cuaca_reduced_X9"
Interpretasi: One-hot encoding mengubah variabel Keadaan_Cuaca_reduced menjadi 10 kolom biner yang mewakili kategori 0–9, dengan nilai 1 untuk kategori yang sesuai dan 0 untuk kategori lainnya. Data latih terdiri atas 594 baris dan data uji 149 baris dengan struktur kolom yang sama. Kategori yang tidak memiliki observasi, seperti 3, 7, dan 8, menghasilkan kolom bernilai 0 seluruhnya, tetapi tetap dipertahankan agar struktur data latih dan data uji konsisten.
##4.8 Handling Imbalance Data (SMOTE)
# 1. Gabungkan Fitur dan Target
X_train_final <- bind_cols(X_train_scale[list_num], X_train_encoded) %>%
mutate(Hujan = factor(y_train))
X_test_final <- bind_cols(X_test_scale[list_num], X_test_encoded) %>%
mutate(Hujan = factor(y_test, levels = levels(X_train_final$Hujan)))
# 2. Distribusi Kelas Sebelum SMOTE
cat("Sebelum SMOTE:\n")## Sebelum SMOTE:
##
## 1 2
## 128 466
##
## 1 2
## 21.55 78.45
# 3. SMOTE pada Data Latih
set.seed(200)
resep_smote <- recipe(Hujan ~ ., data = X_train_final) %>%
step_smote(Hujan, over_ratio = 1, neighbors = 5)
prep_smote <- prep(resep_smote, training = X_train_final)
train_smote <- bake(prep_smote, new_data = NULL)
cat("\nSesudah SMOTE:\n")##
## Sesudah SMOTE:
##
## 1 2
## 466 466
##
## 1 2
## 50 50
##
## Dimensi Data Latih:
## Sebelum: 594 14 | Sesudah: 932 14
##
## Distribusi Kelas Data Uji:
##
## 1 2
## 36 113
# 4. Visualisasi Distribusi Kelas
dist_kelas <- bind_rows(
data.frame(Tahap = "Sebelum SMOTE", Hujan = X_train_final$Hujan),
data.frame(Tahap = "Sesudah SMOTE", Hujan = train_smote$Hujan)
)
ggplot(dist_kelas, aes(x = Hujan, fill = Hujan)) +
geom_bar() +
geom_text(stat = "count", aes(label = after_stat(count)), vjust = -0.3) +
facet_wrap(~Tahap) +
labs(title = "Distribusi Kelas Hujan Sebelum dan Sesudah SMOTE",
x = "Kelas Hujan", y = "Frekuensi") +
theme_minimal() +
theme(legend.position = "none")
Interpretasi: Sebelum SMOTE, data latih didominasi
kelas 2 sebanyak 466 data atau 78,45%, sedangkan kelas 1 berjumlah 128
data atau 21,55%. Setelah SMOTE, kedua kelas menjadi seimbang dengan
masing-masing 466 data, sehingga jumlah data latih meningkat dari 594
menjadi 932. SMOTE hanya diterapkan pada data latih, sedangkan 149 data
uji tetap dipertahankan tanpa perubahan.
Feature engineering merupakan tahapan pengolahan data yang mencakup berbagai teknik untuk meningkatkan kualitas data sebelum pemodelan. Teknik yang digunakan meliputi penanganan missing value, reduksi kardinalitas, deteksi dan penanganan pencilan, encoding, penskalaan, serta penyeimbangan kelas. Setiap teknik memiliki fungsi berbeda sesuai dengan karakteristik dan permasalahan yang ditemukan pada data.
Penerapan teknik feature engineering dilakukan menggunakan RStudio melalui beberapa tahapan pengolahan data. Penanganan missing value dilakukan dengan imputasi rata-rata dan interpolasi, sedangkan pencilan ditangani menggunakan metode capping. Selanjutnya, reduksi kardinalitas, one-hot encoding, Robust Scaling, dan SMOTE diterapkan untuk mempersiapkan data sebelum proses pemodelan.
Berdasarkan hasil pengolahan dataset curah hujan yang terdiri atas 743 observasi, data dibagi menjadi 594 observasi untuk data latih dan 149 observasi untuk data uji. Proses transformasi mencakup penanganan nilai hilang, pengendalian pencilan pada variabel kecepatan angin, penskalaan variabel numerik, serta encoding variabel kategorik. Penerapan SMOTE pada data latih juga berhasil menyeimbangkan jumlah kelas dari 466 data kelas 2 dan 128 data kelas 1 menjadi masing-masing 466 observasi, sehingga data lebih siap digunakan untuk tahap pemodelan.
Ambarwari, A., Adrian, Q. J., & Herdiyeni, Y. (2020). Analisis pengaruh data scaling terhadap performa algoritme machine learning untuk identifikasi tanaman. Jurnal RESTI (Rekayasa Sistem dan Teknologi Informasi), 4(1), 117–122.
Alviola, N. A., Fathurrahman, Z., Rifai, R. N., & Afrah, A. S. (2023). Sistem diagnosa penyakit liver menggunakan metode artificial neural network: Studi berdasarkan dataset Indian Liver Patient Dataset. Jurnal Informatika: Jurnal Pengembangan IT, 8(3), 308–314.
Baihaqi, M. R., Padilah, T. N., & Jajuli, M. (2023). Implementasi metode imputasi mean dan single center imputation chained. Jurnal JTIK (Jurnal Teknologi Informasi dan Komunikasi), 7(4).
Faiq, H. A., & Sabita, H. (2025). Pengembangan model deep learning untuk pengenalan wajah pada sistem keamanan. Teknika, 18(1), 197–209.
Fransiska, H. (2026). Machine learning and modern prediction. Laboratorium Matematika dan Ilmu Pengetahuan Alam, Universitas Bengkulu.
Prasetya, M. R. A., Priyatno, A. M., & Nurhaeni. (2023). Penanganan imputasi missing values pada data time series dengan menggunakan metode data mining. Jurnal Informasi dan Teknologi, 5(2), 56–62.
Syukron, A., Sardiarinto, S., Saputro, E., & Widodo, P. (2023). Penerapan metode SMOTE untuk mengatasi ketidakseimbangan kelas pada prediksi gagal jantung. Jurnal Teknologi Informasi dan Terapan, 10(1), 47–50.
Widyawati, A. S., Fitrianto, A., & Silvianti, P. (2025). Performance of multivariate missing data imputation methods on climate data. Journal of Applied Informatics and Computing (JAIC), 9(6), 3953–3963.