1 Pendahuluan

1.1 Latar Belakang

Data preprocessing merupakan tahap penting dalam data mining karena data mentah sering kali belum siap langsung digunakan untuk analisis. Data dapat mengandung missing value, duplikasi, kategori yang tidak konsisten, kesalahan domain, dan nilai ekstrem (outlier).

Tugas ini mengikuti alur pada materi Data Preprocessing Menggunakan RStudio, yaitu memahami kondisi awal data, melakukan data cleaning, menangani missing values, mengevaluasi outlier, melakukan transformasi atribut numerik, mengintegrasikan dua sumber data, dan melakukan validasi akhir. Materi praktikum menggunakan fungsi dasar R sehingga tidak memerlukan paket tambahan.

1.2 Tujuan Praktikum

Setelah menyelesaikan praktikum, diharapkan dapat:

  1. Mengidentifikasi masalah kualitas data menggunakan R.
  2. Melakukan data cleaning secara sistematis.
  3. Menangani missing values.
  4. Mendeteksi dan mengevaluasi outlier.
  5. Melakukan transformasi atribut numerik.
  6. Mengintegrasikan dua sumber data.
  7. Memvalidasi kondisi data setelah preprocessing.

2 Persiapan RStudio

2.1 Memeriksa lingkungan kerja

Kode berikut digunakan untuk mengetahui direktori kerja dan versi R yang digunakan.

getwd()
## [1] "/Users/naylanurannie/Downloads"
R.version.string
## [1] "R version 4.5.1 (2025-06-13)"

3 Membangun Dataset Praktikum

Dataset berikut terdiri dari 11 data pelanggan dan sengaja dibuat memiliki beberapa masalah agar seluruh tahapan preprocessing dapat dipraktikkan. Masalah tersebut meliputi duplikasi customer_id, missing value, kategori tidak konsisten, kesalahan nilai usia, dan nilai pendapatan yang sangat besar.

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

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

pelanggan_raw
transaksi_raw
dim(pelanggan_raw)
## [1] 11  6
names(pelanggan_raw)
## [1] "customer_id" "nama"        "usia"        "pendapatan"  "kota"       
## [6] "status"
str(pelanggan_raw)
## 'data.frame':    11 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:11          Length:11          Min.   : 21.0   Min.   :  4500000  
##  Class :character   Class :character   1st Qu.: 23.5   1st Qu.:  4725000  
##  Mode  :character   Mode  :character   Median : 28.0   Median :  5000000  
##                                        Mean   : 39.8   Mean   : 54440000  
##                                        3rd Qu.: 34.0   3rd Qu.:  5275000  
##                                        Max.   :150.0   Max.   :500000000  
##                                        NA's   :1       NA's   :1          
##      kota              status         
##  Length:11          Length:11         
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
##                                       
## 

3.1 Audit awal kualitas data

3.1.1 Missing value

# Banyak missing value per atribut
colSums(is.na(pelanggan_raw))
## customer_id        nama        usia  pendapatan        kota      status 
##           0           0           1           1           0           0
# Persentase missing value per atribut
round(colMeans(is.na(pelanggan_raw)) * 100, 2)
## customer_id        nama        usia  pendapatan        kota      status 
##        0.00        0.00        9.09        9.09        0.00        0.00

3.1.2 Duplikasi

# Banyak baris duplikat penuh
sum(duplicated(pelanggan_raw))
## [1] 1
# Banyak customer_id yang berulang
sum(duplicated(pelanggan_raw$customer_id))
## [1] 1

3.1.3 Konsistensi kategori

# Kategori yang tercatat pada atribut kota dan status
sort(unique(pelanggan_raw$kota))
## [1] " PKU"       "Dumai"      "DUMAI"      "pekanbaru"  "Pekanbaru" 
## [6] "PEKANBARU"  "Pekanbaru " "PKU"        "Siak"
sort(unique(pelanggan_raw$status))
## [1] "A"           "ACTIVE"      "aktif"       "Aktif"       "AKTIF"      
## [6] "nonaktif"    "Tidak aktif" "Tidak Aktif"

