BAB I PENDAHULUAN

1.1 Latar Belakang

   Perkembangan teknologi informasi yang semakin pesat menyebabkan jumlah data yang tersedia untuk dianalisis semakin besar dan kompleks. Kondisi tersebut mendorong penggunaan machine learning untuk memperoleh pola dan informasi yang dapat digunakan dalam berbagai permasalahan. Namun, keberhasilan suatu model machine learning tidak hanya dipengaruhi oleh algoritma yang digunakan, tetapi juga oleh kualitas dan bentuk fitur yang menjadi masukan model. Data dengan jumlah fitur yang besar dapat mengandung fitur yang tidak relevan maupun fitur yang memiliki informasi yang berulang sehingga dapat memengaruhi proses pembelajaran model(Villa-Blanco et al., 2023).
   Salah satu tahapan penting dalam pengolahan data sebelum membangun model machine learning adalah Feature engineering. Feature engineering merupakan proses mengolah dan membentuk fitur dari data yang tersedia agar informasi yang digunakan oleh model menjadi lebih representatif terhadap permasalahan yang dianalisis. Proses ini dapat mencakup transformasi fitur, pembentukan fitur baru (Feature construction atau Feature synthesis), ekstraksi fitur, serta pemilihan fitur (Feature selection). Dengan demikian, Feature engineering tidak hanya berfokus pada pengurangan jumlah fitur, tetapi juga pada bagaimana fitur dapat direpresentasikan secara lebih sesuai dengan kebutuhan model (Mumuni & Mumuni, 2025).
   Berdasarkan uraian tersebut, Feature engineering penting dilakukan untuk mempersiapkan fitur agar dapat memberikan informasi yang lebih relevan bagi model machine learning. Melalui proses transformasi, pembentukan, ekstraksi, dan seleksi fitur, data dapat direpresentasikan dengan lebih baik sehingga proses pemodelan dapat dilakukan secara lebih efektif dan efisien. Oleh karena itu, analisis mengenai Feature engineering diperlukan untuk memahami bagaimana pengolahan fitur dapat memengaruhi karakteristik data dan kinerja model machine learning.

1.2 Rumusan Masalah

   1.   Bagaimana cara konsep dari berbagai jenis Feature engineering pada RStudio?
   2.   Bagaimana cara melakukan teknik Feature engineering di program RStudio?

1.3 Tujuan

   1.   Mahasiswa mampu memahami konsep dari berbagai jenis Feature engineering pada RStudio.
   2.   Mahasiswa mampu melakukan teknik Feature engineering di program RStudio.

1.4 Batasan Masalah

   Adapun batasan masalah pada penelitian ini adalah gunakan dataset data curah hujan.xlsx untuk melakukan preprocessing data. NPM ganjil menggunakan mean imputation, shuffle Splitting, dan Robust Scaler, sedangkan NPM genap menggunakan mode imputation, stratify Splitting, dan Standard Scaler. Keduanya melakukan interpolasi pada Keadaan_Cuaca, capping pada data numerik, serta penanganan imbalance data menggunakan SMOTE. Tampilkan dan interpretasikan setiap output!

BAB II TINJAUAN PUSTAKA

2.1 Feature Engineering

   Feature engineering merupakan proses mengolah data mentah menjadi fitur yang lebih sesuai dan informatif untuk digunakan dalam pemodelan machine learning. Fitur adalah variabel atau atribut yang digunakan oleh model untuk mempelajari pola dari data. Dalam praktiknya, data mentah sering kali belum berada dalam bentuk yang optimal untuk digunakan secara langsung sehingga diperlukan proses transformasi, pembentukan, ekstraksi, atau pemilihan fitur (Mumuni & Mumuni, 2025). Feature engineering memerlukan pemahaman yang baik karena melibatkan kombinasi analisis data, pengetahuan tentang data, dan sedikit intuisi. Tujuan dari Feature engineering adalah menyederhanakan dan mempercepat transformasi data sekaligus meningkatkan akurasi model (modul). Berikut merupakan beberapa jenis Feature engineering yang harus dilakukan:

