✨ CUSTOMER DATA RESCUE LAB
Praktikum ini mensimulasikan proses menyiapkan data pelanggan e-commerce yang masih “kotor” hingga menjadi dataset siap analisis.

1 Identitas Praktikum

Komponen Keterangan
Nama Syarifah Al Fa’izah
NIM 2403110912
Mata Kuliah Data Mining
Pertemuan 03
Topik Data Preprocessing
Dosen Pengampu Anisa Nurizki, S.Si., M.Si.
Perangkat Lunak R & RStudio
Alokasi Waktu 2 SKS / 100 menit
Acuan Utama Han, Kamber, & Pei — Chapter 3

🎯 Tujuan: menghasilkan dataset pelanggan yang lebih konsisten, lengkap, terdokumentasi, dan siap digunakan untuk tahap analisis atau data mining berikutnya.

2 Capaian Praktikum

Setelah menyelesaikan praktikum, mahasiswa mampu:

  1. menjelaskan kondisi data yang menyebabkan preprocessing diperlukan;
  2. mengidentifikasi masalah kualitas data menggunakan R;
  3. menerapkan data cleaning secara sistematis;
  4. memilih dan menerapkan strategi penanganan missing values;
  5. mendeteksi serta mengevaluasi outlier;
  6. melakukan transformasi atribut numerik; dan
  7. mengintegrasikan dua sumber data serta memvalidasi hasilnya.

3 Skenario Praktikum

Sebuah perusahaan e-commerce ingin melakukan analisis pelanggan. Data berasal dari dua sumber:

  • data pelanggan, berisi identitas, usia, kota, pendapatan, dan status pelanggan;
  • data transaksi, berisi jumlah transaksi dan total pembelian.

Dataset sengaja dibuat memiliki masalah nyata seperti missing value, kategori tidak konsisten, duplikasi, nilai ekstrem, dan perbedaan nama identifier. Tugas praktikum adalah memperbaiki masalah tersebut secara bertahap.

⚠️ Prinsip penting: data tidak boleh diubah hanya karena terlihat aneh. Setiap perubahan harus memiliki alasan, aturan, dan dokumentasi.

4 Persiapan RStudio

4.1 Membuat Project

  1. Buka RStudio.
  2. Pilih File → New Project → New Directory → New Project.
  3. Beri nama project, misalnya customer_data_rescue.
  4. Simpan file .Rmd ini di folder project.
  5. Klik Knit → Knit to HTML untuk menghasilkan laporan.

4.2 Memeriksa Lingkungan Kerja

getwd()
## [1] "C:/Users/infinix/Documents/LEARN/SEMS 5/DATA MINING"
R.version.string
## [1] "R version 4.4.2 (2024-10-31 ucrt)"

Modul utama menggunakan fungsi dasar R sehingga proses inti dapat dijalankan tanpa paket tambahan.

5 Membangun Dataset Praktikum

Dataset dibuat dengan struktur yang sama seperti contoh praktikum: data pelanggan dan data transaksi.

pelanggan_raw <- data.frame(
  customer_id = c("C001","C002","C003","C004","C005","C006",
                  "C007","C008","C009","C010","C010","C011"),
  nama = c("Ani","Budi","Citra","Dodi","Eka","Fani",
           "Gilang","Hana","Indra","Joko","Joko","Kiki"),
  usia = c(21,25,23,150,27,NA,31,29,22,35,35,28),
  pendapatan = c(4500000,NA,5200000,4800000,4900000,5100000,
                 500000000,4700000,4600000,5300000,5300000,NA),
  kota = c("Pekanbaru"," PKU","PEKANBARU","Dumai","pekanbaru",
           "DUMAI","Pekanbaru ","Siak","PKU","Dumai","Dumai",NA),
  status = c("Aktif","aktif","ACTIVE","A","Tidak Aktif","nonaktif",
             "Aktif","AKTIF","A","Tidak aktif","Tidak aktif","Aktif"),
  stringsAsFactors = FALSE
)

