BAB I PENDAHULUAN

1.1 Latar Belakang

Data merupakan sumber informasi utama dalam analisis, dan setiap data tersusun atas variabel atau fitur yang menggambarkan karakteristik objek yang diamati. Kualitas fitur menentukan seberapa baik informasi dalam data dapat dimanfaatkan untuk analisis maupun pemodelan. Data mentah umumnya memiliki skala beragam, tipe berbeda, dan nilai yang hilang. Penyiapan fitur yang tepat diperlukan agar data dapat digunakan secara optimal.

Feature engineering adalah proses mengubah, membentuk, dan memilih fitur dari data mentah agar lebih representatif bagi kebutuhan analisis. Tujuan utamanya adalah meningkatkan kualitas data sehingga model dapat mengenali pola dengan lebih baik. Proses ini mencakup berbagai teknik, seperti transformasi variabel, penskalaan, pengodean data kategorik, dan pembentukan fitur baru. Pemilihan teknik bergantung pada karakteristik data dan tujuan analisis (Sihombing, 2024).

Pemahaman terhadap berbagai teknik feature engineering perlu diiringi kemampuan menerapkannya pada data. RStudio sebagai lingkungan pengembangan terpadu bagi bahasa R menyediakan beragam fungsi dan package untuk mengolah serta membentuk fitur. Pemrograman di dalamnya memungkinkan setiap tahapan dilakukan secara sistematis dan dapat diulang pada data yang berbeda. Penerapan melalui RStudio menjadikan konsep feature engineering dapat diwujudkan sebagai proses pengolahan data yang terarah.

1.2 Rumusan Masalah

Berdasarkan latar belakang di atas, adapun rumusan masalah yang dapat disimpulkan sebagai berikut:

  1. Bagaimana konsep dari berbagai jenis feature engineering yang dapat diterapkan pada RStudio?
  2. Bagaimana penerapan teknik feature engineering menggunakan program RStudio?

1.3 Tujuan

Adapun tujuan penelitian ini yaitu:

  1. Praktikan memahami konsep dari berbagai jenis feature engineering pada RStudio.
  2. Praktikan dapat melakukan teknik feature engineering di program RStudio.

BAB II TINJAUAN PUSTAKA

2.1 Feature Engineering

Feature engineering merupakan tahap penting dalam pengembangan model prediktif yang melibatkan transformasi variabel-variabel data menjadi bentuk yang lebih representatif untuk meningkatkan kinerja model (Herdian dkk., 2024). Proses ini menggunakan pengetahuan domain untuk mengekstrak atau membuat fitur-fitur baru dari data mentah, dan langkah ini penting karena performa model machine learning sangat bergantung pada kualitas fitur input (Darmawan dkk., 2026). Feature engineering memungkinkan penggalian informasi yang lebih dalam dari data yang ada, seperti variabel lingkungan, tren pasar, dan preferensi konsumen (Sihombing, 2024).

Tujuan dari feature engineering adalah menyederhanakan dan mempercepat transformasi data sekaligus meningkatkan akurasi model, di mana kualitas fitur jauh lebih penting daripada seberapa canggih algoritma yang dipilih (Fransiska, 2026). Feature engineering diperlukan untuk menciptakan representasi data yang sesuai bagi model machine learning, terutama dalam menangani data yang berbentuk label kategori atau non-numerik (Herdian dkk., 2024). Feature engineering yang tepat lebih berdampak daripada pemilihan model, sehingga pemahaman domain dan penciptaan fitur yang cerdas menjadi faktor penentu keberhasilan pemodelan (Darmawan dkk., 2026).

2.2 Jenis Data dan Fitur

Fitur atau variabel dalam machine learning merujuk pada atribut atau karakteristik yang digunakan sebagai input untuk model prediktif. Fitur merupakan representasi dari karakteristik atau properti yang melekat pada objek data yang akan dianalisis (Herdian dkk., 2024). Dalam pemodelan machine learning, fitur berperan sebagai variabel prediktor yang digunakan untuk memprediksi variabel target (Sihombing, 2024).

Data dapat dikelompokkan menjadi data numerik dan data kategorik. Data numerik terdiri atas data numerik diskrit dan kontinu, sedangkan data kategorik terdiri atas data kategorik nominal dan ordinal. Data numerik diskrit merupakan data yang nilainya berupa bilangan bulat dan terpisah, sedangkan data numerik kontinu merupakan data yang nilainya berada dalam suatu rentang tertentu. Data kategorik nominal merupakan data yang tidak memiliki urutan, sedangkan data kategorik ordinal merupakan data yang memiliki tingkatan atau urutan tertentu (Fransiska, 2026).

Kardinalitas merujuk pada jumlah nilai unik atau label yang terdapat dalam suatu variabel kategorik yang dapat diklasifikasikan menjadi kardinalitas rendah (low cardinality) dan kardinalitas tinggi (high cardinality). Variabel dengan kardinalitas tinggi dapat menyebabkan curse of dimensionality jika ditransformasi menggunakan metode encoding standar seperti One-Hot Encoding, karena metode ini akan menciptakan banyak fitur biner baru sesuai jumlah label. Kardinalitas juga secara signifikan meningkatkan risiko overfitting karena banyak label mungkin hanya muncul beberapa kali dalam set data training (Fransiska, 2026).

2.3 Teknik Feature Engineering

Teknik feature engineering mencakup berbagai metode yang digunakan untuk mengubah data mentah menjadi fitur yang lebih informatif dan siap digunakan dalam pemodelan machine learning. Beberapa teknik feature engineering meliputi penanganan missing value, transformasi variabel, standardisasi, scaling, encoding, diskretisasi, pembuatan fitur baru, dan seleksi fitur. Berikut merupakan teknik-teknik feature engineering yang digunakan dalam proses pengolahan data:

1. Missing Value Imputation