a.Handling Missing Values

 Missing Values merupakan salah satu permasalahan yang umum ditemukan pada data dunia nyata. Keberadaan Missing Values dapat memengaruhi kualitas data dan performa model machine learning sehingga diperlukan metode yang tepat untuk menanganinya (Emmanuel et al., 2021).

b.Kardinalitas

 Kardinalitas (cardinality) pada variabel kategoris mengacu pada jumlah kategori atau nilai unik yang terdapat dalam suatu variabel. Variabel kategoris dengan jumlah kategori yang relatif sedikit disebut memiliki low cardinality, sedangkan variabel dengan jumlah kategori yang banyak disebut memiliki high cardinality. Permasalahan high cardinality menjadi perhatian dalam pemodelan machine learning karena semakin banyak kategori yang dimiliki suatu variabel, semakin besar pula representasi fitur yang diperlukan ketika variabel tersebut dikonversi ke dalam bentuk numerik (Pargent et al., 2022).

c.Splitting Data

 Data Splitting merupakan salah satu tahapan penting dalam pemodelan machine learning yang dilakukan dengan membagi dataset menjadi beberapa bagian, terutama data training dan data testing. Data training digunakan untuk membangun atau melatih model, sedangkan data testing dipisahkan dari proses pelatihan dan digunakan untuk mengevaluasi kemampuan model dalam melakukan prediksi terhadap data yang belum pernah digunakan sebelumnya. Pemisahan tersebut diperlukan agar performa model dapat dievaluasi secara lebih objektif dan kemampuan generalisasi model terhadap data baru dapat diketahui (Bichri et al., 2024).

d.Handling Outlier

 Outlier atau pencilan merupakan observasi dalam suatu dataset yang memiliki karakteristik tidak biasa atau menyimpang dari pola umum yang terdapat pada sebagian besar data. Suatu observasi dapat dikategorikan sebagai Outlier apabila karakteristiknya berbeda secara signifikan dari pola yang dianggap normal. Namun, keberadaan Outlier bersifat kontekstual karena suatu observasi yang dianggap sebagai pencilan pada satu kondisi belum tentu dianggap sebagai pencilan pada kondisi lainnya (Foorthuis, 2021).

e.Scaling data

Scaling data merupakan salah satu tahap preprocessing dalam machine learning yang bertujuan untuk menyetarakan skala nilai antarfitur. Tahapan ini diperlukan karena setiap fitur dapat memiliki rentang nilai dan satuan pengukuran yang berbeda. Perbedaan skala tersebut dapat menyebabkan fitur dengan rentang nilai yang lebih besar memberikan pengaruh yang lebih dominan dalam proses pembelajaran model. Oleh karena itu, Scaling digunakan agar nilai antarfitur berada pada skala yang lebih sebanding sehingga proses pemodelan dapat berlangsung dengan lebih baik (Ahsan et al., 2021).

f.Encoding

 Feature Encoding merupakan salah satu tahap preprocessing dalam machine learning yang digunakan untuk mengubah fitur kategoris atau nonnumerik menjadi bentuk numerik sehingga dapat digunakan sebagai input dalam algoritma machine learning. Hal ini diperlukan karena sebagian besar algoritma machine learning dirancang untuk memproses data dalam bentuk numerik (Pargent et al., 2022).

g.Imbalanced Dataset

 Imbalanced Dataset merupakan kondisi ketika jumlah observasi pada setiap kelas dalam suatu dataset tidak terdistribusi secara seimbang. Kelas dengan jumlah observasi yang lebih banyak disebut sebagai kelas mayoritas, sedangkan kelas dengan jumlah observasi yang lebih sedikit disebut sebagai kelas minoritas. Kondisi ini umum ditemukan pada berbagai permasalahan machine learning, terutama pada data dunia nyata, dan dapat menyebabkan model lebih cenderung mempelajari kelas mayoritas dibandingkan kelas minoritas (Mumuni & Mumuni, 2025).

BAB III METODE PENELITIAN