transaksi_raw <- data.frame(
  cust_id = c("C001","C002","C003","C004","C005","C006",
              "C007","C008","C009","C010","C012"),
  jumlah_transaksi = c(5,3,7,2,6,4,20,5,3,8,1),
  total_purchase = c(1500000,900000,2700000,600000,2100000,1300000,
                     25000000,1700000,800000,3200000,250000),
  stringsAsFactors = FALSE
)

pelanggan_raw
transaksi_raw

6 Bagian I — Konsep Data Preprocessing

6.1 Memahami Struktur Data

dim(pelanggan_raw)
## [1] 12  6
names(pelanggan_raw)
## [1] "customer_id" "nama"        "usia"        "pendapatan"  "kota"       
## [6] "status"
str(pelanggan_raw)
## 'data.frame':    12 obs. of  6 variables:
##  $ customer_id: chr  "C001" "C002" "C003" "C004" ...
##  $ nama       : chr  "Ani" "Budi" "Citra" "Dodi" ...
##  $ usia       : num  21 25 23 150 27 NA 31 29 22 35 ...
##  $ pendapatan : num  4.5e+06 NA 5.2e+06 4.8e+06 4.9e+06 5.1e+06 5.0e+08 4.7e+06 4.6e+06 5.3e+06 ...
##  $ kota       : chr  "Pekanbaru" " PKU" "PEKANBARU" "Dumai" ...
##  $ status     : chr  "Aktif" "aktif" "ACTIVE" "A" ...
head(pelanggan_raw)
summary(pelanggan_raw)
##  customer_id            nama                usia          pendapatan       
##  Length:12          Length:12          Min.   : 21.00   Min.   :  4500000  
##  Class :character   Class :character   1st Qu.: 24.00   1st Qu.:  4725000  
##  Mode  :character   Mode  :character   Median : 28.00   Median :  5000000  
##                                        Mean   : 38.73   Mean   : 54440000  
##                                        3rd Qu.: 33.00   3rd Qu.:  5275000  
##                                        Max.   :150.00   Max.   :500000000  
##                                        NA's   :1        NA's   :2          
##      kota              status         
##  Length:12          Length:12         
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
##                                       
## 

6.2 Audit Kualitas Data Awal

audit_data <- function(data) {
  data.frame(
    atribut = names(data),
    tipe = sapply(data, function(x) class(x)[1]),
    jumlah_missing = sapply(data, function(x) sum(is.na(x))),
    persen_missing = round(
      sapply(data, function(x) mean(is.na(x)) * 100), 2
    ),
    jumlah_unik = sapply(data, function(x) length(unique(x))),
    row.names = NULL
  )
}

audit_awal <- audit_data(pelanggan_raw)
audit_awal
cat("Missing value per atribut:\n")
## Missing value per atribut:
colSums(is.na(pelanggan_raw))
## customer_id        nama        usia  pendapatan        kota      status 
##           0           0           1           2           1           0
cat("\nPersentase missing value:\n")
## 
## Persentase missing value:
round(colMeans(is.na(pelanggan_raw)) * 100, 2)
## customer_id        nama        usia  pendapatan        kota      status 
##        0.00        0.00        8.33       16.67        8.33        0.00
cat("\nDuplikasi baris penuh:", sum(duplicated(pelanggan_raw)), "\n")
## 
## Duplikasi baris penuh: 1
cat("Duplikasi customer_id:", sum(duplicated(pelanggan_raw$customer_id)), "\n")
## Duplikasi customer_id: 1
cat("\nKategori kota:\n")
## 
## Kategori kota:
sort(unique(pelanggan_raw$kota))
## [1] " PKU"       "Dumai"      "DUMAI"      "pekanbaru"  "Pekanbaru" 
## [6] "PEKANBARU"  "Pekanbaru " "PKU"        "Siak"
cat("\nKategori status:\n")
## 
## Kategori status:
sort(unique(pelanggan_raw$status))
## [1] "A"           "ACTIVE"      "aktif"       "Aktif"       "AKTIF"      
## [6] "nonaktif"    "Tidak aktif" "Tidak Aktif"
cat("\nRentang usia:\n")
## 
## Rentang usia:
range(pelanggan_raw$usia, na.rm = TRUE)
## [1]  21 150
cat("\nRentang pendapatan:\n")
## 
## Rentang pendapatan:
range(pelanggan_raw$pendapatan, na.rm = TRUE)
## [1] 4.5e+06 5.0e+08