3.1.4 Rentang atribut numerik

range(pelanggan_raw$usia, na.rm = TRUE)
## [1]  21 150
range(pelanggan_raw$pendapatan, na.rm = TRUE)
## [1] 4.5e+06 5.0e+08

3.2 Fungsi audit data

Fungsi berikut membuat ringkasan kualitas setiap atribut sehingga pemeriksaan dapat dilakukan secara lebih sistematis.

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

4 Bagian II — Data Cleaning

4.1 Menyiapkan data untuk dibersihkan

pelanggan <- pelanggan_raw

4.2 Standardisasi kategori

Pada data mentah terdapat perbedaan spasi dan penggunaan huruf besar-kecil. Tahap pertama adalah membersihkan spasi, kemudian menyeragamkan huruf menjadi kecil untuk memudahkan pencocokan kategori.

# Menghapus spasi di awal dan akhir
pelanggan$kota <- trimws(pelanggan$kota)
pelanggan$status <- trimws(pelanggan$status)

# Menyeragamkan huruf menjadi kecil untuk proses pencocokan
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"

Selanjutnya kategori diseragamkan menjadi label yang konsisten.

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

# Standardisasi 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"

4.3 Deduplikasi

customer_id digunakan sebagai identifier pelanggan. Baris dengan identifier yang berulang diperiksa terlebih dahulu.

# Menampilkan seluruh baris dengan customer_id yang berulang
pelanggan[duplicated(pelanggan$customer_id) |
          duplicated(pelanggan$customer_id, fromLast = TRUE), ]

Kemunculan kedua untuk C010 dihapus.

# Mempertahankan kemunculan pertama untuk customer_id yang identik
pelanggan <- pelanggan[!duplicated(pelanggan$customer_id), ]
rownames(pelanggan) <- NULL

dim(pelanggan)
## [1] 10  6

4.4 Pemeriksaan aturan domain

Aturan domain digunakan untuk menemukan nilai yang tidak masuk akal berdasarkan konteks data. Pada contoh ini usia yang dianggap masuk akal adalah 15–100 tahun.

# Kandidat usia tidak valid berdasarkan aturan bisnis 15–100 tahun
pelanggan[pelanggan$usia < 15 | pelanggan$usia > 100, ]

Pendapatan negatif juga diperiksa sebagai kandidat pelanggaran domain.

# Kandidat pendapatan tidak valid jika bernilai negatif
pelanggan[pelanggan$pendapatan < 0, ]

Nilai usia C004 sebesar 150 diperbaiki menjadi 50 berdasarkan sumber asli.

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

4.5 Log perubahan

Pencatatan perubahan penting agar proses preprocessing dapat ditelusuri.

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

5 Bagian III — Penanganan Missing Values

5.1 Mengidentifikasi lokasi nilai hilang

colSums(is.na(pelanggan))
## customer_id        nama        usia  pendapatan        kota      status 
##           0           0           1           1           0           0
# Baris yang memiliki sedikitnya satu missing value
pelanggan[!complete.cases(pelanggan), ]

5.2 Strategi 1 — Menghapus baris lengkap

Sebagai ilustrasi, data tanpa missing value dapat diperoleh dengan complete.cases(). Jumlah baris sebelum dan sesudah dibandingkan.

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

nrow(pelanggan)
## [1] 10
nrow(pelanggan_complete)
## [1] 8
# Persentase baris yang terhapus
round((1 - nrow(pelanggan_complete) / nrow(pelanggan)) * 100, 2)
## [1] 20

5.3 Strategi 2 — Imputasi median

Untuk atribut numerik, median digunakan sebagai salah satu strategi imputasi. Mean juga dihitung sebagai pembanding.

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

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

Pendapatan dan usia kemudian dibuat versi imputasinya tanpa menghilangkan kolom asli.

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