3.1 Jenis dan Sumber Data

   Jenis data yang digunakan pada penelitian ini yaitu data kuantitatif. Data kuantitatif adalah data penelitian yang berbentuk angka dan data yang dapat dilakukan analisis. Data kuantitatif disebut juga dikenal dengan data numerik. 
   Sumber data yang digunakan dalam penelitian ini merupakan data sekunder. Data sekunder adalah data yang telah dikumpulkan dan diolah sebelumnya oleh pihak lain, bukan oleh peneliti yang sedang melakukan penelitian saat ini. Data sekunder yang digunakan pada penelitian ini adalah curah hujan yang diberikan oleh asisten praktikum.

3.2 Variabel Penelitian

   Variabel merupakan objek penelitian atau hal yang menjadi titik perhatian dalam suatu studi. Variabel yang digunakan dalam praktikum ini terdiri atas hujan, suhu, kelembapan, keadaan cuaca, dan kecepatan angin. Variabel hujan, suhu, kelembapan, dan kecepatan angin merupakan variabel numerik, sedangkan keadaan cuaca merupakan variabel kategorik. kelima variabel tersebut digunakan dalam proses preprocessing data untuk mempersiapkan data sebelum dilakukan analisis selanjutnya.

3.3 Analisis Data

   Berikut adalah algoritma untuk menyelesaiankan batasan masalah:
   1.Mulai.
   2.Menghitung distribusi kelas pada variabel target y_train.
   3.Menggabungkan data prediktor hasil encoding dengan variabel target Hujan.
   4.Mengubah variabel target Hujan menjadi tipe factor agar dapat digunakan dalam proses SMOTE.
   5.Menentukan seed untuk menjaga hasil proses tetap konsisten.
   6.Membuat recipe SMOTE dengan variabel Hujan sebagai target.
   7.Menentukan over_ratio = 1 dan jumlah tetangga (neighbors) sebanyak 5.
   8.Melakukan prep() berdasarkan data training.
   9.Menerapkan SMOTE menggunakan bake() untuk menghasilkan data training yang lebih seimbang.
  10.Menghasilkan train_balanced sebagai dataset hasil penanganan imbalanced dataset.
  11.Selesai.

BAB IV HASIL DAN PEMBAHASAN

4.1 Library

library(zoo) 
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(readxl)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(rsample)
library(e1071)
## 
## Attaching package: 'e1071'
## 
## The following object is masked from 'package:rsample':
## 
##     permutations
## 
## The following object is masked from 'package:ggplot2':
## 
##     element
library(DescTools)
library(dplyr)
library(ggplot2)
library(gridExtra)
## 
## Attaching package: 'gridExtra'
## 
## The following object is masked from 'package:dplyr':
## 
##     combine
library(recipes)
## 
## Attaching package: 'recipes'
## 
## The following object is masked from 'package:stringr':
## 
##     fixed
## 
## The following object is masked from 'package:stats':
## 
##     step
library(themis)
library(caret)   
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following objects are masked from 'package:DescTools':
## 
##     MAE, RMSE
## 
## The following object is masked from 'package:rsample':
## 
##     calibration
## 
## The following object is masked from 'package:purrr':
## 
##     lift
# Import Data
data <- read_excel("D:/SEMESTER 7/ML/LAPRAK ML/data curah hujan.xlsx")
View(data)
head(data)
## # A tibble: 6 × 5
##   Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
##   <dbl> <dbl>      <dbl>         <dbl>           <dbl>
## 1     1  23           95             5              NA
## 2     1  24           90             1              NA
## 3     1  26.8         77             1              NA
## 4     1  29.6         62             2               2
## 5     1  30.8         56             1               7
## 6     1  31           55             1               7
str(data)
## tibble [743 × 5] (S3: tbl_df/tbl/data.frame)
##  $ Hujan          : num [1:743] 1 1 1 1 1 1 1 2 2 2 ...
##  $ Suhu           : num [1:743] 23 24 26.8 29.6 30.8 31 30.4 30.9 30.2 29.7 ...
##  $ Kelembapan     : num [1:743] 95 90 77 62 56 55 57 58 62 62 ...
##  $ Keadaan_Cuaca  : num [1:743] 5 1 1 2 1 1 3 2 2 2 ...
##  $ Kecepatan_Angin: num [1:743] NA NA NA 2 7 7 9 10 8 7 ...