🔎 Temuan awal: terdapat missing value pada usia, pendapatan, dan kota; satu customer_id berulang; kategori kota/status tidak konsisten; usia 150 merupakan kandidat nilai tidak valid; dan pendapatan Rp500 juta merupakan kandidat outlier.

7 Bagian II — Implementasi Data Cleaning

7.1 Membuat Salinan Kerja

pelanggan <- pelanggan_raw

7.2 Membersihkan Spasi dan Kapitalisasi

pelanggan$kota <- trimws(pelanggan$kota)
pelanggan$status <- trimws(pelanggan$status)

pelanggan$kota <- tolower(pelanggan$kota)
pelanggan$status <- tolower(pelanggan$status)

sort(unique(pelanggan$kota))
## [1] "dumai"     "pekanbaru" "pku"       "siak"
sort(unique(pelanggan$status))
## [1] "a"           "active"      "aktif"       "nonaktif"    "tidak aktif"

7.3 Menyeragamkan Kategori

# Kota
pelanggan$kota[pelanggan$kota %in% c("pku", "pekanbaru")] <- "Pekanbaru"
pelanggan$kota[pelanggan$kota == "dumai"] <- "Dumai"
pelanggan$kota[pelanggan$kota == "siak"] <- "Siak"

# Status
pelanggan$status[pelanggan$status %in% c("aktif","active","a")] <- "Aktif"
pelanggan$status[pelanggan$status %in% c("tidak aktif","nonaktif")] <- "Tidak Aktif"

sort(unique(pelanggan$kota))
## [1] "Dumai"     "Pekanbaru" "Siak"
sort(unique(pelanggan$status))
## [1] "Aktif"       "Tidak Aktif"

7.4 Mendeteksi dan Menghapus Duplikasi

pelanggan[
  duplicated(pelanggan$customer_id) |
    duplicated(pelanggan$customer_id, fromLast = TRUE),
]
pelanggan <- pelanggan[!duplicated(pelanggan$customer_id), ]
rownames(pelanggan) <- NULL

dim(pelanggan)
## [1] 11  6

Catatan: deduplikasi berdasarkan customer_id aman jika satu customer memang hanya boleh memiliki satu baris pada tabel pelanggan.

7.5 Memeriksa Aturan Domain

pelanggan[pelanggan$usia < 15 | pelanggan$usia > 100, ]
pelanggan[pelanggan$pendapatan < 0, ]

Nilai usia 150 melanggar aturan domain usia 15–100 tahun. Pada skenario praktikum, pemeriksaan sumber asli menunjukkan bahwa nilai tersebut seharusnya 50.

pelanggan$usia[pelanggan$customer_id == "C004"] <- 50

7.6 Log Perubahan

log_perubahan <- data.frame(
  tahap = c("Standardisasi", "Standardisasi",
            "Deduplikasi", "Koreksi domain"),
  atribut = c("kota", "status", "customer_id", "usia"),
  tindakan = c(
    "PKU dan variasi kapital menjadi Pekanbaru",
    "ACTIVE/A menjadi Aktif; nonaktif menjadi Tidak Aktif",
    "Menghapus kemunculan kedua C010",
    "Usia C004 dikoreksi dari 150 menjadi 50 berdasarkan sumber asli"
  ),
  stringsAsFactors = FALSE
)