Missing values atau data hilang terjadi ketika tidak ada nilai yang tersimpan untuk observasi tertentu dalam suatu variabel dan merupakan kejadian umum yang dapat berdampak signifikan pada pemodelan machine learning (Fransiska, 2026). Metode imputasi meliputi metode konvensional dengan mean dan nilai maksimum, serta metode data mining menggunakan KNN dan Neural Network (Prasetya dkk., 2023).

2. Transformasi Variabel

Transformasi variabel merupakan teknik feature engineering yang mengubah skala atau distribusi data untuk meningkatkan representasi data dalam pemodelan. Feature engineering juga mencakup pembuatan fitur turunan seperti rasio antara dua variabel untuk menangkap hubungan yang tidak terlihat pada data mentah (Darmawan dkk., 2026).

3. Standardization

Standardization atau standardisasi merupakan teknik feature engineering yang diterapkan untuk menormalkan distribusi data. Standardisasi menggunakan Robust Scaler dengan rumus:

\[ x' = \frac{x - Q_2}{Q_3 - Q_1} \]

di mana \(x'\) merupakan hasil standardisasi, \(x\) adalah nilai asli, \(Q_2\) adalah nilai tengah data, dan \(Q_3 - Q_1\) merupakan Interquartile Range (IQR). Standardisasi bertujuan untuk menyetarakan skala antar fitur sehingga model tidak berat sebelah terhadap fitur dengan nilai yang lebih besar (Fauzi dkk., 2025).

4. Min-Max Scaling

Min-Max Scaling merupakan salah satu teknik scaling data yang digunakan dalam feature engineering. Min-Max Scaling mengubah distribusi data sehingga nilai-nilai berada dalam rentang tertentu, biasanya antara 0 dan 1. Teknik ini berbeda dengan Robust Scaling dan Standard Scaling yang juga digunakan untuk menormalkan data dengan pendekatan yang berbeda (Fransiska, 2026).

5. Label Encoding

Label Encoding merupakan teknik feature encoding yang mengubah fitur kategoris atau non-numerik menjadi format numerik yang dapat digunakan sebagai input untuk algoritma machine learning. Label encoder digunakan agar tidak menambah jumlah fitur pada data, berbeda dengan One-Hot Encoding yang akan menambah jumlah fitur sesuai dengan jumlah kategori (Fauzi dkk., 2025). Feature encoding diperlukan karena banyak algoritma machine learning membutuhkan input numerik (Fransiska, 2026).

6. One-Hot Encoding

One-Hot Encoding dalam pemrosesan data dan machine learning adalah metode yang digunakan untuk merepresentasikan variabel kategorikal sebagai vektor biner. Setiap kategori atau label dalam metode encoding ini diubah menjadi vektor biner dengan panjang yang sama dengan jumlah total kategori yang berbeda dalam variabel tersebut, di mana semua nilai vektor adalah nol kecuali indeks yang sesuai dengan kategori yang ditandai dengan angka 1. One-Hot Encoding dapat menghasilkan ruang fitur berdimensi tinggi, terutama pada dataset dengan banyak kategori, sehingga perlu pertimbangan hati-hati untuk menyeimbangkan keuntungan representasi dengan kemungkinan peningkatan kompleksitas komputasi (Herdian dkk., 2024).

7. Diskretisasi atau Binning

Diskretisasi atau binning merupakan teknik feature engineering yang mengubah data kontinu menjadi data interval (Herdian dkk., 2024). Diskretisasi dilakukan dengan membagi rentang nilai kontinu menjadi beberapa interval atau bin berdasarkan kriteria tertentu. Transformasi ini bertujuan untuk menyederhanakan data dan memberikan informasi yang lebih eksplisit kepada model mengenai kategori nilai tertentu (Darmawan dkk., 2026).

8. Feature Creation

Feature creation merupakan proses menciptakan fitur-fitur baru yang lebih representatif dari data yang ada. Feature engineering dilakukan untuk membuat fitur baru seperti rasio antara dua variabel, jarak, dan variabel turunan lainnya yang dapat meningkatkan representasi data (Sihombing, 2024). Fitur turunan dibuat sebagai bagian dari strategi feature engineering yang menggabungkan berbagai informasi dari data mentah. Feature creation juga mencakup pembuatan fitur interaksi untuk meningkatkan representasi data (Darmawan dkk., 2026).

9. Feature Selection

Seleksi fitur merupakan proses pemilihan fitur yang tepat dalam proses klasifikasi, dengan tujuan untuk mengurangi tingkat kompleksitas dan meningkatkan akurasi dari suatu algoritma klasifikasi serta mampu mengetahui fitur-fitur apa saja yang paling berkontribusi terhadap tingkat akurasi (Budianita, 2023). Information gain adalah metode seleksi fitur dengan memberikan bobot setiap fitur berdasarkan kelas tertentu dengan memaksimalkan nilai entropy (Putri dkk., 2023). Rumus entropy dan information gain adalah sebagai berikut:

\[ Entropy(S) = -\sum_{i=1}^{c} p_i \log_2(p_i) \]

\[ Gain(S,A) = Entropy(S) - \sum_{v \in Values(A)} \frac{|S_v|}{|S|} \times Entropy(S_v) \]

di mana \(Entropy(S)\) adalah nilai entropy keseluruhan, \(c\) adalah jumlah label sentimen, \(p_i\) adalah rasio label ke-\(i\) pada seluruh tweet, \(Gain(S,A)\) adalah nilai information gain tiap fitur, \(A\) adalah fitur, \(v\) adalah kemungkinan nilai fitur \(A\), \(S_v\) adalah jumlah tweet untuk nilai \(v\), dan \(Entropy(S_v)\) adalah nilai entropy setelah dipartisi dengan fitur \(A\). Penetapan nilai threshold dalam pemilihan fitur dengan information gain dapat ditentukan dengan nilai 0,05, di mana fitur dengan nilai information gain < 0,05 akan direduksi (Putri dkk., 2023). Correlation-based feature selection merupakan teknik seleksi fitur yang memperhitungkan suatu fitur yang memiliki korelasi yang baik dan relevan dengan kelasnya dan tidak memiliki korelasi berlebihan dengan fitur lainnya (Asmoro dkk., 2021).

2.4 Package dan Fungsi R untuk Feature Engineering

Proses pemodelan machine learning dalam RStudio didukung oleh berbagai package yang menyediakan fungsi untuk setiap tahapan analisis data. Package tidyverse digunakan untuk memanipulasi data melalui fungsi drop_na(), fill(), dan is.na() untuk menangani missing value, sedangkan package zoo menyediakan fungsi na.approx() untuk interpolasi data yang hilang. Package rsample menyediakan fungsi initial_split() dan initial_time_split() untuk membagi data, package DescTools menyediakan fungsi Winsorize(), quantile(), dan IQR() untuk menangani outlier, serta package e1071 menyediakan fungsi skewness() untuk mengukur kemencengan distribusi data. Package recipes dan themis digunakan untuk melakukan encoding dan penyeimbangan data melalui fungsi step_dummy() dan step_smote(), sementara package dplyr menyediakan fungsi mutate(), filter(), dan select() untuk manipulasi data. Package ggplot2 dan gridExtra digunakan untuk visualisasi distribusi data, dan package caret digunakan untuk mendukung proses pemodelan dan evaluasi (Fransiska, 2026).

BAB III METODE PENELITIAN

3.1 Jenis dan Sumber Data

Jenis data yang digunakan pada penelitian ini adalah data numerik dan data kategorik. Data numerik merupakan data berbentuk angka yang dapat dianalisis secara statistik, yaitu suhu, kelembapan, dan kecepatan angin. Data kategorik merupakan data yang menyatakan kelompok atau kelas suatu pengamatan, yaitu status hujan dan kode keadaan cuaca.

Sumber data yang digunakan dalam penelitian ini adalah data sekunder. Data sekunder merupakan data yang telah dikumpulkan dan diolah terlebih dahulu oleh pihak lain. Data curah hujan diperoleh dari modul praktikum Machine Learning and Modern Prediction. Dataset tersebut terdiri atas 743 observasi dan 5 variabel.

3.2 Variabel Penelitian

Variabel merupakan karakteristik atau atribut yang dapat diukur maupun diamati dalam suatu penelitian. Penelitian ini menggunakan lima variabel, yaitu Hujan, Suhu, Kelembapan, Keadaan Cuaca, dan Kecepatan Angin. Variabel Hujan berperan sebagai variabel target yang bertipe kategorik dengan dua kelas, yaitu 1 dan 2. Variabel Suhu, Kelembapan, dan Kecepatan Angin bertipe numerik, sedangkan Keadaan Cuaca bertipe kategorik berupa kode keadaan cuaca yang ditulis dalam bentuk angka. Keempat variabel selain Hujan berperan sebagai fitur.

3.3 Analisis Data

Berikut merupakan algoritma penelitian pada batasan masalah:

  1. Input data
  2. Pemeriksaan dan handling missing value
  3. Reduksi kardinalitas
  4. Splitting data dengan metode stratify
  5. Penanganan outlier dengan capping
  6. Scaling data dengan Standard Scaler
  7. Encoding dengan One-Hot Encoding
  8. Penyeimbangan data dengan SMOTE
  9. Output
  10. Interpretasi

BAB IV HASIL DAN PEMBAHASAN

4.1 Library dan Import Data

# Library
library(zoo)
library(readxl)
library(tidyverse)
library(rsample)
library(e1071)
library(DescTools)
library(dplyr)
library(ggplot2)
library(gridExtra)
library(recipes)
library(themis)
library(caret)

# Import Data
data <- read_excel("C:/Users/Andini Putri Aria/Documents/UNIB/Statistics 23/Semester 7/Machine Learning and Modern Prediction/Laporan Praktikum/Pt 1/data curah hujan.xlsx")

head(data)
## # A tibble: 6 × 5
##   Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
##   <dbl> <dbl>      <dbl>         <dbl>           <dbl>
## 1     1  23           95             5              NA
## 2     1  24           90             1              NA
## 3     1  26.8         77             1              NA
## 4     1  29.6         62             2               2
## 5     1  30.8         56             1               7
## 6     1  31           55             1               7
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 ...

Tabel 4.1 Fungsi library dalam preprocessing

Library Fungsi
readxl Membaca data dari berkas Excel
tidyverse, dplyr Manipulasi dan penyaringan data
zoo Interpolasi nilai hilang (na.approx)
DescTools Perhitungan modus (Mode) dan capping (Winsorize)
rsample Pembagian data latih dan data uji
e1071 Perhitungan skewness
ggplot2, gridExtra Visualisasi histogram dan boxplot
recipes Pengodean variabel kategorik
themis Penyeimbangan kelas dengan SMOTE
caret Pendukung pemodelan dan evaluasi

Pada batasan masalah diminta penggunaan data curah hujan untuk melakukan preprocessing data. Tahap awal yang dikerjakan adalah memuat library yang dibutuhkan dan mengimpor data ke RStudio. Sebelas library berhasil dimuat tanpa kesalahan. Fungsi masing-masing library tersaji pada Tabel 4.1.

Fungsi head() menampilkan enam observasi pertama dari dataset, sedangkan fungsi str() memperlihatkan struktur data secara keseluruhan. Dataset terdiri atas 743 observasi dan 5 variabel yang seluruhnya bertipe numerik. Variabel Hujan bernilai 1 dan 2 sehingga berperan sebagai variabel target. Empat variabel lainnya, yaitu Suhu, Kelembapan, Keadaan Cuaca, dan Kecepatan Angin berperan sebagai fitur.

Keluaran head() dan str() menghasilkan empat temuan yang menentukan langkah selanjutnya. Variabel Keadaan Cuaca dan Kecepatan Angin memiliki nilai NA sehingga memerlukan penanganan missing value. Variabel Keadaan Cuaca bertipe numerik tetapi sebenarnya berupa kode kategori dengan nilai yang sangat beragam, sehingga memerlukan reduksi kardinalitas dan pengodean. Satuan dan rentang variabel numerik berbeda serta proporsi kelas Hujan belum diketahui, sehingga diperlukan pemeriksaan outlier, penskalaan, dan pengecekan keseimbangan data.

4.2 Handling Missing Value

# Cek Missing Value
colSums(is.na(data))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               9             314
colMeans(is.na(data))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##      0.00000000      0.00000000      0.00000000      0.01211306      0.42261104
# Lihat baris yang kosong di Keadaan_Cuaca
data %>% filter(is.na(Keadaan_Cuaca))
## # A tibble: 9 × 5
##   Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin
##   <dbl> <dbl>      <dbl>         <dbl>           <dbl>
## 1     2  26           92            NA              NA
## 2     1  23.8         98            NA               5
## 3     1  23.3         97            NA              NA
## 4     2  28.8         79            NA              12
## 5     2  24.6         92            NA              NA
## 6     1  22.8         98            NA               4
## 7     2  25.5         96            NA              NA
## 8     2  27           80            NA               4
## 9     2  31           57            NA               6
# Penanganan Missing Value
df_imp <- data

# Interpolasi pada Keadaan_Cuaca
# rule = 2 agar NA di awal/akhir data tetap terisi
df_imp$Keadaan_Cuaca <- na.approx(df_imp$Keadaan_Cuaca, na.rm = FALSE, rule = 2)
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0             314
# Mode Imputation pada Kecepatan_Angin
mode_value <- Mode(df_imp$Kecepatan_Angin, na.rm = TRUE)[1]
mode_value
## [1] 3
df_imp$Kecepatan_Angin[is.na(df_imp$Kecepatan_Angin)] <- mode_value

# Verifikasi tidak ada missing value tersisa
colSums(is.na(df_imp))
##           Hujan            Suhu      Kelembapan   Keadaan_Cuaca Kecepatan_Angin 
##               0               0               0               0               0

Tabel 4.2 Jumlah dan persentase missing value sebelum penanganan

Variabel Jumlah missing value Persentase
Hujan 0 0,00%
Suhu 0 0,00%
Kelembapan 0 0,00%
Keadaan Cuaca 9 1,21%
Kecepatan Angin 314 42,26%

Pada batasan masalah diminta penanganan missing value dengan interpolasi pada Keadaan Cuaca dan mode imputation pada Kecepatan Angin. Pemeriksaan awal menunjukkan bahwa nilai kosong hanya terdapat pada dua variabel, sebagaimana tersaji pada Tabel 4.2. Variabel Keadaan Cuaca memiliki 9 nilai kosong, sedangkan Kecepatan Angin memiliki 314 nilai kosong. Variabel Hujan, Suhu, dan Kelembapan tidak memiliki nilai kosong.

Interpolasi pada Keadaan Cuaca dilakukan dengan fungsi na.approx, yang mengisi nilai kosong berdasarkan estimasi linear dari nilai di sekitarnya. Argumen rule = 2 memastikan nilai kosong di awal atau akhir data tetap terisi. Sembilan nilai kosong pada variabel ini berhasil diisi sehingga jumlahnya menjadi nol. Variabel Kecepatan_Angin masih memiliki 314 nilai kosong pada tahap ini.

Mode imputation pada Kecepatan Angin mengisi nilai kosong dengan nilai yang paling sering muncul. Perhitungan menunjukkan bahwa modus variabel tersebut adalah 3. Seluruh 314 nilai kosong diganti dengan angka 3 sehingga tidak ada lagi missing value pada dataset. Proporsi nilai kosong pada Kecepatan Angin mencapai 42,26% sehingga penghapusan baris akan membuang hampir separuh data. Imputasi dipilih agar jumlah observasi tetap terjaga. Angka 3 menjadi sangat dominan pada variabel ini sebagai konsekuensinya.

4.3 Kardinalitas

head(df_imp, 10)
## # 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
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
# Tentukan batas bin
bins <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

# Tentukan label untuk setiap bin (10 label: 0 s/d 9)
labels <- 0:9

# Terapkan cut()
df_imp$Keadaan_Cuaca_reduced <- cut(
  df_imp$Keadaan_Cuaca,
  breaks = bins,
  labels = labels,
  right = TRUE,            # interval (a, b]
  include.lowest = TRUE    # nilai batas paling bawah (0) tetap terhitung
)

# Verifikasi
cat("--- Hasil Perbandingan ---\n")
## --- Hasil Perbandingan ---
print(df_imp[sample(nrow(df_imp), 10), ])
## # A tibble: 10 × 6
##    Hujan  Suhu Kelembapan Keadaan_Cuaca Kecepatan_Angin Keadaan_Cuaca_reduced
##    <dbl> <dbl>      <dbl>         <dbl>           <dbl> <fct>                
##  1     2  27.2         85             1               2 0                    
##  2     2  27.7         88            13               3 1                    
##  3     2  27           87             2               3 0                    
##  4     1  23.7         98            60               3 5                    
##  5     2  29.7         61             2               8 0                    
##  6     2  24.3         93             3               3 0                    
##  7     2  23.4         94             2               3 0                    
##  8     1  25.1         90             2               3 0                    
##  9     2  30.3         67             2               9 0                    
## 10     2  24.3         90            60               4 5
cat("\n--- Pengecekan Kardinalitas ---\n")
## 
## --- Pengecekan Kardinalitas ---
cat('Jumlah kategori di "Keadaan_Cuaca" asli    :', length(unique(df_imp$Keadaan_Cuaca)), "\n")
## 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
cat("\nKategori unik yang baru (reduced):\n")
## 
## Kategori unik yang baru (reduced):
print(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

Tabel 4.3 Hasil pengelompokan nilai Keadaan_Cuaca

Nilai asli Interval Kategori baru
1; 1,5; 2; 3; 5; 10 0–10 0
13; 14; 15; 16; 17 10–20 1
21; 29 20–30 2
49 40–50 4
56; 60 50–60 5
61; 62; 63; 65 60–70 6
91; 95; 97 90–100 9

Pada batasan masalah diminta interpolasi pada Keadaan Cuaca, yang menghasilkan variabel dengan nilai beragam sehingga kardinalitasnya perlu diperiksa. Kardinalitas adalah jumlah kategori unik pada suatu variabel. Variabel Keadaan Cuaca memiliki 23 nilai unik, misalnya 1; 1,5; 2; 5; 14; 60; 95; dan 97. Kardinalitas setinggi ini menyulitkan pengodean karena one hot encoding akan menghasilkan banyak kolom yang sebagian besar bernilai nol dan berisiko memicu overfitting.

Reduksi kardinalitas dilakukan dengan binning menggunakan fungsi cut(). Nilai dikelompokkan ke dalam 10 interval yang masing-masing selebar 10 dengan format (a, b], lalu diberi label 0 sampai 9. Argumen include.lowest = TRUE memastikan nilai batas bawah, yaitu 0, tetap tercakup pada interval pertama. Hasil pengelompokan tersaji pada Tabel 4.3.

Jumlah kategori turun dari 23 menjadi 7, yaitu kategori 0, 1, 2, 4, 5, 6, dan 9. Sebagian besar observasi masuk kategori 0 karena nilai asli 1, 2, dan 3 paling sering muncul. Variabel hasil reduksi bertipe factor dengan 10 level, sehingga seluruh level tetap tersimpan meskipun sebagian tidak muncul pada data. Struktur ini menjaga kesamaan kategori antara data latih dan data uji saat pengodean.

4.4 Splitting Data

# Splitting Data (Stratify)
set.seed(46)
split_stratify <- initial_split(df_imp, prop = 0.8, strata = Hujan)

X_train <- training(split_stratify) %>% select(-Hujan)
X_test  <- testing(split_stratify)  %>% select(-Hujan)
y_train <- training(split_stratify)$Hujan
y_test  <- testing(split_stratify)$Hujan

dim(X_train)
## [1] 594   5
dim(X_test)
## [1] 149   5
# Cek proporsi kelas pada data latih dan data uji
prop.table(table(y_train))
## y_train
##         1         2 
## 0.2205387 0.7794613
prop.table(table(y_test))
## y_test
##         1         2 
## 0.2214765 0.7785235

Tabel 4.4 Ukuran data dan proporsi kelas hasil stratify splitting

Data Jumlah observasi Proporsi kelas 1 Proporsi kelas 2
Data latih 594 22,05% 77,95%
Data uji 149 22,15% 77,85%

Pada batasan masalah diminta stratify splitting untuk NPM genap. Data dibagi dengan perbandingan 80% untuk data latih dan 20% untuk data uji, dengan set.seed(46) agar hasil pembagian dapat direproduksi. Data latih berisi 594 observasi dan data uji berisi 149 observasi, masing-masing dengan 5 kolom. Variabel Hujan dipisahkan sebagai target dalam objek y_train dan y_test.

Stratify splitting membagi data per kelas target sehingga proporsi kelas pada kedua subset tetap mendekati data asli. Kelas 1 menempati 22,05% pada data latih dan 22,15% pada data uji, sedangkan kelas 2 menempati 77,95% dan 77,85% sebagaimana tersaji pada Tabel 4.4. Selisih proporsi yang sangat kecil menunjukkan bahwa data uji merepresentasikan data latih dengan baik. Proporsi tersebut sekaligus menunjukkan bahwa data tidak seimbang karena kelas 2 berjumlah sekitar empat kali lipat kelas 1. Kondisi ini berpotensi membuat model condong pada kelas mayoritas.

4.5 Handling Outlier

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

# Hitung batas IQR untuk setiap kolom (berdasarkan data latih)
list_outlier     <- c()
list_lower_bound <- c()
list_upper_bound <- c()

for (i in list_num) {
  Q1      <- quantile(X_train[[i]], 0.25, na.rm = TRUE)
  Q3      <- quantile(X_train[[i]], 0.75, na.rm = TRUE)
  IQR_val <- Q3 - Q1

  lower_bound <- Q1 - 1.5 * IQR_val
  upper_bound <- Q3 + 1.5 * IQR_val

  list_lower_bound <- c(list_lower_bound, lower_bound)
  list_upper_bound <- c(list_upper_bound, upper_bound)

  num_outliers_lower <- sum(X_train[[i]] < lower_bound, na.rm = TRUE)
  num_outliers_upper <- sum(X_train[[i]] > upper_bound, na.rm = TRUE)

  list_outlier <- c(list_outlier, num_outliers_lower + num_outliers_upper)
}

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

outliers
##             Kolom Jumlah_Outlier Lower_Bound Upper_Bound
## 1            Suhu              0        17.5        35.9
## 2      Kelembapan              0        44.0       124.0
## 3 Kecepatan_Angin              5        -3.0        13.0
# Capping (Winsorize) untuk setiap fitur numerik
# Batas dihitung dari data latih, lalu diterapkan ke data latih dan data uji
X_train_capped <- X_train
X_test_capped  <- X_test

for (i in list_num) {
  batas <- outliers %>% filter(Kolom == i)
  lower <- batas$Lower_Bound
  upper <- batas$Upper_Bound

  X_train_capped[[i]] <- Winsorize(X_train[[i]], val = c(lower, upper))
  X_test_capped[[i]]  <- Winsorize(X_test[[i]],  val = c(lower, upper))
}

# Fungsi plot diagnostik
diagnostic_plots <- function(df, variable) {

  p1 <- ggplot(df, aes(x = .data[[variable]])) +
    geom_histogram(bins = 30, fill = "#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)
}

Tabel 4.5 Jumlah outlier dan batas IQR pada data latih

Variabel Jumlah outlier Batas bawah Batas atas
Suhu 0 17,5 35,9
Kelembapan 0 44,0 124,0
Kecepatan_Angin 5 −3,0 13,0
diagnostic_plots(X_train, "Suhu")
Gambar 4.1 Histogram dan boxplot Suhu sebelum capping

Gambar 4.1 Histogram dan boxplot Suhu sebelum capping

diagnostic_plots(X_train_capped, "Suhu")
Gambar 4.2 Histogram dan boxplot Suhu setelah capping

Gambar 4.2 Histogram dan boxplot Suhu setelah capping

diagnostic_plots(X_train, "Kelembapan")
Gambar 4.3 Histogram dan boxplot Kelembapan sebelum capping

Gambar 4.3 Histogram dan boxplot Kelembapan sebelum capping

diagnostic_plots(X_train_capped, "Kelembapan")
Gambar 4.4 Histogram dan boxplot Kelembapan setelah capping

Gambar 4.4 Histogram dan boxplot Kelembapan setelah capping

diagnostic_plots(X_train, "Kecepatan_Angin")
Gambar 4.5 Histogram dan boxplot Kecepatan_Angin sebelum capping

Gambar 4.5 Histogram dan boxplot Kecepatan_Angin sebelum capping

diagnostic_plots(X_train_capped, "Kecepatan_Angin")
Gambar 4.6 Histogram dan boxplot Kecepatan_Angin setelah capping

Gambar 4.6 Histogram dan boxplot Kecepatan_Angin setelah capping

Pada batasan masalah diminta capping pada data numerik. Deteksi outlier memakai metode IQR, yaitu nilai di bawah \(Q1 − 1,5×IQR\) atau di atas \(Q3 + 1,5×IQR\) dikategorikan sebagai outlier. Batas dihitung dari data latih saja agar tidak terjadi kebocoran data dari data uji. Hasilnya tersaji pada Tabel 4.5, yaitu Suhu dan Kelembapan tidak memiliki outlier, sedangkan Kecepatan Angin memiliki 5 outlier.

Variabel Suhu (Gambar 4.1 dan 4.2) berkisar sekitar 22,5 sampai 31 dengan median sekitar 26. Histogramnya menyebar tanpa puncak yang ekstrem, dan boxplot tidak menampilkan titik di luar whisker. Capping tidak mengubah data karena tidak ada outlier. Grafik sebelum dan sesudah capping menjadi identik.

Variabel Kelembapan (Gambar 4.3 dan 4.4) berkisar sekitar 52 sampai 100 dengan median sekitar 86. Histogramnya menceng ke kiri dengan frekuensi tertinggi di sekitar nilai 95 sampai 97. Nilai terendahnya masih berada di atas batas bawah 44 sehingga tidak ada outlier. Grafik sebelum dan sesudah capping pun identik.

Variabel Kecepatan Angin sebelum capping (Gambar 4.5) memiliki 5 outlier pada sisi atas, tampak sebagai titik di sekitar nilai 14 dan 15 pada boxplot. Histogramnya menunjukkan lonjakan sangat tinggi pada nilai 3, yaitu sekitar 290 observasi, yang berasal dari mode imputation. Lonjakan ini membuat distribusi terpusat pada satu nilai. Pola tersebut menjadi konsekuensi dari besarnya proporsi nilai kosong yang diisi dengan modus.

Setelah capping dengan Winsorize (Gambar 4.6), nilai yang melebihi 13 diganti menjadi 13 sehingga boxplot tidak lagi menampilkan titik outlier. Batas bawah −3,0 tidak berpengaruh karena nilai minimum data sekitar 2. Capping dipilih karena mempertahankan seluruh observasi dan hanya membatasi nilai ekstrem, sehingga ukuran data latih tetap 594 observasi. Batas yang sama dari data latih juga diterapkan pada data uji.

4.6 Scaling Data

# Standard Scaler
# Parameter mean dan sd dihitung dari data latih saja
mean_val <- sapply(X_train_capped[list_num], mean, na.rm = TRUE)
sd_val   <- sapply(X_train_capped[list_num], sd,   na.rm = TRUE)

X_train_scale <- X_train_capped
X_test_scale  <- X_test_capped

# fit_transform pada data latih
for (col in list_num) {
  X_train_scale[[col]] <- (X_train_capped[[col]] - mean_val[col]) / sd_val[col]
}

# transform pada data uji (memakai parameter data latih)
for (col in list_num) {
  X_test_scale[[col]] <- (X_test_capped[[col]] - mean_val[col]) / sd_val[col]
}

# Verifikasi: mean data latih ~ 0 dan sd ~ 1
round(sapply(X_train_scale[list_num], mean), 4)
##            Suhu      Kelembapan Kecepatan_Angin 
##               0               0               0
round(sapply(X_train_scale[list_num], sd), 4)
##            Suhu      Kelembapan Kecepatan_Angin 
##               1               1               1

Tabel 4.6 Rata-rata dan simpangan baku data latih setelah Standard Scaler

Variabel Rata-rata Simpangan baku
Suhu 0 1
Kelembapan 0 1
Kecepatan Angin 0 1

Pada batasan masalah diminta penggunaan Standard Scaler untuk NPM genap. Metode ini mengubah setiap nilai menjadi z-score dengan rumus \(z = \frac{x - \mu}{\sigma}\), dengan \(\mu\) adalah rata-rata dan \(\sigma\) adalah simpangan baku data latih. Penskalaan menyamakan skala Suhu, Kelembapan, dan Kecepatan Angin yang semula berbeda satuan dan rentang. Skala yang seragam mencegah satu variabel mendominasi hanya karena nilainya besar, terutama pada algoritma yang sensitif terhadap skala.

Verifikasi pada Tabel 4.6 menunjukkan bahwa rata-rata ketiga variabel pada data latih sama dengan 0 dan simpangan bakunya sama dengan 1. Hasil ini menandakan bahwa proses penskalaan berhasil. Parameter \(\mu\) dan \(\sigma\) dihitung dari data latih, lalu dipakai untuk mentransformasi data uji. Cara ini memperlakukan data uji sebagai data baru sehingga tidak terjadi kebocoran informasi.

4.7 Encoding

# One Hot Encoder
list_cat   <- c("Keadaan_Cuaca_reduced")
all_levels <- levels(df_imp$Keadaan_Cuaca_reduced)

# Samakan level kategori pada data latih dan data uji
X_train_scale$Keadaan_Cuaca_reduced <- factor(X_train_scale$Keadaan_Cuaca_reduced, levels = all_levels)
X_test_scale$Keadaan_Cuaca_reduced  <- factor(X_test_scale$Keadaan_Cuaca_reduced,  levels = all_levels)

# Buat resep encoding (fit dari data latih)
resep_encode <- recipe(~ ., data = X_train_scale[, c(list_num, list_cat)]) %>%
  step_unknown(all_of(list_cat)) %>%
  step_dummy(all_of(list_cat), one_hot = TRUE)

resep_encode_prep <- prep(resep_encode, training = X_train_scale[, c(list_num, list_cat)])

# Terapkan encoding (fit_transform pada data latih, transform pada data uji)
X_train_encoded <- bake(resep_encode_prep, new_data = X_train_scale[, c(list_num, list_cat)])
X_test_encoded  <- bake(resep_encode_prep, new_data = X_test_scale[, c(list_num, list_cat)])

head(X_train_encoded)
## # A tibble: 6 × 14
##      Suhu Kelembapan Kecepatan_Angin Keadaan_Cuaca_reduced_X0
##     <dbl>      <dbl>           <dbl>                    <dbl>
## 1 -1.39       0.963           -0.701                        1
## 2  0.0906    -0.581           -0.701                        1
## 3  1.18      -1.87            -1.04                         1
## 4  1.73      -2.47             0.654                        1
## 5  1.49      -2.30             1.33                         1
## 6 -0.143     -0.0660          -0.701                        1
## # ℹ 10 more variables: Keadaan_Cuaca_reduced_X1 <dbl>,
## #   Keadaan_Cuaca_reduced_X2 <dbl>, Keadaan_Cuaca_reduced_X3 <dbl>,
## #   Keadaan_Cuaca_reduced_X4 <dbl>, Keadaan_Cuaca_reduced_X5 <dbl>,
## #   Keadaan_Cuaca_reduced_X6 <dbl>, Keadaan_Cuaca_reduced_X7 <dbl>,
## #   Keadaan_Cuaca_reduced_X8 <dbl>, Keadaan_Cuaca_reduced_X9 <dbl>,
## #   Keadaan_Cuaca_reduced_unknown <dbl>
dim(X_train_encoded)
## [1] 594  14
dim(X_test_encoded)
## [1] 149  14

Pada batasan masalah diminta interpolasi pada Keadaan Cuaca, yang kemudian direduksi menjadi Keadaan Cuaca_reduced sehingga perlu diubah ke bentuk numerik melalui pengodean. Variabel ini bertipe factor sehingga belum dapat diproses langsung oleh sebagian besar algoritma pemodelan. One hot encoding mengubahnya menjadi kolom biner, satu kolom untuk setiap kategori. Nilai 1 menandakan observasi termasuk kategori pada kolom tersebut, sedangkan nilai 0 menandakan sebaliknya.

Pada enam observasi pertama, kolom Keadaan_Cuaca_reduced_X0 bernilai 1 yang berarti seluruhnya termasuk kategori 0, yaitu nilai asli 0 sampai 10. Penyamaan level dengan levels = all_levels memastikan data latih dan data uji memiliki kolom yang sama. Tahap step_unknown menambahkan kolom Keadaan_Cuaca_reduced_unknown untuk menampung kategori yang hilang atau tidak dikenal. Kolom ini seluruhnya bernilai 0 karena data sudah tidak memiliki missing value.

Hasil akhir pengodean memiliki 14 kolom, yaitu 3 fitur numerik terskala, 10 kolom dummy untuk level 0 sampai 9, dan 1 kolom unknown. Data latih berukuran 594 × 14 dan data uji berukuran 149 × 14. Jumlah kolom yang sama pada kedua data menandakan struktur fitur yang konsisten. Resep pengodean dipelajari dari data latih (prep), lalu diterapkan pada kedua data (bake).

4.8 Balancing Data (SMOTE)

# Distribusi kelas sebelum SMOTE
table(y_train)
## y_train
##   1   2 
## 131 463
prop.table(table(y_train))
## y_train
##         1         2 
## 0.2205387 0.7794613
# Gabungkan fitur dan target (SMOTE membutuhkan target bertipe factor)
train_full <- X_train_encoded %>%
  mutate(Hujan = factor(y_train))

set.seed(46)

resep_smote <- recipe(Hujan ~ ., data = train_full) %>%
  step_smote(Hujan, over_ratio = 1, neighbors = 5)

resep_smote_prep <- prep(resep_smote, training = train_full)

train_balanced <- bake(resep_smote_prep, new_data = NULL)

# Distribusi kelas setelah SMOTE
table(train_balanced$Hujan)
## 
##   1   2 
## 463 463
prop.table(table(train_balanced$Hujan))
## 
##   1   2 
## 0.5 0.5
dim(train_balanced)
## [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)))

Tabel 4.7 Distribusi kelas data latih sebelum dan sesudah SMOTE

Kondisi Kelas 1 Kelas 2 Total Proporsi kelas 1 : kelas 2
Sebelum SMOTE 131 463 594 22,05% : 77,95%
Sesudah SMOTE 463 463 926 50% : 50%

Pada batasan masalah diminta penanganan data tidak seimbang menggunakan SMOTE. Sebelum SMOTE, data latih tidak seimbang karena kelas 1 sebagai kelas minoritas hanya berjumlah 131 observasi, sedangkan kelas 2 sebagai kelas mayoritas berjumlah 463 observasi. Kondisi tersebut tersaji pada Tabel 4.7. Model yang dilatih pada data seperti ini cenderung memprediksi kelas mayoritas dan kurang peka terhadap kelas minoritas.

SMOTE (Synthetic Minority Over-sampling Technique) menyeimbangkan kelas dengan membangkitkan observasi sintetis untuk kelas minoritas. Titik baru dibentuk dengan menginterpolasi antara suatu observasi minoritas dan salah satu dari 5 tetangga terdekatnya (neighbors = 5). Argumen over_ratio = 1 menargetkan jumlah kelas minoritas sama dengan kelas mayoritas. Pembangkitan data memakai set.seed(46) agar hasilnya dapat direproduksi.

Sesudah SMOTE, kedua kelas masing-masing berjumlah 463 observasi dengan proporsi 50% : 50%. Sebanyak 332 observasi sintetis dibangkitkan (463 − 131) sehingga ukuran data latih bertambah dari 594 menjadi 926 observasi. Jumlah kolom menjadi 15, yaitu 14 fitur ditambah variabel target Hujan.

SMOTE hanya diterapkan pada data latih. Data uji dibiarkan pada distribusi aslinya agar evaluasi model mencerminkan kondisi data yang sebenarnya. Pada data uji hanya ditambahkan variabel target Hujan dalam bentuk factor sehingga siap digunakan pada tahap pemodelan.

BAB V PENUTUP

5.1 Kesimpulan

Feature engineering adalah proses mentransformasi variabel data menjadi bentuk yang lebih representatif untuk meningkatkan kinerja model prediktif. Konsep ini mencakup berbagai teknik, yaitu imputasi missing value, transformasi variabel, standardisasi, scaling, Label Encoding, One-Hot Encoding, diskretisasi, pembuatan fitur baru, dan seleksi fitur. Masing-masing teknik dipilih sesuai jenis data, yaitu numerik atau kategorik, serta tingkat kardinalitas variabel.

Penerapan teknik feature engineering di RStudio didukung oleh berbagai package yang menyediakan fungsi pada setiap tahap pengolahan data. Penanganan missing value memakai tidyverse dan zoo, pembagian data memakai rsample, dan penanganan outlier memakai DescTools. Pengodean dan penyeimbangan data memakai recipes dan themis, sedangkan visualisasi distribusi memakai ggplot2 dan gridExtra. Rangkaian fungsi tersebut membuat tahapan pengolahan data berjalan secara sistematis dan dapat diulang.

Pada batasan masalah, preprocessing data curah hujan menggunakan mode imputation, stratify splitting, dan Standard Scaler, dilengkapi interpolasi pada Keadaan Cuaca, capping pada data numerik, dan SMOTE. Seluruh missing value berhasil ditangani, kardinalitas Keadaan Cuaca berkurang dari 23 menjadi 7 kategori, dan proporsi kelas data latih serta data uji tetap serupa. Penskalaan menghasilkan rata-rata 0 dan simpangan baku 1, sedangkan SMOTE menyeimbangkan kelas data latih menjadi 463 observasi pada masing-masing kelas.

5.2 Saran

Penelitian selanjutnya disarankan membandingkan beberapa metode pada tahap yang sama, misalnya mean, median, dan mode imputation pada penanganan missing value, atau Standard Scaler dan Robust Scaler pada penskalaan. Perbandingan tersebut dapat dinilai melalui kinerja model sehingga pemilihan teknik memiliki dasar yang lebih kuat. Proporsi missing value yang besar pada Kecepatan Angin juga sebaiknya ditangani dengan metode yang tidak memusatkan nilai pada satu angka, seperti KNN. Selain itu, pengaruh feature engineering terhadap hasil pemodelan perlu diuji agar manfaatnya dapat dibuktikan secara langsung.

DAFTAR PUSTAKA

Asmoro, A. S. B., Irianto, W. S. G., & Pujianto, U. (2021). JEPIN (Jurnal Edukasi dan Penelitian Informatika) Perbandingan Kinerja Hasil Seleksi Fitur pada Prediksi Kinerja Akademik Siswa Berbasis Pohon Keputusan. JEPIN: Jurnal Edukasi dan Penelitian Informatika, 4(2), 84–89. www.kaggle.com/aljarah/xAPI-Edu-Data

Budianita, A. (2023). Information Gain Berbasis Algoritma Naive Bayes Classifier Pada Pemodelan Prediksi Kelulusan Information Gain Based on Naive Bayes Classifier Algorithm in Graduation Prediction Modeling. Jurnal Ilmiah Intech: Information Technology Journal of UMUS, 5(1), 1–10.

Darmawan, R., Yut, I. V., Hernando, A., Handayani, R. I., Pratiwi, R. L., & Widanengsih, E. (2026). Analisis Peran Feature Engineering pada Kinerja Model Machine Learning untuk Klasifikasi Potensi Tsunami. Jurnal Informatika dan Teknik Elektro Terapan, 14(1), 236–249. https://doi.org/10.23960/jitet.v14i1.8303

Fauzi, N. P. N., Khomsah, S., & Wicaksono, A. D. P. (2025). Penerapan Feature Engineering dan Hyperparameter Tuning untuk Meningkatkan Akurasi Model Random Forest pada Klasifikasi Risiko Kredit. Jurnal Teknologi Informasi dan Ilmu Komputer, 12(2), 251–262. https://doi.org/10.25126/jtiik.2025128472

Fransiska, H. (2026). Modul Praktikum Machine Learning and Modern Prediction. Bengkulu: Laboratorium Matematika Fakultas Matematika dan Ilmu Pengetahuan Alam Universitas Bengkulu.

Herdian, C., Kamila, A., Tampinongkol, F. F., Kembau, A. S., & Budidarma, I. G. A. M. (2024). One-Hot Encoding Feature Engineering untuk Label-Based Data Studi Kasus Prediksi Harga Mobil Bekas. Jurnal Informasi Interaktif, 9(1), 10–16.

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. https://doi.org/10.37034/jidt.v5i1.324

Putri, D. F. A., Masjkur, M., & Indahwati. (2023). Penerapan Bernoulli Naïve Bayes untuk Analisis Sentimen Pengguna Twitter Terhadap Layanan Online Food Delivery di Indonesia. Xplore: Journal of Statistics, 12(1), 50–62. https://doi.org/10.29244/xplore.v12i1.1110

Sihombing, D. J. C. (2024). Application of Feature Engineering Techniques and Machine Learning Algorithms for Property Price Prediction. JITSI: Jurnal Ilmiah Teknologi Sistem Informasi, 5(2), 72–76. https://doi.org/10.62527/jitsi.5.2.241