4.2 Handling Missing Value

# Jumlah missing value setiap variabel
colSums(is.na(data))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               9             314
# Persentase missing value setiap variabel
colMeans(is.na(data))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##      0.00000000      0.00000000      0.00000000      0.01211306      0.42261104
# Melihat baris yang memiliki missing value
data %>% filter(if_any(everything(), is.na))
## # A tibble: 319 × 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  25           89             2              NA
##  5     1  24.6         90             2              NA
##  6     2  24.2         90             2              NA
##  7     2  23.9         90             2              NA
##  8     2  23.7         91             2              NA
##  9     2  23.5         92             2              NA
## 10     2  23.3         92             2              NA
## # ℹ 309 more rows
#Interpolasi
df_imp <- data

df_imp$Keadaan_Cuaca <- na.approx(
  df_imp$Keadaan_Cuaca,
  na.rm = FALSE
)

# Melihat jumlah missing setelah interpolasi
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0             314
# Menghitung nilai mean Kecepatan_Angin
mean_angin <- mean(
  df_imp$Kecepatan_Angin,
  na.rm = TRUE
)

# Mengisi missing value dengan mean
df_imp$Kecepatan_Angin[
  is.na(df_imp$Kecepatan_Angin)
] <- mean_angin

# Mengecek kembali missing value
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0               0

4.3 Kadinalitas

# Melihat kategori unik Keadaan_Cuaca
unique(df_imp$Keadaan_Cuaca)
##  [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
# Membuat interval
bins <- c(
  0, 10, 20, 30, 40,
  50, 60, 70, 80, 90, 100
)

# Membuat label kategori
labels <- 0:9

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

# Melihat hasil
head(df_imp, 10)
## # A tibble: 10 × 6
##    Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin Keadaan_Cuaca_reduced
##    <dbl> <dbl>      <dbl>         <dbl>           <dbl> <fct>                
##  1     1  23           95             5            6.66 0                    
##  2     1  24           90             1            6.66 0                    
##  3     1  26.8         77             1            6.66 0                    
##  4     1  29.6         62             2            2    0                    
##  5     1  30.8         56             1            7    0                    
##  6     1  31           55             1            7    0                    
##  7     1  30.4         57             3            9    0                    
##  8     2  30.9         58             2           10    0                    
##  9     2  30.2         62             2            8    0                    
## 10     2  29.7         62             2            7    0
# Membandingkan jumlah kategori
cat(
  "Jumlah kategori Keadaan_Cuaca asli :",
  length(unique(df_imp$Keadaan_Cuaca)),
  "\n"
)
## Jumlah kategori Keadaan_Cuaca asli : 23
cat(
  "Jumlah kategori Keadaan_Cuaca setelah reduksi :",
  length(unique(df_imp$Keadaan_Cuaca_reduced)),
  "\n"
)
## Jumlah kategori Keadaan_Cuaca setelah reduksi : 7
# Melihat kategori hasil reduksi
unique(df_imp$Keadaan_Cuaca_reduced)
## [1] 0 1 5 6 2 9 4
## Levels: 0 1 2 3 4 5 6 7 8 9

4.4 Splitting Data

set.seed(200)

split_shuffle <- initial_split(
  df_imp,
  prop = 0.8
)

# Data training
train_data <- training(split_shuffle)

# Data testing
test_data <- testing(split_shuffle)

# Memisahkan variabel prediktor dan target
X_train <- train_data %>% select(-Hujan)
X_test  <- test_data %>% select(-Hujan)

y_train <- train_data$Hujan
y_test  <- test_data$Hujan

# Melihat ukuran data
dim(X_train)
## [1] 594   5
dim(X_test)
## [1] 149   5

4.5 Handling Outlier