log_perubahan

8 Bagian III — Penanganan Missing Values

8.1 Mengidentifikasi Missing Value

colSums(is.na(pelanggan))
## customer_id        nama        usia  pendapatan        kota      status 
##           0           0           1           2           1           0
pelanggan[!complete.cases(pelanggan), ]

8.2 Strategi 1 — Menghapus Baris Tidak Lengkap

pelanggan_complete <- pelanggan[complete.cases(pelanggan), ]

nrow(pelanggan)
## [1] 11
nrow(pelanggan_complete)
## [1] 8
round(
  (1 - nrow(pelanggan_complete) / nrow(pelanggan)) * 100,
  2
)
## [1] 27.27

Hasil menunjukkan bahwa penghapusan seluruh baris tidak lengkap akan membuang 27,27% baris data. Karena ukuran data kecil dan informasi pelanggan masih berguna, strategi ini tidak dipilih sebagai hasil akhir.

8.3 Strategi 2 — Imputasi Median

mean_pendapatan <- mean(pelanggan$pendapatan, na.rm = TRUE)
median_pendapatan <- median(pelanggan$pendapatan, na.rm = TRUE)

mean_pendapatan
## [1] 59900000
median_pendapatan
## [1] 4900000

Karena pendapatan sangat dipengaruhi nilai ekstrem Rp500 juta, median lebih stabil untuk contoh ini.

pelanggan$pendapatan_imputasi <- pelanggan$pendapatan
pelanggan$pendapatan_imputasi[
  is.na(pelanggan$pendapatan_imputasi)
] <- median_pendapatan

median_usia <- median(pelanggan$usia, na.rm = TRUE)

pelanggan$usia_imputasi <- pelanggan$usia
pelanggan$usia_imputasi[
  is.na(pelanggan$usia_imputasi)
] <- median_usia

pelanggan[, c(
  "customer_id", "usia", "usia_imputasi",
  "pendapatan", "pendapatan_imputasi"
)]

8.4 Imputasi Kategori

pelanggan$kota_imputasi <- pelanggan$kota
pelanggan$kota_imputasi[is.na(pelanggan$kota_imputasi)] <- "Tidak diketahui"

table(pelanggan$kota_imputasi, useNA = "ifany")
## 
##           Dumai       Pekanbaru            Siak Tidak diketahui 
##               3               6               1               1

8.5 Indikator Missing

pelanggan$pendapatan_missing <- as.integer(
  is.na(pelanggan$pendapatan)
)

table(pelanggan$pendapatan_missing)
## 
## 0 1 
## 9 2

💡 Keputusan: median digunakan untuk usia dan pendapatan, sedangkan kota yang hilang diberi kategori Tidak diketahui agar ketidakpastian tidak disembunyikan.

8.6 Visualisasi Sebelum dan Sesudah Imputasi

par(mfrow = c(1, 2))

hist(
  pelanggan$pendapatan,
  main = "Sebelum Imputasi",
  xlab = "Pendapatan",
  col = "#A78BFA",
  breaks = 8
)

hist(
  pelanggan$pendapatan_imputasi,
  main = "Sesudah Imputasi Median",
  xlab = "Pendapatan",
  col = "#5EEAD4",
  breaks = 8
)

par(mfrow = c(1, 1))

9 Bagian IV — Penanganan Outlier

9.1 Boxplot

boxplot(
  pelanggan$pendapatan_imputasi,
  horizontal = TRUE,
  col = "#93C5FD",
  main = "Boxplot Pendapatan Setelah Imputasi",
  xlab = "Pendapatan (Rp)"
)

9.2 Batas IQR

q1 <- quantile(pelanggan$pendapatan_imputasi, 0.25)
q3 <- quantile(pelanggan$pendapatan_imputasi, 0.75)
iqr <- IQR(pelanggan$pendapatan_imputasi)