# Imputasi usia dengan median
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")]

5.4 Imputasi kategori

Untuk kota yang tidak diketahui, digunakan label Tidak diketahui agar ketidakpastian tidak disamarkan sebagai kategori tertentu.

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

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

5.5 Menambahkan indikator missing

Indikator biner dapat digunakan untuk mempertahankan informasi bahwa nilai pendapatan pada awalnya merupakan missing value.

pelanggan$pendapatan_missing <- as.integer(is.na(pelanggan$pendapatan))
table(pelanggan$pendapatan_missing)
## 
## 0 1 
## 9 1

5.6 Membandingkan distribusi sebelum dan sesudah imputasi

par(mfrow = c(1, 2))
hist(pelanggan$pendapatan,
     main = "Sebelum Imputasi",
     xlab = "Pendapatan", col = "skyblue", breaks = 8)
hist(pelanggan$pendapatan_imputasi,
     main = "Sesudah Imputasi Median",
     xlab = "Pendapatan", col = "lightgreen", breaks = 8)

par(mfrow = c(1, 1))

6 Bagian IV — Penanganan Outlier

6.1 Visualisasi dengan boxplot

Boxplot digunakan untuk membantu melihat kandidat nilai ekstrem pada pendapatan.

boxplot(pelanggan$pendapatan_imputasi,
        horizontal = TRUE,
        col = "lightblue",
        main = "Boxplot Pendapatan",
        xlab = "Pendapatan")

6.2 Menghitung batas IQR

Metode IQR menggunakan Q1, Q3, dan IQR untuk menentukan batas bawah dan batas atas kandidat outlier.

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% 
##         4725000         5175000          450000         4050000         5850000

6.3 Menandai kandidat outlier

Nilai yang berada di luar batas IQR ditandai sebagai kandidat outlier. Penandaan ini bukan berarti nilai langsung dihapus.

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

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

6.4 Winsorization

Sebagai contoh penanganan, nilai yang berada di luar batas digeser ke batas bawah atau batas atas menggunakan winsorization.

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

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

7 Bagian V — Transformasi Data

Transformasi digunakan untuk mengubah skala atribut numerik. Tiga metode yang digunakan dalam praktikum ini adalah min–maks, z-score, dan decimal scaling.

7.1 Normalisasi min–maks

Rumus min–maks untuk rentang [0,1] adalah:

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

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")]

7.2 Normalisasi z-score

Z-score mengubah nilai menjadi ukuran relatif terhadap mean dan simpangan baku.

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)

7.3 Decimal scaling

decimal_scale <- function(x) {
  maks <- max(abs(x), na.rm = TRUE)
  if (maks == 0) return(x)
  j <- ceiling(log10(maks + 1))
  x / (10 ^ j)
}

pelanggan$pendapatan_decimal <-
  decimal_scale(pelanggan$pendapatan_imputasi)

range(pelanggan$pendapatan_decimal, na.rm = TRUE)
## [1] 0.0045 0.5000

7.4 Membandingkan metode transformasi

transformasi <- pelanggan[, c(
  "customer_id", "pendapatan_imputasi", "pendapatan_minmax",
  "pendapatan_z", "pendapatan_decimal"
)]

transformasi

7.5 Dampak outlier terhadap normalisasi

Perbandingan berikut menunjukkan bagaimana penanganan outlier dapat memengaruhi hasil normalisasi min–maks.

pelanggan$pendapatan_winsor_minmax <- minmax(pelanggan$pendapatan_winsor)

plot(pelanggan$pendapatan_minmax,
     pelanggan$pendapatan_winsor_minmax,
     pch = 19, col = "navy",
     xlab = "Min–maks Data Asli",
     ylab = "Min–maks Data Winsorized",
     main = "Dampak Penanganan Outlier terhadap Normalisasi")
abline(0, 1, col = "red", lty = 2)

8 Bagian VI — Integrasi Data

8.1 Memeriksa kunci pada kedua sumber