# Variabel numerik
list_num <- c(
  "Suhu",
  "Kelembapan",
  "Kecepatan_Angin"
)

# Menyiapkan wadah hasil
list_outlier <- c()
list_lower_bound <- c()
list_upper_bound <- c()

# Menghitung batas outlier dengan IQR
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
  
  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
  )
  
  list_lower_bound <- c(
    list_lower_bound,
    lower_bound
  )
  
  list_upper_bound <- c(
    list_upper_bound,
    upper_bound
  )
}

# Membuat tabel hasil
outliers <- data.frame(
  Kolom = list_num,
  Jumlah_Outlier = list_outlier,
  Lower_Bound = list_lower_bound,
  Upper_Bound = list_upper_bound
)

outliers
##             Kolom Jumlah_Outlier Lower_Bound Upper_Bound
## 1            Suhu              0        17.4        35.8
## 2      Kelembapan              0        46.5       122.5
## 3 Kecepatan_Angin             50         2.0        10.0

4.6 Capping

X_train_capped <- X_train
X_test_capped <- X_test

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
  
  # Capping data training
  X_train_capped[[i]] <- pmin(
    pmax(
      X_train[[i]],
      lower_bound
    ),
    upper_bound
  )
  
  # Capping data testing menggunakan
  # batas dari data training
  X_test_capped[[i]] <- pmin(
    pmax(
      X_test[[i]],
      lower_bound
    ),
    upper_bound
  )
}
diagnostic_plots <- function(df, variable) {
  
  p1 <- ggplot(
    df,
    aes(x = .data[[variable]])
  ) +
    geom_histogram(
      bins = 30,
      fill = "navy",
      color = "black"
    ) +
    ggtitle("Histogram") +
    theme_minimal()
  
  p2 <- ggplot(
    df,
    aes(y = .data[[variable]])
  ) +
    geom_boxplot(
      fill = "navy"
    ) +
    ggtitle("Boxplot") +
    theme_minimal()
  
  grid.arrange(
    p1,
    p2,
    ncol = 2
  )
}

for (col in list_num) {
  
  cat(
    col,
    "- Sebelum Capping\n"
  )
  
  diagnostic_plots(
    X_train,
    col
  )
  
  cat(
    "\n",
    col,
    "- Setelah Capping\n"
  )
  
  diagnostic_plots(
    X_train_capped,
    col
  )
}
## Suhu - Sebelum Capping

## 
##  Suhu - Setelah Capping

## Kelembapan - Sebelum Capping

## 
##  Kelembapan - Setelah Capping

## Kecepatan_Angin - Sebelum Capping

## 
##  Kecepatan_Angin - Setelah Capping

## 4.6 scalling data dengan robust scaler

# Robust Scaling menggunakan median dan IQR
median_val <- sapply(
  X_train_capped[list_num],
  median,
  na.rm = TRUE
)

iqr_val <- sapply(
  X_train_capped[list_num],
  IQR,
  na.rm = TRUE
)

# Scaling data training
for (col in list_num) {
  
  X_train_capped[[col]] <-
    (
      X_train_capped[[col]] -
        median_val[col]
    ) /
    iqr_val[col]
}

# Scaling data testing menggunakan
# median dan IQR dari data training
for (col in list_num) {
  
  X_test_capped[[col]] <-
    (
      X_test_capped[[col]] -
        median_val[col]
    ) /
    iqr_val[col]
}

# Melihat hasil scaling
head(X_train_capped)
## # 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

4.7 encoding

list_cat <- c(
  "Keadaan_Cuaca_reduced"
)

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

X_train_encoded <- bake(
  resep_encode,
  new_data = X_train_capped
)

X_test_encoded <- bake(
  resep_encode,
  new_data = X_test_capped
)

# Melihat hasil encoding
head(X_train_encoded)
## # A tibble: 6 × 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 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>
head(X_test_encoded)
## # A tibble: 6 × 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 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>

4.8 Balancing data dengan SMOTE

# Melihat distribusi target sebelum SMOTE
table(y_train)
## y_train
##   1   2 
## 128 466
# Menggabungkan X dan y
train_full <- X_train_encoded %>%
  mutate(
    Hujan = factor(y_train)
  )

