Data pelanggan dan data transaksi dapat dimanfaatkan untuk memperoleh gambaran mengenai karakteristik pelanggan serta pola aktivitas pembelian. Namun, sebelum data digunakan untuk analisis, kondisi dan kualitas data perlu diperiksa terlebih dahulu karena data yang tersedia dapat mengandung berbagai permasalahan.
Dalam pengolahan ini digunakan dua dataset, yaitu dataset pelanggan dan dataset transaksi. Dataset pelanggan memuat informasi terkait identitas pelanggan, usia, pendapatan, kota, serta status pelanggan. Sementara itu, dataset transaksi memuat informasi mengenai jumlah transaksi dan total pembelian yang dilakukan.
Dari kedua dataset tersebut ditemukan beberapa kondisi yang perlu diperhatikan, antara lain nilai yang belum tersedia, perbedaan format penulisan kategori, adanya identifier pelanggan yang berulang, nilai numerik yang berada di luar rentang yang semestinya, serta nilai pendapatan yang memiliki jarak sangat jauh dari observasi lainnya. Selain itu, terdapat perbedaan penamaan identifier pada kedua dataset.
Untuk mengatasi kondisi tersebut, dilakukan beberapa tahapan preprocessing agar data menjadi lebih terstruktur dan sesuai untuk analisis lanjutan. Proses yang dilakukan mencakup pemeriksaan data awal, pembersihan data, penanganan missing value, identifikasi outlier, transformasi variabel, penggabungan dataset, hingga pemeriksaan terhadap hasil akhir.
Kasus yang digunakan dalam pengolahan ini merupakan kasus perusahaan e-commerce yang hendak memperoleh informasi lebih lanjut mengenai pelanggan yang dimilikinya. Data yang tersedia berasal dari dua sumber, yaitu data pelanggan dan data transaksi.
Data pelanggan digunakan untuk memberikan informasi mengenai karakteristik setiap pelanggan, sedangkan data transaksi memberikan gambaran mengenai aktivitas pembelian. Kedua dataset tersebut selanjutnya dikaitkan berdasarkan identifier pelanggan.
Preprocessing dalam kasus ini tidak hanya bertujuan untuk menghilangkan data yang bermasalah. Setiap tindakan terhadap data perlu didasarkan pada alasan yang dapat dipertanggungjawabkan sehingga perubahan yang dilakukan tetap dapat ditelusuri. Dengan pendekatan tersebut, dataset yang dihasilkan diharapkan memiliki kualitas dan konsistensi yang lebih baik untuk analisis selanjutnya.
Dataset pelanggan dan transaksi disusun dengan kondisi tertentu yang sengaja digunakan untuk menggambarkan beberapa permasalahan yang umum ditemukan dalam proses pengolahan data. Kondisi tersebut selanjutnya akan ditangani melalui tahapan preprocessing.
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_rawPada kondisi awal, dataset pelanggan memiliki 12 baris dengan 6
variabel. Beberapa nilai belum tersedia pada variabel usia, pendapatan,
dan kota. Selain itu, identifier C010 muncul lebih dari satu kali.
Dataset transaksi sendiri terdiri atas 11 baris dan menggunakan
identifier dengan nama cust_id.
Tahap pemeriksaan awal dilakukan untuk memperoleh informasi mengenai dimensi data, nama variabel, struktur tipe data, contoh observasi, serta ringkasan statistik. Informasi tersebut diperlukan agar karakteristik dataset dapat dipahami sebelum proses perubahan dilakukan.
## [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
## 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
##
##
##
##
Dari pemeriksaan struktur dapat diketahui bahwa dataset pelanggan
memiliki 12 observasi dan 6 variabel. Variabel customer_id,
nama, kota, dan status bertipe
karakter, sedangkan usia dan pendapatan
termasuk variabel numerik.
Selanjutnya dilakukan pengecekan kualitas untuk mengidentifikasi masalah yang terdapat pada dataset. Pemeriksaan diarahkan pada keberadaan missing value, data yang berulang, variasi kategori, dan rentang nilai pada variabel numerik.
## 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
## [1] 1
## [1] 1
## [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
Hasil pengecekan memperlihatkan satu nilai hilang pada usia, dua
nilai hilang pada pendapatan, dan satu nilai hilang pada kota. Selain
itu, terdapat satu customer_id yang muncul kembali, yaitu
C010. Pada variabel kota dan status juga ditemukan beberapa bentuk
penulisan yang berbeda walaupun merujuk pada kategori yang sama.
Pada variabel usia terdapat nilai maksimum 150 tahun. Sementara itu, pendapatan memiliki nilai maksimum 500 juta. Kedua nilai tersebut selanjutnya perlu ditinjau agar dapat ditentukan apakah merupakan kesalahan data atau kondisi yang memang valid.
Agar proses audit dapat dilakukan secara lebih praktis, dibuat sebuah fungsi yang merangkum informasi penting dari setiap variabel, meliputi tipe data, jumlah dan persentase missing value, serta banyaknya nilai unik.
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_awalAudit awal memberikan gambaran mengenai kualitas dataset sebelum dilakukan tindakan preprocessing. Informasi tersebut kemudian digunakan sebagai pertimbangan dalam menentukan langkah perbaikan yang diperlukan.
Dataset asli tidak langsung dimodifikasi. Sebagai gantinya, dibuat salinan kerja sehingga kondisi data sebelum dan sesudah preprocessing masih dapat dibandingkan.
Beberapa nilai pada variabel kota memiliki spasi yang tidak diperlukan, sementara penulisan kategori menggunakan kombinasi huruf besar dan huruf kecil. Jika kondisi ini dibiarkan, satu kategori dapat terbaca sebagai beberapa kategori berbeda.
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"
## [1] "a" "active" "aktif" "nonaktif" "tidak aktif"
Setelah dilakukan penghapusan spasi tambahan dan penyamaan kapitalisasi, variasi penulisan kategori menjadi lebih mudah dikenali dan diseragamkan pada tahap berikutnya.
Nilai pada variabel kota dan status selanjutnya dipetakan ke kategori yang telah ditentukan agar setiap kategori memiliki satu bentuk penulisan.
pelanggan$kota[pelanggan$kota %in%
c("pku", "pekanbaru")] <- "Pekanbaru"
pelanggan$kota[pelanggan$kota == "dumai"] <- "Dumai"
pelanggan$kota[pelanggan$kota == "siak"] <- "Siak"
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"
Setelah standardisasi dilakukan, variabel kota memiliki tiga kategori, yakni Pekanbaru, Dumai, dan Siak. Pada variabel status tersisa dua kategori, yaitu Aktif dan Tidak Aktif.
Identifier pelanggan seharusnya bersifat unik karena satu identifier
merepresentasikan satu pelanggan. Oleh sebab itu, kemunculan
customer_id yang sama perlu diperiksa sebelum data
digunakan lebih lanjut.
pelanggan[
duplicated(pelanggan$customer_id) |
duplicated(pelanggan$customer_id, fromLast = TRUE),
]Pemeriksaan menemukan identifier C010 sebanyak dua kali dengan informasi yang sama. Karena identifier tersebut harus bersifat unik, salah satu baris duplikat kemudian dikeluarkan dari dataset.
pelanggan <- pelanggan[
!duplicated(pelanggan$customer_id),
]
rownames(pelanggan) <- NULL
dim(pelanggan)## [1] 11 6
Setelah duplikasi dihilangkan, dataset pelanggan terdiri atas 11 baris.
Selain melihat struktur dan kelengkapan data, nilai numerik juga perlu dibandingkan dengan aturan domain yang relevan. Untuk variabel usia, digunakan batas usia 15 hingga 100 tahun.
Hasil pemeriksaan menemukan usia 150 tahun pada C004. Nilai tersebut berada di luar rentang yang ditetapkan sehingga dianggap tidak sesuai. Berdasarkan informasi sumber asli pada skenario, nilai tersebut diperbaiki menjadi 50.
Pada variabel pendapatan dilakukan pemeriksaan tambahan untuk memastikan tidak terdapat nilai negatif.
Tidak terdapat observasi dengan pendapatan negatif. Dengan demikian, tidak diperlukan perubahan pada nilai pendapatan berdasarkan aturan tersebut.
Agar seluruh tindakan preprocessing dapat ditelusuri, setiap perubahan penting dicatat dalam sebuah tabel log.
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_perubahanSetelah proses cleaning selesai, pemeriksaan missing value dilakukan kembali. Tujuannya adalah mengetahui nilai yang masih kosong serta menentukan metode penanganan yang sesuai.
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
Nilai yang masih kosong terdapat pada variabel usia, pendapatan, dan kota. Kondisi tersebut kemudian dipertimbangkan dalam menentukan strategi penanganan missing value.
Salah satu pendekatan yang dapat digunakan adalah menghilangkan seluruh observasi yang memiliki nilai kosong. Untuk mengetahui dampaknya, pendekatan tersebut dicoba terlebih dahulu sebagai simulasi.
## [1] 11
## [1] 8
## [1] 27.27
Penghapusan observasi yang tidak lengkap menyebabkan jumlah data berkurang cukup besar. Karena kehilangan observasi cukup berarti, metode penghapusan baris tidak dipilih sebagai solusi utama pada pengolahan ini.
Pada pendapatan terdapat nilai 500 juta yang jauh lebih tinggi dibandingkan sebagian besar observasi. Kondisi tersebut berpotensi menyebabkan rata-rata menjadi kurang representatif, sehingga nilai mean dibandingkan dengan median terlebih dahulu.
mean_pendapatan <- mean(
pelanggan$pendapatan,
na.rm = TRUE
)
median_pendapatan <- median(
pelanggan$pendapatan,
na.rm = TRUE
)
mean_pendapatan## [1] 59900000
## [1] 4900000
Perbedaan antara mean dan median memperlihatkan adanya pengaruh kuat dari nilai ekstrem terhadap rata-rata pendapatan. Oleh karena itu, median dipilih sebagai dasar imputasi untuk nilai pendapatan yang hilang.
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"
)
]Variabel hasil imputasi dibuat terpisah sehingga nilai asli tetap dapat dilihat. Dengan demikian, proses perubahan data dapat dibandingkan dengan kondisi sebelum imputasi.
Untuk nilai kota yang tidak tersedia, pengisian dengan modus tidak langsung digunakan. Hal ini dilakukan agar informasi mengenai ketidakpastian lokasi pelanggan tetap terlihat dalam dataset.
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
Selain mengisi nilai yang kosong, informasi bahwa suatu nilai awalnya missing juga dipertahankan melalui variabel indikator. Cara ini memungkinkan kondisi awal data tetap diketahui setelah imputasi.
pelanggan$pendapatan_missing <-
as.integer(
is.na(pelanggan$pendapatan)
)
table(
pelanggan$pendapatan_missing
)##
## 0 1
## 9 2
Untuk melihat pengaruh imputasi terhadap pola data, distribusi pendapatan sebelum dan sesudah pengisian nilai kosong dibandingkan secara visual.
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
)Pengisian missing value membuat data menjadi lebih lengkap, tetapi perubahan tersebut dapat memengaruhi bentuk distribusi dan tingkat variasi. Karena itu, metode imputasi yang dipilih perlu dicatat sebagai bagian dari proses preprocessing.
Keberadaan nilai ekstrem pada pendapatan diamati terlebih dahulu melalui boxplot agar perbedaan antara nilai umum dan nilai yang jauh dari observasi lainnya dapat terlihat.
boxplot(
pelanggan$pendapatan_imputasi,
horizontal = TRUE,
col = "lightblue",
main = "Boxplot Pendapatan",
xlab = "Pendapatan"
)Dari boxplot terlihat adanya satu observasi dengan pendapatan yang jauh lebih tinggi dibandingkan nilai lainnya.
Untuk menentukan kandidat outlier secara lebih terukur digunakan pendekatan Interquartile Range (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
Hasil perhitungan menghasilkan batas bawah sebesar 4.150.000 dan batas atas sebesar 5.750.000. Observasi yang berada di luar interval tersebut selanjutnya dikategorikan sebagai 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"
)
]Berdasarkan hasil deteksi, C007 dengan pendapatan sebesar 500.000.000 teridentifikasi sebagai kandidat outlier.
Nilai yang terdeteksi sebagai outlier tidak serta-merta dianggap sebagai kesalahan dan dihapus. Nilai 500 juta masih mungkin mencerminkan kondisi pelanggan yang sebenarnya, misalnya pelanggan dengan tingkat pendapatan yang memang lebih tinggi. Karena tidak ditemukan bukti yang menunjukkan bahwa nilai tersebut merupakan kesalahan pencatatan, nilai aslinya tetap dipertahankan.
Sebagai metode pembanding, dibuat pula data hasil winsorizing dengan membatasi nilai ekstrem pada batas atas yang telah dihitung.
pelanggan$pendapatan_winsor <- pmin(
pmax(
pelanggan$pendapatan_imputasi,
batas_bawah
),
batas_atas
)
pelanggan[
pelanggan$outlier_pendapatan,
c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_winsor"
)
]Winsorizing digunakan untuk memberikan gambaran mengenai perubahan data apabila nilai ekstrem dibatasi. Metode tersebut tidak digunakan untuk menggantikan nilai asli secara langsung.
Transformasi dilakukan untuk menyesuaikan skala variabel numerik agar dapat digunakan secara lebih sesuai dalam analisis tertentu. Beberapa metode transformasi dibandingkan untuk melihat karakteristik hasil yang diperoleh.
Normalisasi min–maks mengubah nilai ke dalam skala antara 0 dan 1 dengan menggunakan rumus berikut:
\[ 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"
)
]Hasil normalisasi menghasilkan nilai dalam interval 0 hingga 1. Namun, pada variabel pendapatan, nilai ekstrem menyebabkan sebagian besar observasi memiliki nilai normalisasi yang sangat kecil.
Z-score mengubah data berdasarkan posisi setiap observasi terhadap rata-rata dan simpangan bakunya.
\[ 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
)Decimal scaling merupakan teknik transformasi yang mengurangi skala nilai dengan membaginya menggunakan suatu pangkat sepuluh.
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
Hasil dari ketiga teknik transformasi kemudian disajikan secara bersamaan agar perubahan skala yang dihasilkan masing-masing metode dapat dibandingkan.
transformasi <- pelanggan[
,
c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_minmax",
"pendapatan_z",
"pendapatan_decimal"
)
]
transformasiKetiga metode menghasilkan skala yang berbeda karena masing-masing memiliki mekanisme transformasi yang berbeda. Oleh karena itu, penggunaan metode tertentu sebaiknya disesuaikan dengan kebutuhan dan tujuan analisis yang akan dilakukan.
Pengaruh nilai ekstrem terhadap hasil normalisasi diperiksa dengan membandingkan data pendapatan asli dengan data yang telah melalui proses winsorizing.
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
)Perbandingan tersebut memperlihatkan bahwa keberadaan nilai ekstrem dapat menyebabkan rentang hasil normalisasi menjadi sangat sempit bagi sebagian besar observasi. Hal ini menunjukkan pentingnya mengevaluasi outlier sebelum menentukan teknik transformasi.
Sebelum proses penggabungan, identifier pada kedua dataset diperiksa. Langkah ini bertujuan memastikan kunci tidak mengalami duplikasi serta mengetahui apakah terdapat pelanggan yang hanya muncul pada salah satu sumber data.
## [1] 0
## [1] 0
## [1] "C011"
## [1] "C012"
Pemeriksaan menunjukkan bahwa C011 terdapat pada dataset pelanggan, tetapi tidak ditemukan pada dataset transaksi. Sebaliknya, identifier C012 hanya ditemukan pada data transaksi dan tidak terdapat dalam data pelanggan.
Kedua dataset menggunakan nama kolom identifier yang berbeda. Dataset
pelanggan menggunakan customer_id, sedangkan dataset
transaksi menggunakan cust_id. Agar dapat digunakan sebagai
kunci penggabungan, nama tersebut disamakan.
Penggabungan dilakukan dengan mempertahankan seluruh observasi dari dataset pelanggan. Dengan cara ini, pelanggan yang belum memiliki data transaksi tetap dapat muncul pada dataset hasil penggabungan.
data_terintegrasi <- merge(
pelanggan,
transaksi,
by = "customer_id",
all.x = TRUE
)
data_terintegrasi[
,
c(
"customer_id",
"nama",
"jumlah_transaksi",
"total_purchase"
)
]Setelah kedua sumber data digabungkan, dilakukan validasi untuk memastikan jumlah observasi, keunikan identifier, serta kondisi missing value pada variabel transaksi.
## sebelum sesudah
## 11 11
## [1] 0
## jumlah_transaksi total_purchase
## 1 1
Hasil penggabungan tetap menghasilkan 11 pelanggan. C011 tidak memiliki pasangan pada data transaksi sehingga nilai transaksi untuk pelanggan tersebut menjadi missing.
Nilai NA pada variabel transaksi tidak dapat langsung
dianggap sebagai nol. Nilai tersebut perlu ditafsirkan terlebih dahulu
karena dapat menunjukkan tidak adanya transaksi maupun ketidaktersediaan
informasi.
Dalam skenario ini digunakan asumsi bahwa C011 memang belum melakukan
transaksi. Oleh sebab itu, nilai NA pada variabel transaksi
untuk pelanggan tersebut diubah menjadi nol.
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
)
] <- 0Setelah tahapan preprocessing selesai, variabel yang diperlukan untuk membentuk dataset akhir dipilih dari hasil integrasi.
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_finalDataset akhir merupakan gabungan informasi pelanggan dan transaksi yang telah melalui proses pembersihan. Beberapa variabel tambahan hasil imputasi, indikator missing, deteksi outlier, dan transformasi juga disertakan untuk mendukung analisis berikutnya.
Pemeriksaan terakhir dilakukan untuk memastikan hasil preprocessing telah memenuhi kondisi yang diharapkan, khususnya berkaitan dengan missing value dan duplikasi identifier.
## [1] 0
## 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
Hasil audit akhir menunjukkan bahwa seluruh missing value telah ditangani dan tidak terdapat lagi identifier pelanggan yang duplikat. Dengan demikian, kondisi dataset akhir menjadi lebih teratur dibandingkan kondisi sebelum preprocessing.
Untuk melihat perubahan kualitas secara keseluruhan, kondisi dataset sebelum preprocessing dibandingkan dengan kondisi dataset setelah seluruh tahapan selesai.
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
)
)
)
)
perbandinganDari perbandingan tersebut terlihat bahwa jumlah observasi berubah dari 12 menjadi 11 akibat penghapusan satu data duplikat. Jumlah duplikasi identifier berhasil menjadi nol dan missing value telah ditangani. Selain itu, kategori pada variabel kota dan status menjadi lebih seragam.
Hasil akhir preprocessing beserta catatan perubahan disimpan ke dalam file agar dapat digunakan kembali tanpa perlu mengulangi seluruh proses dari awal.
Berdasarkan rangkaian pemeriksaan yang telah dilakukan, dataset pelanggan dan transaksi pada awalnya masih mengandung beberapa masalah kualitas. Permasalahan tersebut meliputi missing value, perbedaan format kategori, identifier yang berulang, nilai usia yang berada di luar batas wajar, serta nilai pendapatan yang sangat tinggi.
Pada tahap data cleaning, spasi tambahan terlebih dahulu dihilangkan
dan penggunaan huruf besar maupun kecil diseragamkan. Selanjutnya,
kategori kota dan status dipetakan ke bentuk yang konsisten. Variasi
PKU, PEKANBARU, dan pekanbaru
disatukan menjadi Pekanbaru, sedangkan variasi
ACTIVE, A, dan aktif
dikelompokkan menjadi Aktif. Identifier C010 yang muncul
dua kali juga ditangani dengan menghapus salah satu baris yang memiliki
informasi sama.
Pemeriksaan berdasarkan aturan domain menemukan nilai usia 150 tahun pada C004. Karena nilai tersebut berada di luar rentang usia yang telah ditentukan, nilainya diperbaiki menjadi 50 dengan mengacu pada informasi sumber asli. Sementara itu, tidak ditemukan pendapatan negatif. Namun, nilai pendapatan 500 juta pada C007 terlihat jauh berbeda dibandingkan observasi lainnya sehingga perlu dianalisis lebih lanjut.
Untuk missing value numerik, digunakan median sebagai metode
imputasi. Pemilihan tersebut didasarkan pada adanya nilai pendapatan
ekstrem yang dapat memengaruhi nilai mean. Pada variabel kota, nilai
yang tidak tersedia diberi kategori Tidak diketahui
sehingga informasi mengenai ketidakpastian tetap terlihat.
Deteksi outlier menggunakan pendekatan IQR menghasilkan C007 dengan pendapatan 500 juta sebagai kandidat outlier. Meskipun demikian, nilai tersebut tidak langsung dihapus karena belum ada dasar yang cukup untuk menyatakan bahwa data tersebut merupakan kesalahan. Sebagai alternatif, winsorizing dilakukan untuk mengetahui bagaimana pembatasan nilai ekstrem memengaruhi skala data.
Transformasi numerik kemudian dilakukan menggunakan Min-Max, Z-Score, dan Decimal Scaling. Ketiga metode menghasilkan bentuk skala yang berbeda. Khusus pada Min-Max, keberadaan nilai pendapatan ekstrem menyebabkan sebagian besar observasi memiliki nilai yang sangat dekat dengan nol. Hal tersebut memperlihatkan bahwa kondisi outlier perlu dipertimbangkan sebelum menentukan teknik transformasi.
Pada proses integrasi, kedua dataset disatukan berdasarkan
customer_id setelah nama identifier diselaraskan.
Pemeriksaan identifier menunjukkan bahwa C011 hanya terdapat pada data
pelanggan, sedangkan C012 hanya terdapat pada data transaksi. Karena
fokus integrasi adalah mempertahankan seluruh pelanggan, penggabungan
dilakukan menggunakan merge() dengan
all.x = TRUE.
Setelah seluruh tahapan preprocessing diterapkan, dataset akhir tidak
lagi memiliki missing value dan duplikasi customer_id.
Kategori kota dan status juga telah memiliki bentuk penulisan yang lebih
konsisten. Dengan demikian, hasil pengolahan memberikan dataset yang
lebih siap untuk digunakan pada proses analisis selanjutnya.
Dataset pelanggan dan transaksi pada kondisi awal masih memiliki sejumlah masalah kualitas data, seperti nilai yang hilang, ketidakteraturan penulisan kategori, duplikasi identifier, nilai usia yang berada di luar aturan domain, serta nilai pendapatan yang sangat ekstrem.
Perbaikan dilakukan secara bertahap melalui pemeriksaan kondisi awal,
data cleaning, penanganan missing value, identifikasi outlier,
transformasi variabel, dan integrasi data. Missing value numerik
ditangani menggunakan median, sedangkan nilai kota yang kosong diberi
kategori Tidak diketahui. Duplikasi C010 dihilangkan dan
nilai usia C004 diperbaiki dari 150 menjadi 50 sesuai informasi
sumber.
Berdasarkan metode IQR, pendapatan C007 sebesar 500 juta teridentifikasi sebagai kandidat outlier. Nilai tersebut tetap dipertahankan karena tidak ditemukan bukti bahwa data merupakan kesalahan pencatatan. Sebagai bahan evaluasi, dibuat pula versi winsorized. Selanjutnya, variabel numerik ditransformasikan menggunakan Min-Max, Z-Score, dan Decimal Scaling untuk melihat perbedaan skala yang dihasilkan.
Pada tahap integrasi, data pelanggan dan transaksi berhasil
digabungkan menggunakan customer_id. Dataset akhir memiliki
struktur yang lebih konsisten, seluruh missing value telah ditangani,
dan tidak terdapat duplikasi identifier. Oleh karena itu, dataset hasil
preprocessing dapat digunakan sebagai dasar untuk analisis pelanggan dan
transaksi pada tahap berikutnya.
Tahapan preprocessing pada data ini dimulai dari pemeriksaan kondisi awal, dilanjutkan dengan pembersihan data, penanganan missing value, pemeriksaan outlier, transformasi variabel numerik, penggabungan data, dan evaluasi dataset akhir.
Hasil pengolahan menunjukkan bahwa preprocessing tidak selalu berarti menghapus seluruh nilai yang dianggap tidak biasa. Setiap perubahan perlu disesuaikan dengan karakteristik data dan tujuan analisis. Melalui pendekatan tersebut, proses cleaning, imputasi, evaluasi outlier, transformasi, serta integrasi dapat dilakukan dengan tetap mempertahankan informasi penting dari data awal.
Batini, C., & Scannapieco, M. (2016). Data and Information Quality: Dimensions, Principles and Techniques. Springer.
Kuhn, M., & Johnson, K. (2013). Applied Predictive Modeling. Springer.
Wickham, H., & Grolemund, G. (2017). R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. O’Reilly Media.