Sebelum melakukan integrasi, identifier harus diperiksa agar tidak menghasilkan penggandaan baris yang tidak diinginkan.

sum(duplicated(pelanggan$customer_id))
## [1] 0
sum(duplicated(transaksi_raw$cust_id))
## [1] 0
# Customer yang ada di pelanggan tetapi tidak ada di transaksi
setdiff(pelanggan$customer_id, transaksi_raw$cust_id)
## character(0)
# Customer yang ada di transaksi tetapi tidak ada di pelanggan
setdiff(transaksi_raw$cust_id, pelanggan$customer_id)
## [1] "C999"

8.2 Menyamakan nama kunci

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

8.3 Menggabungkan data

merge(..., all.x = TRUE) digunakan untuk mempertahankan seluruh pelanggan dan mengambil informasi transaksi yang cocok.

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

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

8.4 Validasi hasil integrasi

# Apakah jumlah baris berubah secara tidak wajar?
c(sebelum = nrow(pelanggan), sesudah = nrow(data_terintegrasi))
## sebelum sesudah 
##      10      10
# Apakah customer_id tetap unik?
sum(duplicated(data_terintegrasi$customer_id))
## [1] 0
# Missing value baru akibat tidak ditemukan pasangan transaksi
colSums(is.na(data_terintegrasi[, c("jumlah_transaksi", "total_purchase")]))
## jumlah_transaksi   total_purchase 
##                1                1

Pelanggan yang tidak memiliki pasangan transaksi ditampilkan untuk diperiksa lebih lanjut.

data_terintegrasi[is.na(data_terintegrasi$jumlah_transaksi),
                  c("customer_id", "nama")]

8.5 Penanganan pelanggan tanpa transaksi

Jika setelah pemeriksaan diketahui bahwa NA memang berarti pelanggan belum pernah bertransaksi, nilai dapat diubah 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

9 Bagian VII — Dataset Final dan Audit Akhir

9.1 Membentuk dataset final

Hanya variabel yang diperlukan untuk dataset akhir dipertahankan.

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

9.2 Audit akhir

audit_akhir <- audit_data(data_final)
audit_akhir
# Memeriksa kembali duplikasi identifier
sum(duplicated(data_final$customer_id))
## [1] 0
# Memeriksa kembali missing value
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

9.3 Membandingkan kondisi 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

9.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)

10 Kesimpulan

Berdasarkan seluruh tahapan praktikum, preprocessing dilakukan secara bertahap mulai dari memahami struktur dan kualitas awal data, membersihkan kategori, menghapus duplikasi, memperbaiki pelanggaran domain, menangani missing values, mendeteksi dan mengevaluasi outlier, melakukan transformasi numerik, mengintegrasikan data, hingga melakukan audit akhir.

Hal penting yang perlu diperhatikan adalah bahwa preprocessing bukan sekadar menjalankan kode. Setiap perubahan terhadap data merupakan keputusan yang perlu memiliki alasan. Outlier tidak otomatis dihapus, missing value tidak selalu harus dibuang, dan hasil integrasi harus divalidasi agar tidak menimbulkan duplikasi atau kesalahan baru.

11 Pertanyaan Refleksi

  1. Apakah dataset tanpa missing value selalu lebih berkualitas?
  2. Mengapa outlier tidak boleh otomatis dihapus?
  3. Bagaimana preprocessing dapat menimbulkan bias?
  4. Mengapa parameter imputasi dan transformasi seharusnya dihitung dari data pelatihan?
  5. Apa risiko integrasi data jika identifier tidak unik?

12 Ringkasan Alur

Data mentah
    ↓
Eksplorasi dan audit awal
    ↓
Standardisasi kategori
    ↓
Deduplikasi dan pemeriksaan domain
    ↓
Penanganan missing value
    ↓
Deteksi dan evaluasi outlier
    ↓
Transformasi data
    ↓
Integrasi data
    ↓
Audit akhir
    ↓
Data siap digunakan untuk analisis/data mining