# SMOTE
set.seed(42)

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
)

# Memisahkan kembali X dan y
X_train_balanced <- train_balanced %>%
  select(-Hujan)

y_train_balanced <-
  train_balanced$Hujan

# Melihat distribusi setelah SMOTE
table(y_train_balanced)
## y_train_balanced
##   1   2 
## 466 466

BAB V KESIMPULAN

5.1 Kesimpulan

   Berdasarkan hasil preprocessing data curah hujan sebanyak 743 observasi, ditemukan missing value pada variabel Keadaan_Cuaca sebanyak 9 data dan Kecepatan_Angin sebanyak 314 data. Missing value pada Keadaan_Cuaca ditangani menggunakan interpolasi, sedangkan pada Kecepatan_Angin diisi menggunakan nilai rata-rata. Variabel Keadaan_Cuaca kemudian direduksi dari 23 kategori menjadi 7 kategori melalui pengelompokan interval. Data selanjutnya dibagi menjadi data training sebanyak 594 observasi dan data testing sebanyak 149 observasi. Pada variabel numerik Suhu, Kelembapan, dan Kecepatan_Angin dilakukan deteksi outlier menggunakan metode IQR dan penanganan outlier dengan teknik capping berdasarkan batas yang diperoleh dari data training. Selanjutnya, data numerik distandarisasi menggunakan Robust Scaling berdasarkan median dan IQR, sedangkan variabel kategorik Keadaan_Cuaca_reduced diubah menjadi variabel dummy. Distribusi target Hujan menunjukkan ketidakseimbangan kelas, yaitu 128 observasi untuk kelas 1 dan 466 observasi untuk kelas 2, sehingga dilakukan SMOTE untuk menyeimbangkan data training. Setelah SMOTE, jumlah masing-masing kelas menjadi 466 observasi, sehingga data training menjadi seimbang dan siap digunakan pada tahap pemodelan klasifikasi.

5.2 Saran

   Dalam membuat laporan praktikum ini penulis menyarankan untuk selalu memperhatikan sintaks pada program R yang digunakan. Selain itu, perlu untuk memperhatikan tata cara penulisan yang sesuai dengan KBBI dan penulisan yang bercetak tebal. Sehingga dapat menghasilkan laporan yang baik

DAFTAR PUSTAKA

Ahsan, M. M., Mahmud, M. A. P., Saha, P. K., Gupta, K. D., & Siddique, Z. (2021). Effect of Data Scaling Methods on Machine Learning Algorithms and Model Performance. Technologies, 9(3). https://doi.org/10.3390/technologies9030052
Bichri, H., Chergui, A., & Hain, M. (2024). Investigating the Impact of Train / Test Split Ratio on the Performance of Pre-Trained Models with Custom Datasets. In IJACSA) International Journal of Advanced Computer Science and Applications (Vol. 15, Number 2). www.ijacsa.thesai.org
Emmanuel, T., Maupong, T., Mpoeleng, D., Semong, T., Mphago, B., & Tabona, O. (2021). A survey on missing data in machine learning. Journal of Big Data, 8(1). https://doi.org/10.1186/s40537-021-00516-9
Foorthuis, R. (2021). On the nature and types of anomalies: a review of deviations in data. In International Journal of Data Science and Analytics (Vol. 12, Number 4, pp. 297–331). Springer Science and Business Media Deutschland GmbH. https://doi.org/10.1007/s41060-021-00265-1
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
Pargent, F., Pfisterer, F., Thomas, J., & Bischl, B. (2022). Regularized target encoding outperforms traditional methods in supervised machine learning with high cardinality features. Computational Statistics, 37(5), 2671–2692. https://doi.org/10.1007/s00180-022-01207-6
Villa-Blanco, C., Bielza, C., & Larrañaga, P. (2023). Feature subset selection for data and feature streams: a review. Artificial Intelligence Review, 56, 1011–1062. https://doi.org/10.1007/s10462-023-10546-9