Preprocessing_Data_Ecommerce
1. Pendahuluan
Dalam proses analisis data pelanggan pada perusahaan e-commerce, data yang berasal dari sistem operasional belum tentu berada dalam kondisi yang siap digunakan. Data dapat mengandung nilai yang hilang, perbedaan penulisan kategori, identitas pelanggan yang tercatat lebih dari satu kali, nilai yang tidak sesuai dengan aturan domain, hingga nilai ekstrem yang dapat memengaruhi hasil analisis.
Pada studi kasus ini, perusahaan memiliki dua sumber data utama, yaitu data pelanggan dan data transaksi. Kedua sumber tersebut perlu diperiksa dan dipersiapkan terlebih dahulu agar memiliki struktur dan format yang konsisten sebelum digunakan untuk menganalisis perilaku belanja pelanggan.
Proses preprocessing dilakukan secara bertahap, dimulai dari memahami struktur data dan mengevaluasi kualitas data awal, kemudian dilanjutkan dengan cleaning, penanganan missing value, pemeriksaan nilai tidak valid, deteksi outlier, transformasi variabel, pengolahan data transaksi, integrasi kedua sumber data, hingga pemeriksaan akhir.
2. Studi Kasus
Sebuah tim analitik pada perusahaan e-commerce sedang menyiapkan data pelanggan untuk digunakan dalam analisis perilaku belanja. Data pelanggan berasal dari sistem administrasi perusahaan, sedangkan data transaksi diperoleh dari sistem penjualan.
Data pelanggan memuat informasi mengenai identitas pelanggan, usia, pendapatan, kota domisili, status pelanggan, metode pembayaran, serta lama menjadi anggota. Sementara itu, data transaksi mencatat informasi mengenai ID transaksi, ID pelanggan, jumlah transaksi, dan total nilai pembelian.
Dalam proses pemeriksaan awal ditemukan beberapa persoalan kualitas data. Permasalahan tersebut meliputi nilai yang hilang, penulisan kategori yang tidak seragam, duplikasi identitas pelanggan, nilai yang tidak sesuai dengan aturan domain, nilai ekstrem pada variabel tertentu, serta perbedaan nama identifier antara data pelanggan dan data transaksi.
Oleh karena itu, preprocessing dilakukan untuk menghasilkan data yang lebih konsisten, terstruktur, dan dapat digunakan sebagai dasar analisis perilaku belanja pelanggan.
Catatan penting: setiap perubahan terhadap data harus didasarkan pada aturan yang jelas. Nilai yang terlihat tidak biasa tidak selalu berarti salah, sehingga perlu diperiksa berdasarkan konteks dan aturan domain sebelum dilakukan perubahan atau penanganan.
Persiapan RStudio
Tahap ini dilakukan untuk menyiapkan lingkungan kerja R yang akan digunakan dalam seluruh proses preprocessing. Package yang diperlukan dimuat terlebih dahulu agar proses pemeriksaan, pembersihan, transformasi, dan pengolahan data dapat dilakukan dengan fungsi yang sesuai.
## [1] "D:/ham"
## [1] "R version 4.4.1 (2024-06-14 ucrt)"
Membangun Dataset Studi Kasus
Karena proses preprocessing dilakukan dalam sebuah studi kasus e-commerce, data perlu disiapkan terlebih dahulu agar dapat menggambarkan kondisi yang menyerupai permasalahan kualitas data pada sistem perusahaan.
Data yang dibentuk mencakup informasi pelanggan dan transaksi sehingga setiap tahap preprocessing dapat menunjukkan bagaimana permasalahan kualitas data ditemukan dan ditangani.
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## customer_id nama usia pendapatan kota status
## 1 C001 Ani 21 4.5e+06 Pekanbaru Aktif
## 2 C002 Budi 25 NA PKU aktif
## 3 C003 Citra 23 5.2e+06 PEKANBARU ACTIVE
## 4 C004 Dodi 150 4.8e+06 Dumai A
## 5 C005 Eka 27 4.9e+06 pekanbaru Tidak Aktif
## 6 C006 Fani NA 5.1e+06 DUMAI nonaktif
## 7 C007 Gilang 31 5.0e+08 Pekanbaru Aktif
## 8 C008 Hana 29 4.7e+06 Siak AKTIF
## 9 C009 Indra 22 4.6e+06 PKU A
## 10 C010 Joko 35 5.3e+06 Dumai Tidak aktif
## 11 C010 Joko 35 5.3e+06 Dumai Tidak aktif
## 12 C011 Kiki 28 NA <NA> Aktif
## cust_id jumlah_transaksi total_purchase
## 1 C001 5 1.5e+06
## 2 C002 3 9.0e+05
## 3 C003 7 2.7e+06
## 4 C004 2 6.0e+05
## 5 C005 6 2.1e+06
## 6 C006 4 1.3e+06
## 7 C007 20 2.5e+07
## 8 C008 5 1.7e+06
## 9 C009 3 8.0e+05
## 10 C010 8 3.2e+06
## 11 C012 1 2.5e+05
Bagian I — Profil dan Kualitas Awal Data
Dataset pelanggan digunakan sebagai sumber utama informasi mengenai karakteristik setiap pelanggan. Variabel yang digunakan mencakup identitas pelanggan, informasi demografis, pendapatan, status, metode pembayaran, serta lama menjadi anggota.
Setelah dataset pelanggan dibentuk, struktur data diperiksa untuk mengetahui jenis variabel, jumlah observasi, serta susunan kolom yang tersedia. Pemeriksaan ini penting sebagai langkah awal untuk memahami bentuk data sebelum dilakukan perubahan.
## [1] 12 6
## [1] "customer_id" "nama" "usia" "pendapatan" "kota"
## [6] "status"
## '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" ...
## customer_id nama usia pendapatan kota status
## 1 C001 Ani 21 4500000 Pekanbaru Aktif
## 2 C002 Budi 25 NA PKU aktif
## 3 C003 Citra 23 5200000 PEKANBARU ACTIVE
## 4 C004 Dodi 150 4800000 Dumai A
## 5 C005 Eka 27 4900000 pekanbaru Tidak Aktif
## 6 C006 Fani NA 5100000 DUMAI nonaktif
## 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
##
##
##
##
Sebelum melakukan proses cleaning, kondisi awal dataset perlu diperiksa dan didokumentasikan. Pemeriksaan ini bertujuan untuk mengetahui permasalahan yang terdapat pada data sehingga proses preprocessing dapat dilakukan secara terarah.
Tahap ini juga menjadi dasar untuk membandingkan kondisi data sebelum dan setelah preprocessing.
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
## customer_id nama usia pendapatan kota status
## 0.00 0.00 8.33 16.67 8.33 0.00
Pemeriksaan missing value dilakukan untuk mengetahui apakah terdapat informasi pelanggan yang tidak tersedia pada variabel tertentu. Nilai yang hilang perlu diidentifikasi karena dapat memengaruhi proses analisis apabila dibiarkan tanpa penanganan.
## [1] 1
## [1] 1
Pemeriksaan duplikasi dilakukan untuk memastikan bahwa satu identitas pelanggan tidak tercatat lebih dari satu kali. Duplikasi identitas dapat menyebabkan jumlah pelanggan terlihat lebih besar dari kondisi sebenarnya dan berpotensi menghasilkan kesalahan ketika data digabungkan dengan transaksi.
## [1] " PKU" "Dumai" "DUMAI" "pekanbaru" "Pekanbaru"
## [6] "PEKANBARU" "Pekanbaru " "PKU" "Siak"
## [1] "A" "ACTIVE" "aktif" "Aktif" "AKTIF"
## [6] "nonaktif" "Tidak aktif" "Tidak Aktif"
## [1] 21 150
## [1] 4.5e+06 5.0e+08
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## atribut tipe jumlah_missing persen_missing jumlah_unik
## 1 customer_id character 0 0.00 11
## 2 nama character 0 0.00 11
## 3 usia numeric 1 8.33 11
## 4 pendapatan numeric 2 16.67 10
## 5 kota character 1 8.33 10
## 6 status character 0 0.00 8
Pemeriksaan kategori dilakukan untuk menemukan penulisan kategori yang tidak seragam. Kategori yang sebenarnya memiliki arti sama dapat tercatat menggunakan variasi penulisan yang berbeda sehingga perlu diidentifikasi sebelum proses analisis dilakukan.
Bagian II — Data Cleaning
Setelah permasalahan kualitas data awal diketahui, tahap berikutnya adalah melakukan data cleaning. Tujuan tahap ini adalah memperbaiki ketidakkonsistenan pada data tanpa menghilangkan informasi yang masih relevan.
Salinan data dibuat agar proses cleaning tidak langsung mengubah dataset mentah. Dengan demikian, data awal tetap dapat digunakan sebagai referensi apabila diperlukan perbandingan antara kondisi sebelum dan sesudah preprocessing.
# 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"
Penulisan nama kota diseragamkan agar variasi format penulisan yang merujuk pada lokasi yang sama tidak dianggap sebagai kategori yang berbeda. Dengan standardisasi ini, distribusi pelanggan berdasarkan wilayah dapat dianalisis dengan lebih tepat.
## [1] "a" "active" "aktif" "nonaktif" "tidak aktif"
Kategori status pelanggan diperiksa dan diseragamkan sehingga setiap status memiliki satu bentuk penulisan yang konsisten. Hal ini penting agar pelanggan dengan status yang sama tidak terpisah menjadi beberapa kelompok akibat perbedaan penulisan.
# 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"
## [1] "Aktif" "Tidak Aktif"
# Menampilkan seluruh baris dengan customer_id yang berulang
pelanggan[duplicated(pelanggan$customer_id) |
duplicated(pelanggan$customer_id, fromLast = TRUE), ]## customer_id nama usia pendapatan kota status
## 10 C010 Joko 35 5300000 Dumai Tidak Aktif
## 11 C010 Joko 35 5300000 Dumai Tidak Aktif
# Mempertahankan kemunculan pertama untuk customer_id yang identik
pelanggan <- pelanggan[!duplicated(pelanggan$customer_id), ]
rownames(pelanggan) <- NULL
dim(pelanggan)## [1] 11 6
# Kandidat usia tidak valid berdasarkan aturan bisnis 15–100 tahun
pelanggan[pelanggan$usia < 15 | pelanggan$usia > 100, ]## customer_id nama usia pendapatan kota status
## 4 C004 Dodi 150 4800000 Dumai Aktif
## NA <NA> <NA> NA NA <NA> <NA>
## customer_id nama usia pendapatan kota status
## NA <NA> <NA> NA NA <NA> <NA>
## NA.1 <NA> <NA> NA NA <NA> <NA>
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## tahap atribut
## 1 Standardisasi kota
## 2 Standardisasi status
## 3 Deduplikasi customer_id
## 4 Koreksi domain usia
## tindakan
## 1 PKU dan variasi kapital menjadi Pekanbaru
## 2 ACTIVE/A menjadi Aktif; nonaktif menjadi Tidak Aktif
## 3 Menghapus kemunculan kedua C010
## 4 Usia C004 dikoreksi dari 150 menjadi 50 berdasarkan sumber asli
Bagian III — Penanganan Missing Values
Setelah missing value berhasil diidentifikasi, diperlukan strategi penanganan yang sesuai dengan karakteristik variabel. Tujuannya adalah mengurangi kehilangan informasi tanpa memasukkan nilai secara sembarangan.
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
## customer_id nama usia pendapatan kota status
## 2 C002 Budi 25 NA Pekanbaru Aktif
## 6 C006 Fani NA 5100000 Dumai Tidak Aktif
## 11 C011 Kiki 28 NA <NA> Aktif
## [1] 11
## [1] 8
## [1] 27.27
mean_pendapatan <- mean(pelanggan$pendapatan, na.rm = TRUE)
median_pendapatan <- median(pelanggan$pendapatan, na.rm = TRUE)
mean_pendapatan## [1] 59900000
## [1] 4900000
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")]## customer_id usia usia_imputasi pendapatan pendapatan_imputasi
## 1 C001 21 21.0 4.5e+06 4.5e+06
## 2 C002 25 25.0 NA 4.9e+06
## 3 C003 23 23.0 5.2e+06 5.2e+06
## 4 C004 50 50.0 4.8e+06 4.8e+06
## 5 C005 27 27.0 4.9e+06 4.9e+06
## 6 C006 NA 27.5 5.1e+06 5.1e+06
## 7 C007 31 31.0 5.0e+08 5.0e+08
## 8 C008 29 29.0 4.7e+06 4.7e+06
## 9 C009 22 22.0 4.6e+06 4.6e+06
## 10 C010 35 35.0 5.3e+06 5.3e+06
## 11 C011 28 28.0 NA 4.9e+06
Nilai usia yang hilang ditangani menggunakan nilai median usia. Median digunakan karena relatif tidak mudah dipengaruhi oleh nilai ekstrem dan dapat mewakili nilai tengah populasi pelanggan.
Selain nilai hasil imputasi, status missing value tetap dicatat agar proses perubahan terhadap data dapat ditelusuri.
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
Untuk variabel kategorik seperti kota, nilai yang kosong ditangani menggunakan kategori yang paling sering muncul. Pendekatan ini digunakan agar data pelanggan tetap memiliki kategori yang dapat digunakan pada analisis tanpa membuat kategori baru yang tidak memiliki dasar pada data.
pelanggan$pendapatan_missing <- as.integer(is.na(pelanggan$pendapatan))
table(pelanggan$pendapatan_missing)##
## 0 1
## 9 2
Pendapatan yang memiliki nilai hilang juga ditangani menggunakan median pendapatan. Pendekatan ini digunakan untuk mempertahankan jumlah observasi pelanggan sekaligus mengurangi pengaruh nilai ekstrem terhadap nilai pengganti.
Kolom penanda missing value tetap dipertahankan sehingga dapat diketahui observasi mana yang sebelumnya memiliki data pendapatan yang kosong.
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)Setelah proses imputasi selesai, dataset diperiksa kembali untuk memastikan bahwa nilai yang hilang telah ditangani sesuai dengan strategi yang ditetapkan.
Pemeriksaan ulang ini diperlukan agar proses preprocessing tidak hanya berhenti setelah pengisian nilai, tetapi juga memastikan kondisi akhir dataset sesuai dengan yang diharapkan.
Bagian IV — Penanganan Outlier
Outlier merupakan observasi yang memiliki nilai jauh berbeda dibandingkan sebagian besar data. Dalam studi kasus ini, perhatian diberikan terutama pada variabel pendapatan karena terdapat kemungkinan pelanggan dengan pendapatan yang jauh lebih tinggi dibandingkan pelanggan lainnya.
Deteksi outlier dilakukan sebagai proses identifikasi, bukan sebagai alasan untuk langsung menghapus observasi. Nilai ekstrem tetap perlu dilihat dalam konteks agar tidak menghilangkan informasi pelanggan yang sebenarnya valid.
boxplot(pelanggan$pendapatan_imputasi,
horizontal = TRUE,
col = "lightblue",
main = "Boxplot Pendapatan",
xlab = "Pendapatan")Boxplot digunakan untuk memperoleh gambaran awal mengenai distribusi pendapatan pelanggan dan melihat apakah terdapat observasi yang berada jauh di luar pola umum data. Visualisasi ini membantu mengidentifikasi kemungkinan adanya nilai ekstrem.
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
Batas outlier dihitung menggunakan metode Interquartile Range (IQR). Nilai kuartil pertama dan kuartil ketiga digunakan untuk menentukan rentang data utama, kemudian diperoleh batas bawah dan batas atas untuk mengidentifikasi observasi yang berada di luar rentang tersebut.
pelanggan$outlier_pendapatan <-
pelanggan$pendapatan_imputasi < batas_bawah |
pelanggan$pendapatan_imputasi > batas_atas
pelanggan[pelanggan$outlier_pendapatan,
c("customer_id", "nama", "pendapatan_imputasi")]## customer_id nama pendapatan_imputasi
## 7 C007 Gilang 5e+08
Observasi yang berada di luar batas IQR diberi penanda sebagai outlier. Penandaan dilakukan agar informasi mengenai nilai ekstrem tetap tersedia sehingga dapat dipertimbangkan dalam analisis berikutnya, bukan langsung dihapus dari dataset.
pelanggan$pendapatan_winsor <- pmin(
pmax(pelanggan$pendapatan_imputasi, batas_bawah),
batas_atas
)
pelanggan[pelanggan$outlier_pendapatan,
c("customer_id", "pendapatan_imputasi", "pendapatan_winsor")]## customer_id pendapatan_imputasi pendapatan_winsor
## 7 C007 5e+08 5750000
Selain mempertahankan nilai asli dan penanda outlier, dibuat pula versi data yang telah melalui proses winsorization. Pendekatan ini membatasi nilai yang terlalu rendah atau terlalu tinggi pada batas yang telah ditentukan.
Versi winsorized digunakan sebagai alternatif ketika analisis membutuhkan data yang lebih terkendali terhadap pengaruh nilai ekstrem, sementara nilai asli tetap dipertahankan untuk keperluan audit dan perbandingan.
Bagian V — Transformasi Data
Transformasi variabel numerik dilakukan untuk menghasilkan bentuk data yang lebih sesuai dengan kebutuhan analisis. Transformasi tidak mengubah makna dasar variabel, tetapi membantu menyetarakan skala atau bentuk representasi variabel numerik.
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")]## customer_id usia usia_minmax pendapatan_imputasi pendapatan_minmax
## 1 C001 21 0.00000000 4.5e+06 0.0000000000
## 2 C002 25 0.13793103 4.9e+06 0.0008072654
## 3 C003 23 0.06896552 5.2e+06 0.0014127144
## 4 C004 50 1.00000000 4.8e+06 0.0006054490
## 5 C005 27 0.20689655 4.9e+06 0.0008072654
## 6 C006 NA 0.22413793 5.1e+06 0.0012108981
## 7 C007 31 0.34482759 5.0e+08 1.0000000000
## 8 C008 29 0.27586207 4.7e+06 0.0004036327
## 9 C009 22 0.03448276 4.6e+06 0.0002018163
## 10 C010 35 0.48275862 5.3e+06 0.0016145308
## 11 C011 28 0.24137931 4.9e+06 0.0008072654
Min-Max Scaling digunakan untuk mengubah nilai pendapatan ke dalam rentang skala yang seragam. Transformasi ini bermanfaat ketika beberapa variabel numerik memiliki rentang nilai yang berbeda jauh.
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)## usia_z pendapatan_z
## 1 -0.984 -0.304
## 2 -0.489 -0.301
## 3 -0.737 -0.299
## 4 2.604 -0.302
## 5 -0.242 -0.301
## 6 -0.180 -0.300
## 7 0.253 3.015
## 8 0.006 -0.303
## 9 -0.860 -0.303
## 10 0.748 -0.299
## 11 -0.118 -0.301
Z-Score digunakan untuk menunjukkan posisi suatu nilai terhadap rata-rata dalam satuan simpangan baku. Hasil transformasi ini dapat membantu membandingkan nilai numerik pada skala yang lebih terstandar.
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
transformasi <- pelanggan[, c(
"customer_id", "pendapatan_imputasi", "pendapatan_minmax",
"pendapatan_z", "pendapatan_decimal"
)]
transformasi## customer_id pendapatan_imputasi pendapatan_minmax pendapatan_z
## 1 C001 4.5e+06 0.0000000000 -0.3041235
## 2 C002 4.9e+06 0.0008072654 -0.3014440
## 3 C003 5.2e+06 0.0014127144 -0.2994343
## 4 C004 4.8e+06 0.0006054490 -0.3021138
## 5 C005 4.9e+06 0.0008072654 -0.3014440
## 6 C006 5.1e+06 0.0012108981 -0.3001042
## 7 C007 5.0e+08 1.0000000000 3.0151095
## 8 C008 4.7e+06 0.0004036327 -0.3027837
## 9 C009 4.6e+06 0.0002018163 -0.3034536
## 10 C010 5.3e+06 0.0016145308 -0.2987645
## 11 C011 4.9e+06 0.0008072654 -0.3014440
## pendapatan_decimal
## 1 0.0045
## 2 0.0049
## 3 0.0052
## 4 0.0048
## 5 0.0049
## 6 0.0051
## 7 0.5000
## 8 0.0047
## 9 0.0046
## 10 0.0053
## 11 0.0049
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)Bagian VI — Integrasi Data
Setelah data pelanggan dan data transaksi memiliki identifier yang sama, kedua sumber data digabungkan menggunakan identitas pelanggan sebagai kunci.
Hasil integrasi memberikan satu dataset yang menggabungkan informasi karakteristik pelanggan dengan ringkasan perilaku transaksinya. Dengan demikian, setiap pelanggan dapat dianalisis berdasarkan karakteristik pribadi sekaligus aktivitas belanjanya.
## [1] 0
## [1] 0
## [1] "C011"
## [1] "C012"
data_terintegrasi <- merge(
pelanggan,
transaksi,
by = "customer_id",
all.x = TRUE
)
data_terintegrasi[, c(
"customer_id", "nama", "jumlah_transaksi", "total_purchase"
)]## customer_id nama jumlah_transaksi total_purchase
## 1 C001 Ani 5 1.5e+06
## 2 C002 Budi 3 9.0e+05
## 3 C003 Citra 7 2.7e+06
## 4 C004 Dodi 2 6.0e+05
## 5 C005 Eka 6 2.1e+06
## 6 C006 Fani 4 1.3e+06
## 7 C007 Gilang 20 2.5e+07
## 8 C008 Hana 5 1.7e+06
## 9 C009 Indra 3 8.0e+05
## 10 C010 Joko 8 3.2e+06
## 11 C011 Kiki NA NA
# Apakah jumlah baris berubah secara tidak wajar?
c(sebelum = nrow(pelanggan), sesudah = nrow(data_terintegrasi))## sebelum sesudah
## 11 11
## [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 tanpa pasangan transaksi
data_terintegrasi[is.na(data_terintegrasi$jumlah_transaksi),
c("customer_id", "nama")]## customer_id nama
## 11 C011 Kiki
# Contoh jika telah dikonfirmasi bahwa NA berarti belum pernah bertransaksi
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)
] <- 0Tidak seluruh pelanggan harus memiliki riwayat transaksi. Pelanggan yang tidak memiliki transaksi tetap dipertahankan dalam dataset utama karena keberadaan mereka tetap relevan dalam analisis populasi pelanggan.
Untuk pelanggan tanpa transaksi, variabel jumlah transaksi dan nilai pembelian diisi dengan nilai nol agar kondisi tersebut dapat dibedakan dari missing value yang menunjukkan data tidak tersedia.
Dataset Akhir dan Evaluasi
Pada tahap ini dipilih variabel-variabel yang diperlukan untuk membentuk dataset final. Dataset akhir mencakup informasi identitas pelanggan, karakteristik pelanggan, variabel hasil imputasi dan transformasi, penanda outlier, serta ringkasan aktivitas transaksi.
Dataset ini menjadi hasil utama dari seluruh proses preprocessing dan akan digunakan sebagai dasar untuk analisis perilaku belanja pelanggan.
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## customer_id nama usia kota status pendapatan_imputasi
## 1 C001 Ani 21.0 Pekanbaru Aktif 4.5e+06
## 2 C002 Budi 25.0 Pekanbaru Aktif 4.9e+06
## 3 C003 Citra 23.0 Pekanbaru Aktif 5.2e+06
## 4 C004 Dodi 50.0 Dumai Aktif 4.8e+06
## 5 C005 Eka 27.0 Pekanbaru Tidak Aktif 4.9e+06
## 6 C006 Fani 27.5 Dumai Tidak Aktif 5.1e+06
## 7 C007 Gilang 31.0 Pekanbaru Aktif 5.0e+08
## 8 C008 Hana 29.0 Siak Aktif 4.7e+06
## 9 C009 Indra 22.0 Pekanbaru Aktif 4.6e+06
## 10 C010 Joko 35.0 Dumai Tidak Aktif 5.3e+06
## 11 C011 Kiki 28.0 Tidak diketahui Aktif 4.9e+06
## pendapatan_missing outlier_pendapatan usia_minmax pendapatan_minmax
## 1 0 FALSE 0.00000000 0.0000000000
## 2 1 FALSE 0.13793103 0.0008072654
## 3 0 FALSE 0.06896552 0.0014127144
## 4 0 FALSE 1.00000000 0.0006054490
## 5 0 FALSE 0.20689655 0.0008072654
## 6 0 FALSE 0.22413793 0.0012108981
## 7 0 TRUE 0.34482759 1.0000000000
## 8 0 FALSE 0.27586207 0.0004036327
## 9 0 FALSE 0.03448276 0.0002018163
## 10 0 FALSE 0.48275862 0.0016145308
## 11 1 FALSE 0.24137931 0.0008072654
## jumlah_transaksi_final total_purchase_final
## 1 5 1.5e+06
## 2 3 9.0e+05
## 3 7 2.7e+06
## 4 2 6.0e+05
## 5 6 2.1e+06
## 6 4 1.3e+06
## 7 20 2.5e+07
## 8 5 1.7e+06
## 9 3 8.0e+05
## 10 8 3.2e+06
## 11 0 0.0e+00
## atribut tipe jumlah_missing persen_missing jumlah_unik
## 1 customer_id character 0 0 11
## 2 nama character 0 0 11
## 3 usia numeric 0 0 11
## 4 kota character 0 0 4
## 5 status character 0 0 2
## 6 pendapatan_imputasi numeric 0 0 9
## 7 pendapatan_missing integer 0 0 2
## 8 outlier_pendapatan logical 0 0 2
## 9 usia_minmax numeric 0 0 11
## 10 pendapatan_minmax numeric 0 0 9
## 11 jumlah_transaksi_final numeric 0 0 9
## 12 total_purchase_final numeric 0 0 11
Sebelum dataset digunakan untuk analisis, dilakukan audit akhir untuk memastikan bahwa hasil preprocessing telah memenuhi tujuan yang ditetapkan.
## [1] 0
Pemeriksaan duplikasi dilakukan kembali pada identifier pelanggan untuk memastikan bahwa proses cleaning dan integrasi tidak menghasilkan identitas pelanggan yang tercatat lebih dari satu kali.
## 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
Missing value diperiksa kembali pada seluruh variabel dataset final. Pemeriksaan ini bertujuan memastikan bahwa seluruh nilai yang memang harus ditangani telah diproses sesuai dengan strategi preprocessing yang ditetapkan.
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## indikator sebelum sesudah
## 1 Jumlah baris 12 11
## 2 Duplikasi customer_id 1 0
## 3 Total missing value 4 0
## 4 Kategori kota unik 10 4
## 5 Kategori status unik 8 2
Kondisi dataset sebelum dan sesudah preprocessing dibandingkan menggunakan beberapa indikator, seperti jumlah baris, jumlah kolom, jumlah missing value, dan jumlah duplikasi identifier.
Perbandingan ini digunakan untuk melihat secara langsung perubahan kualitas data setelah seluruh tahapan preprocessing dilakukan.
write.csv(data_final,
"data_pelanggan_setelah_preprocessing.csv",
row.names = FALSE)
write.csv(log_perubahan,
"log_perubahan_preprocessing.csv",
row.names = FALSE)Setelah seluruh proses preprocessing dan audit selesai, dataset final disimpan agar dapat digunakan kembali pada tahap analisis berikutnya.
Selain dataset final, hasil audit juga disimpan sebagai dokumentasi sehingga perubahan dan kondisi akhir data dapat ditelusuri.
Kesimpulan
Berdasarkan seluruh tahapan yang dilakukan, data pelanggan dan transaksi pada perusahaan e-commerce belum dapat langsung digunakan untuk analisis karena masih terdapat berbagai persoalan kualitas data. Permasalahan tersebut mencakup missing value, ketidakkonsistenan kategori, duplikasi identitas pelanggan, nilai yang tidak sesuai dengan aturan domain, nilai ekstrem, serta perbedaan identifier antar sumber data.
Preprocessing dilakukan secara bertahap untuk memperbaiki kualitas data dengan tetap mempertahankan informasi yang masih relevan. Missing value ditangani berdasarkan jenis variabel, kategori diseragamkan, duplikasi identitas diperbaiki, nilai yang tidak valid diperiksa berdasarkan aturan domain, dan nilai ekstrem diberi penanda serta dibandingkan dengan versi winsorized.
Data transaksi kemudian dibersihkan dan diagregasi berdasarkan pelanggan sebelum digabungkan dengan data pelanggan. Hasil akhirnya adalah dataset yang memiliki struktur lebih konsisten dan dapat digunakan sebagai dasar untuk analisis perilaku belanja pelanggan.
Refleksi
Dari proses preprocessing dapat dipahami bahwa kualitas data tidak hanya ditentukan oleh ada atau tidaknya missing value. Data yang lengkap tetap dapat bermasalah apabila memiliki kategori yang tidak konsisten, identitas yang terduplikasi, nilai yang tidak sesuai dengan domain, atau nilai ekstrem yang belum diperiksa.
Dalam konteks e-commerce, konsistensi identitas pelanggan sangat penting karena informasi pelanggan dan transaksi harus dapat dihubungkan dengan benar. Selain itu, nilai ekstrem perlu ditinjau berdasarkan konteks sehingga observasi yang sebenarnya valid tidak dihilangkan hanya karena memiliki nilai yang besar.
Setiap perubahan yang dilakukan terhadap data juga perlu dapat ditelusuri sehingga proses preprocessing dapat dipertanggungjawabkan dan hasil analisis berikutnya memiliki dasar data yang jelas.
Ringkasan
Secara keseluruhan, proses preprocessing pada studi kasus ini dimulai dari pemeriksaan kualitas data pelanggan dan transaksi, kemudian dilanjutkan dengan cleaning, penanganan nilai tidak valid dan missing value, deteksi serta penanganan outlier, transformasi variabel, pengolahan dan agregasi transaksi, penyamaan identifier, integrasi kedua sumber data, audit akhir, hingga pembentukan dataset yang siap digunakan untuk analisis.
Alur tersebut dapat diringkas menjadi:
Data pelanggan dan transaksi → pemeriksaan kualitas → data cleaning → penanganan nilai tidak valid → penanganan missing value → deteksi outlier → transformasi → pengolahan dan agregasi transaksi → penyamaan identifier → integrasi data → audit akhir → dataset siap analisis.
Preprocessing bukan hanya proses menjalankan fungsi pada R, tetapi juga merupakan proses pengambilan keputusan mengenai bagaimana setiap permasalahan kualitas data ditangani berdasarkan karakteristik dan tujuan analisis.
Daftar Pustaka
Han, J., Kamber, M., & Pei, J. (2012). Data Mining: Concepts and Techniques (3rd ed.). Morgan Kaufmann.