batas_bawah <- q1 - 1.5 * iqr
batas_atas <- q3 + 1.5 * iqr

c(
  Q1 = q1,
  Q3 = q3,
  IQR = iqr,
  batas_bawah = batas_bawah,
  batas_atas = batas_atas
)
##          Q1.25%          Q3.75%             IQR batas_bawah.25%  batas_atas.75% 
##         4750000         5150000          400000         4150000         5750000

9.3 Menandai Kandidat Outlier

pelanggan$outlier_pendapatan <-
  pelanggan$pendapatan_imputasi < batas_bawah |
  pelanggan$pendapatan_imputasi > batas_atas

pelanggan[
  pelanggan$outlier_pendapatan,
  c("customer_id", "nama", "pendapatan_imputasi")
]

Hasil menunjukkan C007 (Gilang) dengan pendapatan Rp500.000.000 sebagai kandidat outlier.

9.4 Winsorizing sebagai Perbandingan

pelanggan$pendapatan_winsor <- pmin(
  pmax(pelanggan$pendapatan_imputasi, batas_bawah),
  batas_atas
)

pelanggan[
  pelanggan$outlier_pendapatan,
  c("customer_id", "pendapatan_imputasi", "pendapatan_winsor")
]

⚠️ Interpretasi: nilai ekstrem tidak otomatis dihapus. Nilai Rp500 juta dipertahankan sebagai data asli dan versi winsorized dibuat hanya untuk melihat dampak metode.

10 Bagian V — Transformasi Data

10.1 Normalisasi Min–Maks

Rumus:

\[ x' = \frac{x-\min(x)}{\max(x)-\min(x)} \]

minmax <- function(x) {
  if (all(is.na(x))) return(rep(NA_real_, length(x)))

  rentang <- max(x, na.rm = TRUE) - min(x, na.rm = TRUE)

  if (rentang == 0) return(rep(0, length(x)))

  (x - min(x, na.rm = TRUE)) / rentang
}

pelanggan$usia_minmax <- minmax(pelanggan$usia_imputasi)
pelanggan$pendapatan_minmax <- minmax(pelanggan$pendapatan_imputasi)

pelanggan[, c(
  "customer_id", "usia", "usia_minmax",
  "pendapatan_imputasi", "pendapatan_minmax"
)]

10.2 Normalisasi Z-Score

\[ z = \frac{x-\bar{x}}{s} \]

pelanggan$usia_z <- as.numeric(scale(pelanggan$usia_imputasi))
pelanggan$pendapatan_z <- as.numeric(
  scale(pelanggan$pendapatan_imputasi)
)

round(
  pelanggan[, c("usia_z", "pendapatan_z")],
  3
)

10.3 Decimal Scaling

decimal_scale <- function(x) {
  if (all(is.na(x))) return(rep(NA_real_, length(x)))

  j <- ifelse(max(abs(x), na.rm = TRUE) == 0, 0,
              ceiling(log10(max(abs(x), na.rm = TRUE)) + 1))

  x / (10^j)
}

pelanggan$pendapatan_decimal <-
  decimal_scale(pelanggan$pendapatan_imputasi)

pelanggan[, c(
  "customer_id", "pendapatan_imputasi",
  "pendapatan_decimal"
)]

10.4 Membandingkan Dampak Outlier

pelanggan$pendapatan_winsor_minmax <-
  minmax(pelanggan$pendapatan_winsor)

plot(
  pelanggan$pendapatan_minmax,
  pelanggan$pendapatan_winsor_minmax,
  pch = 19,
  col = "#7C3AED",
  xlab = "Min–maks Data Asli",
  ylab = "Min–maks Data Winsorized",
  main = "Dampak Outlier terhadap Normalisasi"
)

abline(0, 1, col = "#E11D48", lty = 2)

📌 Insight: outlier dapat membuat sebagian besar nilai lain terkonsentrasi pada rentang yang sangat sempit setelah normalisasi min–maks.

11 Bagian VI — Integrasi Data

11.1 Memeriksa Kunci

sum(duplicated(pelanggan$customer_id))
## [1] 0
sum(duplicated(transaksi_raw$cust_id))
## [1] 0
setdiff(pelanggan$customer_id, transaksi_raw$cust_id)
## [1] "C011"
setdiff(transaksi_raw$cust_id, pelanggan$customer_id)
## [1] "C012"

Hasil:

  • C011 ada pada data pelanggan tetapi tidak memiliki pasangan transaksi.
  • C012 ada pada data transaksi tetapi tidak memiliki pasangan data pelanggan.

11.2 Menyelaraskan Identifier

transaksi <- transaksi_raw
names(transaksi)[names(transaksi) == "cust_id"] <- "customer_id"

11.3 Left Join dengan merge()

data_terintegrasi <- merge(
  pelanggan,
  transaksi,
  by = "customer_id",
  all.x = TRUE
)

data_terintegrasi[
  ,
  c("customer_id", "nama",
    "jumlah_transaksi", "total_purchase")
]

🔗 Mengapa left join? Karena seluruh pelanggan pada tabel utama harus tetap dipertahankan meskipun belum memiliki pasangan transaksi.

11.4 Validasi Integrasi

c(
  sebelum = nrow(pelanggan),
  sesudah = nrow(data_terintegrasi)
)
## sebelum sesudah 
##      11      11
sum(duplicated(data_terintegrasi$customer_id))
## [1] 0
colSums(
  is.na(
    data_terintegrasi[, c(
      "jumlah_transaksi",
      "total_purchase"
    )]
  )
)
## jumlah_transaksi   total_purchase 
##                1                1
data_terintegrasi[
  is.na(data_terintegrasi$jumlah_transaksi),
  c("customer_id", "nama")
]

11.5 Menentukan Perlakuan NA Transaksi

NA transaksi dapat berarti:

  1. pelanggan benar-benar belum pernah bertransaksi; atau
  2. data transaksi pelanggan tidak tersedia/gagal dipadankan.

Nilai NA hanya boleh diubah menjadi 0 jika definisi tersebut sudah dikonfirmasi. Untuk skenario praktikum, diasumsikan bahwa C011 memang belum memiliki transaksi, sehingga NA dikonversi menjadi 0.

data_terintegrasi$jumlah_transaksi_final <-
  data_terintegrasi$jumlah_transaksi

data_terintegrasi$total_purchase_final <-
  data_terintegrasi$total_purchase

data_terintegrasi$jumlah_transaksi_final[
  is.na(data_terintegrasi$jumlah_transaksi_final)
] <- 0

data_terintegrasi$total_purchase_final[
  is.na(data_terintegrasi$total_purchase_final)
] <- 0

12 Dataset Akhir dan Evaluasi

12.1 Memilih Atribut Akhir

data_final <- data_terintegrasi[, c(
  "customer_id",
  "nama",
  "usia_imputasi",
  "kota_imputasi",
  "status",
  "pendapatan_imputasi",
  "pendapatan_missing",
  "outlier_pendapatan",
  "usia_minmax",
  "pendapatan_minmax",
  "jumlah_transaksi_final",
  "total_purchase_final"
)]

names(data_final)[names(data_final) == "kota_imputasi"] <- "kota"
names(data_final)[names(data_final) == "usia_imputasi"] <- "usia"

data_final

12.2 Audit Akhir

audit_akhir <- audit_data(data_final)
audit_akhir
sum(duplicated(data_final$customer_id))
## [1] 0
colSums(is.na(data_final))
##            customer_id                   nama                   usia 
##                      0                      0                      0 
##                   kota                 status    pendapatan_imputasi 
##                      0                      0                      0 
##     pendapatan_missing     outlier_pendapatan            usia_minmax 
##                      0                      0                      0 
##      pendapatan_minmax jumlah_transaksi_final   total_purchase_final 
##                      0                      0                      0

✅ Target akhir: tidak ada duplikasi customer_id dan tidak ada missing value pada dataset akhir setelah strategi preprocessing diterapkan.

12.3 Perbandingan Sebelum dan Sesudah

perbandingan <- data.frame(
  indikator = c(
    "Jumlah baris",
    "Duplikasi customer_id",
    "Total missing value",
    "Kategori kota unik",
    "Kategori status unik"
  ),
  sebelum = c(
    nrow(pelanggan_raw),
    sum(duplicated(pelanggan_raw$customer_id)),
    sum(is.na(pelanggan_raw)),
    length(unique(pelanggan_raw$kota)),
    length(unique(pelanggan_raw$status))
  ),
  sesudah = c(
    nrow(data_final),
    sum(duplicated(data_final$customer_id)),
    sum(is.na(data_final)),
    length(unique(data_final$kota)),
    length(unique(data_final$status))
  )
)

perbandingan

12.4 Menyimpan Hasil

write.csv(
  data_final,
  "data_pelanggan_setelah_preprocessing.csv",
  row.names = FALSE
)

write.csv(
  log_perubahan,
  "log_perubahan_preprocessing.csv",
  row.names = FALSE
)

13 Pertanyaan Refleksi

13.0.1 1. Apakah dataset tanpa missing value selalu lebih berkualitas?

Tidak selalu. Menghilangkan missing value memang membuat data terlihat lengkap, tetapi dapat mengurangi ukuran sampel atau menghilangkan informasi penting. Kualitas data harus dinilai berdasarkan tujuan analisis.

13.0.2 2. Mengapa outlier tidak boleh otomatis dihapus?

Karena outlier dapat merupakan kesalahan input, observasi valid yang ekstrem, atau anggota populasi yang berbeda. Keputusan harus didasarkan pada konteks dan verifikasi data.

13.0.3 3. Bagaimana preprocessing dapat menimbulkan bias?

Imputasi, penghapusan data, standardisasi kategori, dan pembatasan outlier dapat mengubah distribusi data. Jika aturan diterapkan secara tidak tepat, karakteristik asli data dapat berubah.

13.0.4 4. Mengapa parameter imputasi dan transformasi seharusnya dihitung dari data pelatihan?

Dalam analisis prediktif, parameter seperti median, mean, atau batas transformasi sebaiknya dihitung dari data pelatihan agar informasi dari data pengujian tidak “bocor” ke proses pembentukan model.

13.0.5 5. Apa risiko integrasi data jika identifier tidak unik?

Identifier yang tidak unik dapat menyebabkan satu pelanggan dipasangkan dengan beberapa baris secara tidak semestinya sehingga jumlah observasi membengkak dan hasil analisis menjadi bias.

14 Ringkasan

Alur preprocessing yang telah dilakukan:

Audit → Cleaning → Missing Values → Outlier → Transformasi → Integrasi → Validasi

🌈 Kesimpulan: preprocessing bukan sekadar menjalankan kode R. Setiap perubahan pada data harus mempunyai alasan, aturan, dan dokumentasi. Dataset akhir yang baik bukan hanya bebas dari error teknis, tetapi juga sesuai dengan tujuan analisis dan konteks data.

15 Daftar Pustaka

  1. Han, J., Kamber, M., & Pei, J. (2012). Data Mining: Concepts and Techniques (3rd ed.). Morgan Kaufmann. Chapter 3: Data Preprocessing. ISBN 978-0-12-381479-1.

  2. Wickham, H., & Grolemund, G. (2017). R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. O’Reilly Media.

📚 Catatan sumber: Referensi utama Han, Kamber, & Pei memang memuat Chapter 3 tentang Data Preprocessing, termasuk data cleaning, data integration, data reduction, serta data transformation. Referensi R for Data Science digunakan sebagai pendukung penggunaan R dalam pengolahan dan eksplorasi data.