Data mining tidak hanya membutuhkan metode analisis yang tepat, tetapi juga membutuhkan data yang sudah diperiksa dan dipersiapkan dengan baik. Data yang diperoleh dari suatu sumber biasanya belum langsung dapat digunakan karena masih dapat ditemukan berbagai masalah, seperti data kosong, data yang terduplikasi, penulisan kategori yang tidak konsisten, serta nilai yang terlalu besar atau terlalu kecil dibandingkan data lainnya.
Pada tugas ini digunakan dua dataset sederhana, yaitu dataset pelanggan dan dataset transaksi. Dataset pelanggan berisi informasi mengenai identitas pelanggan, usia, pendapatan, kota tempat tinggal, dan status pelanggan. Sementara itu, dataset transaksi berisi jumlah transaksi dan total pembelian dari pelanggan.
Data tersebut sengaja dibuat memiliki beberapa masalah agar proses
preprocessing dapat dilakukan secara langsung. Beberapa masalah yang
terdapat pada data antara lain missing value, duplikasi
customer_id, perbedaan penulisan kategori, nilai usia yang
tidak wajar, serta nilai pendapatan yang cukup jauh dibandingkan nilai
lainnya.
Tahapan yang dilakukan meliputi pemeriksaan kondisi awal data, data cleaning, penanganan duplikasi, pemeriksaan nilai tidak wajar, penanganan missing value, pemeriksaan dan penanganan outlier, transformasi data, integrasi data, serta pemeriksaan dataset akhir. Setiap tahap dilakukan secara bertahap agar kondisi data sebelum dan sesudah preprocessing dapat dibandingkan.
Tujuan dari preprocessing ini adalah menghasilkan dataset yang lebih rapi, konsisten, dan siap digunakan untuk proses analisis data mining selanjutnya.
Dataset dibuat secara langsung menggunakan fungsi
data.frame(). Data dibuat dengan beberapa kondisi yang umum
ditemukan dalam proses preprocessing, sehingga setiap tahapan dapat
diterapkan pada data yang sama.
Dataset pelanggan berisi informasi mengenai identitas pelanggan, nama, usia, pendapatan, kota tempat tinggal, dan status pelanggan.
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
)Dataset kedua adalah dataset transaksi. Dataset ini berisi jumlah transaksi dan total pembelian yang dilakukan oleh setiap pelanggan.
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
)Dataset transaksi nantinya akan digabungkan dengan dataset pelanggan. Identifier yang digunakan pada dataset transaksi adalah cust_id, sedangkan dataset pelanggan menggunakan customer_id. Perbedaan nama tersebut akan diperbaiki sebelum proses integrasi.
Dataset pelanggan ditampilkan untuk melihat kondisi awal data.
## 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
Dataset transaksi juga ditampilkan.
## 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
Sebelum melakukan perubahan, kondisi awal data perlu dilihat terlebih dahulu. Hal ini dilakukan untuk mengetahui ukuran dataset, nama variabel, tipe data, dan gambaran umum dari nilai yang terdapat di dalam data.
## [1] 12 6
## [1] "customer_id" "nama" "usia" "pendapatan" "kota"
## [6] "status"
Fungsi dim() digunakan untuk mengetahui jumlah baris dan kolom. Sementara itu, names() digunakan untuk melihat nama variabel yang terdapat pada dataset.
## '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" ...
Fungsi str() digunakan untuk melihat tipe data setiap variabel. Dari hasil tersebut dapat diketahui variabel mana yang berupa numerik dan mana yang berupa karakter.
## 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
##
##
##
##
Fungsi summary() digunakan untuk melihat ringkasan data. Pada variabel numerik dapat dilihat nilai minimum, kuartil, median, mean, dan maksimum. Ringkasan ini membantu melihat apakah terdapat nilai yang terlihat tidak wajar.
Setelah struktur data diketahui, langkah berikutnya adalah memeriksa masalah yang terdapat pada dataset. Pemeriksaan dilakukan terhadap missing value, duplikasi, kategori, serta rentang nilai numerik.
Jumlah missing value pada setiap variabel diperiksa menggunakan is.na().
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
Persentase missing value juga dihitung agar dapat diketahui seberapa besar proporsi data yang kosong.
## customer_id nama usia pendapatan kota status
## 0.00 0.00 8.33 16.67 8.33 0.00
Dari pemeriksaan tersebut dapat diketahui bahwa terdapat missing value pada variabel usia, pendapatan, dan kota.
Pemeriksaan pertama dilakukan terhadap duplikasi baris secara keseluruhan.
## [1] 1
Selanjutnya diperiksa apakah terdapat customer_id yang berulang.
## [1] 1
Pemeriksaan berdasarkan customer_id diperlukan karena variabel tersebut digunakan sebagai identitas pelanggan. Satu pelanggan seharusnya tidak memiliki lebih dari satu data pada dataset utama.
Kategori pada variabel kota diperiksa menggunakan unique().
## [1] " PKU" "Dumai" "DUMAI" "pekanbaru" "Pekanbaru"
## [6] "PEKANBARU" "Pekanbaru " "PKU" "Siak"
Kategori pada variabel status juga diperiksa.
## [1] "A" "ACTIVE" "aktif" "Aktif" "AKTIF"
## [6] "nonaktif" "Tidak aktif" "Tidak Aktif"
Dari hasil tersebut terlihat bahwa terdapat beberapa penulisan yang berbeda. Misalnya Pekanbaru, PEKANBARU, dan PKU sebenarnya digunakan untuk menunjukkan kota yang sama. Hal yang sama juga terjadi pada variabel status.
Rentang usia diperiksa terlebih dahulu.
## [1] 21 150
Rentang pendapatan juga diperiksa.
## [1] 4.5e+06 5.0e+08
Pemeriksaan ini dilakukan untuk mengetahui nilai minimum dan maksimum. Dari sini dapat terlihat bahwa terdapat nilai yang cukup jauh dari nilai lainnya dan perlu diperiksa lebih lanjut.
Agar pemeriksaan kualitas data dapat dilakukan dengan lebih praktis, dibuat fungsi audit_data(). Fungsi ini memberikan informasi mengenai tipe data, jumlah missing value, persentase missing value, dan jumlah 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
)
}Fungsi tersebut diterapkan pada dataset 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
Audit ini digunakan sebagai gambaran kondisi data sebelum dilakukan perbaikan. Hasilnya nantinya dapat dibandingkan dengan audit setelah seluruh proses preprocessing selesai.
Setelah masalah pada data diketahui, tahap berikutnya adalah melakukan cleaning. Pada tahap ini dilakukan perbaikan terhadap penulisan kategori, duplikasi, dan nilai yang tidak wajar.
Data asli tetap dipertahankan dengan membuat salinan baru.
Beberapa nilai kota memiliki spasi tambahan. Spasi tersebut dapat membuat kategori yang sebenarnya sama dianggap berbeda.
Kategori kota diperiksa kembali.
## [1] "Dumai" "DUMAI" "pekanbaru" "Pekanbaru" "PEKANBARU" "PKU"
## [7] "Siak"
Perbedaan huruf besar dan kecil juga diperbaiki agar penulisan kota menjadi lebih seragam.
Kategori kota diperiksa kembali.
## [1] "dumai" "pekanbaru" "pku" "siak"
Beberapa nama kota memiliki bentuk yang berbeda tetapi memiliki arti yang sama. PKU dan Pekanbaru diseragamkan menjadi pekanbaru.
Kategori kota setelah standardisasi diperiksa kembali.
## [1] "dumai" "pekanbaru" "siak"
Setelah langkah ini, kategori kota menjadi lebih konsisten. Kota Dumai tetap ditulis sebagai dumai, sedangkan Pekanbaru ditulis sebagai pekanbaru.
Variabel status juga memiliki beberapa bentuk penulisan. Pertama, seluruh nilai diubah menjadi huruf kecil dan spasi tambahan dihapus.
Selanjutnya kategori status diseragamkan.
Kategori status diperiksa kembali.
## [1] "aktif" "tidak aktif"
Dengan demikian, status pelanggan hanya menggunakan dua bentuk kategori, yaitu aktif dan tidak aktif.
Setelah data kategorik diperbaiki, pemeriksaan duplikasi dilakukan kembali. Duplikasi diperiksa berdasarkan customer_id karena variabel tersebut menjadi identifier utama pelanggan.
## customer_id nama usia pendapatan kota status
## 11 C010 Joko 35 5300000 dumai tidak aktif
Dari hasil pemeriksaan terlihat bahwa C010 muncul lebih dari satu kali.
Duplikasi dihapus dengan mempertahankan data yang muncul pertama kali.
Jumlah baris setelah penghapusan diperiksa.
## [1] 11
Kemudian diperiksa kembali apakah masih terdapat customer_id yang berulang.
## [1] 0
Jika hasilnya 0, berarti tidak terdapat lagi duplikasi berdasarkan customer_id.
Selain data kosong dan duplikasi, terdapat nilai yang tidak sesuai dengan kondisi umum. Contohnya adalah usia 150 tahun. Nilai tersebut perlu diperiksa sebelum digunakan dalam analisis.
## customer_id nama usia pendapatan kota status
## 4 C004 Dodi 150 4800000 dumai aktif
## NA <NA> <NA> NA NA <NA> <NA>
Usia 150 tahun dianggap tidak wajar untuk data pelanggan. Nilai tersebut tidak langsung diganti dengan angka tertentu karena tidak diketahui nilai usia sebenarnya.
Nilai usia yang tidak wajar diubah menjadi NA.
Kemudian kondisi usia diperiksa kembali.
## [1] 21 25 23 NA 27 NA 31 29 22 35 28
Setelah menjadi NA, nilai tersebut dapat ditangani bersama dengan missing value lainnya pada tahap imputasi.
Agar perubahan yang dilakukan dapat diketahui, dibuat log sederhana. Log ini berisi tahapan dan keterangan perubahan yang dilakukan pada dataset.
log_perubahan <- data.frame(
tahap = c(
"Standardisasi kota",
"Standardisasi status",
"Penghapusan duplikasi",
"Koreksi usia"
),
keterangan = c(
"Menyamakan penulisan kategori kota",
"Menyamakan penulisan kategori status",
"Menghapus customer_id yang duplikat",
"Mengubah usia tidak wajar menjadi NA"
),
stringsAsFactors = FALSE
)
log_perubahan## tahap keterangan
## 1 Standardisasi kota Menyamakan penulisan kategori kota
## 2 Standardisasi status Menyamakan penulisan kategori status
## 3 Penghapusan duplikasi Menghapus customer_id yang duplikat
## 4 Koreksi usia Mengubah usia tidak wajar menjadi NA
Log tersebut membantu melihat kembali perubahan yang sudah dilakukan selama proses cleaning.
Setelah cleaning dilakukan, masih terdapat beberapa nilai yang kosong. Missing value perlu ditangani karena dapat mengganggu proses analisis apabila dibiarkan begitu saja.
Metode pengisian disesuaikan dengan jenis variabel. Untuk data numerik digunakan median, sedangkan untuk data kategorik digunakan modus.
Missing value pada usia diperiksa terlebih dahulu.
## customer_id nama usia pendapatan kota status
## 4 C004 Dodi NA 4800000 dumai aktif
## 6 C006 Fani NA 5100000 dumai tidak aktif
Karena usia merupakan variabel numerik, median digunakan sebagai nilai pengganti. Median dipilih karena tidak terlalu dipengaruhi oleh nilai ekstrem.
## [1] 27
Variabel baru dibuat untuk menyimpan hasil imputasi.
pelanggan$usia_imputasi <- pelanggan$usia
pelanggan$usia_imputasi[
is.na(
pelanggan$usia_imputasi
)
] <- median_usiaHasil sebelum dan sesudah imputasi dapat dibandingkan.
## customer_id usia usia_imputasi
## 1 C001 21 21
## 2 C002 25 25
## 3 C003 23 23
## 4 C004 NA 27
## 5 C005 27 27
## 6 C006 NA 27
## 7 C007 31 31
## 8 C008 29 29
## 9 C009 22 22
## 10 C010 35 35
## 12 C011 28 28
Missing value pada pendapatan diperiksa.
## customer_id nama usia pendapatan kota status usia_imputasi
## 2 C002 Budi 25 NA pekanbaru aktif 25
## 12 C011 Kiki 28 NA <NA> aktif 28
Karena pendapatan merupakan data numerik, median digunakan sebagai nilai pengganti.
## [1] 4900000
Hasil imputasi disimpan dalam variabel baru.
pelanggan$pendapatan_imputasi <-
pelanggan$pendapatan
pelanggan$pendapatan_imputasi[
is.na(
pelanggan$pendapatan_imputasi
)
] <- median_pendapatanHasilnya diperiksa.
## customer_id pendapatan pendapatan_imputasi
## 1 C001 4.5e+06 4.5e+06
## 2 C002 NA 4.9e+06
## 3 C003 5.2e+06 5.2e+06
## 4 C004 4.8e+06 4.8e+06
## 5 C005 4.9e+06 4.9e+06
## 6 C006 5.1e+06 5.1e+06
## 7 C007 5.0e+08 5.0e+08
## 8 C008 4.7e+06 4.7e+06
## 9 C009 4.6e+06 4.6e+06
## 10 C010 5.3e+06 5.3e+06
## 12 C011 NA 4.9e+06
Missing value pada kota diperiksa.
## customer_id nama usia pendapatan kota status usia_imputasi
## 12 C011 Kiki 28 NA <NA> aktif 28
## pendapatan_imputasi
## 12 4900000
Karena kota merupakan data kategorik, nilai yang kosong diisi menggunakan modus atau kategori yang paling sering muncul.
## [1] "pekanbaru"
Hasil imputasi disimpan dalam variabel baru.
pelanggan$kota_imputasi <-
pelanggan$kota
pelanggan$kota_imputasi[
is.na(
pelanggan$kota_imputasi
)
] <- modus_kotaHasilnya diperiksa kembali.
## customer_id kota kota_imputasi
## 1 C001 pekanbaru pekanbaru
## 2 C002 pekanbaru pekanbaru
## 3 C003 pekanbaru pekanbaru
## 4 C004 dumai dumai
## 5 C005 pekanbaru pekanbaru
## 6 C006 dumai dumai
## 7 C007 pekanbaru pekanbaru
## 8 C008 siak siak
## 9 C009 pekanbaru pekanbaru
## 10 C010 dumai dumai
## 12 C011 <NA> pekanbaru
Selain melakukan imputasi, dibuat variabel yang menunjukkan apakah pendapatan pada awalnya merupakan missing value.
Jumlah data yang sebelumnya memiliki missing value dapat dilihat dengan:
##
## FALSE TRUE
## 9 2
Penanda ini berguna agar informasi mengenai kondisi awal data tetap tersimpan.
Setelah seluruh proses imputasi selesai, jumlah missing value diperiksa kembali.
## customer_id nama usia pendapatan
## 0 0 2 2
## kota status usia_imputasi pendapatan_imputasi
## 1 0 0 0
## kota_imputasi pendapatan_missing
## 0 0
Pemeriksaan ini dilakukan untuk memastikan variabel yang menjadi target imputasi sudah tidak memiliki nilai kosong.
Setelah missing value ditangani, tahap berikutnya adalah pemeriksaan outlier. Outlier merupakan nilai yang jauh dari sebagian besar pengamatan.
Pada tugas ini pemeriksaan dilakukan pada variabel usia dan pendapatan. Pemeriksaan menggunakan boxplot dan metode IQR.
boxplot(
pelanggan$usia_imputasi,
horizontal = TRUE,
col = "skyblue",
main = "Boxplot Usia",
xlab = "Usia"
)Boxplot digunakan untuk melihat penyebaran data dan mengetahui apakah terdapat nilai yang berada jauh dari data lainnya.
Kuartil pertama, kuartil ketiga, dan IQR dihitung terlebih dahulu.
Q1_usia <- quantile(
pelanggan$usia_imputasi,
0.25,
na.rm = TRUE
)
Q3_usia <- quantile(
pelanggan$usia_imputasi,
0.75,
na.rm = TRUE
)
IQR_usia <- Q3_usia - Q1_usia
Q1_usia## 25%
## 24
## 75%
## 28.5
## 75%
## 4.5
Batas bawah dan batas atas ditentukan dengan rumus:
\[ \text{Batas Bawah} = Q_1 - 1.5 \times IQR \]
\[ \text{Batas Atas} = Q_3 + 1.5 \times IQR \]
batas_bawah_usia <-
Q1_usia - 1.5 * IQR_usia
batas_atas_usia <-
Q3_usia + 1.5 * IQR_usia
batas_bawah_usia## 25%
## 17.25
## 75%
## 35.25
pelanggan$outlier_usia <-
pelanggan$usia_imputasi < batas_bawah_usia |
pelanggan$usia_imputasi > batas_atas_usiaObservasi yang terdeteksi sebagai outlier ditampilkan.
## [1] customer_id nama usia_imputasi
## <0 rows> (or 0-length row.names)
Hasil tersebut digunakan untuk melihat apakah nilai yang terdeteksi memang perlu mendapatkan perhatian lebih lanjut.
Pendapatan juga diperiksa karena memiliki nilai yang cukup jauh dibandingkan sebagian besar data.
boxplot(
pelanggan$pendapatan_imputasi,
horizontal = TRUE,
col = "lightblue",
main = "Boxplot Pendapatan",
xlab = "Pendapatan"
)Boxplot membantu melihat apakah terdapat nilai pendapatan yang berada jauh dari pola umum data.
Q1_pendapatan <- quantile(
pelanggan$pendapatan_imputasi,
0.25,
na.rm = TRUE
)
Q3_pendapatan <- quantile(
pelanggan$pendapatan_imputasi,
0.75,
na.rm = TRUE
)
IQR_pendapatan <-
Q3_pendapatan - Q1_pendapatan
Q1_pendapatan## 25%
## 4750000
## 75%
## 5150000
## 75%
## 4e+05
Batas bawah dan batas atas dihitung.
batas_bawah_pendapatan <-
Q1_pendapatan -
1.5 * IQR_pendapatan
batas_atas_pendapatan <-
Q3_pendapatan +
1.5 * IQR_pendapatan
batas_bawah_pendapatan## 25%
## 4150000
## 75%
## 5750000
pelanggan$outlier_pendapatan <-
pelanggan$pendapatan_imputasi <
batas_bawah_pendapatan |
pelanggan$pendapatan_imputasi >
batas_atas_pendapatanData yang terdeteksi sebagai outlier ditampilkan.
## customer_id nama pendapatan_imputasi
## 7 C007 Gilang 5e+08
Nilai yang terdeteksi sebagai outlier tidak langsung dihapus. Nilai tersebut diperiksa terlebih dahulu karena outlier belum tentu merupakan kesalahan.
pelanggan[
order(
pelanggan$pendapatan_imputasi,
decreasing = TRUE
),
c(
"customer_id",
"nama",
"pendapatan_imputasi"
)
]## customer_id nama pendapatan_imputasi
## 7 C007 Gilang 5.0e+08
## 10 C010 Joko 5.3e+06
## 3 C003 Citra 5.2e+06
## 6 C006 Fani 5.1e+06
## 2 C002 Budi 4.9e+06
## 5 C005 Eka 4.9e+06
## 12 C011 Kiki 4.9e+06
## 4 C004 Dodi 4.8e+06
## 8 C008 Hana 4.7e+06
## 9 C009 Indra 4.6e+06
## 1 C001 Ani 4.5e+06
Pemeriksaan ini membantu melihat nilai ekstrem secara lebih jelas dan membandingkannya dengan pendapatan pelanggan lainnya.
Outlier pada pendapatan tidak langsung dihapus karena masih mungkin merupakan nilai yang benar. Sebagai alternatif, digunakan winsorizing untuk membatasi nilai ekstrem tanpa menghapus observasi.
pelanggan$pendapatan_winsor <-
pmin(
pmax(
pelanggan$pendapatan_imputasi,
batas_bawah_pendapatan
),
batas_atas_pendapatan
)Nilai sebelum dan sesudah winsorizing dibandingkan.
pelanggan[
pelanggan$outlier_pendapatan,
c(
"customer_id",
"nama",
"pendapatan_imputasi",
"pendapatan_winsor"
)
]## customer_id nama pendapatan_imputasi pendapatan_winsor
## 7 C007 Gilang 5e+08 5750000
Dengan cara ini, nilai ekstrem dibatasi pada batas yang sudah ditentukan tanpa menghapus baris pelanggan.
Perubahan sebelum dan sesudah winsorizing dapat dilihat menggunakan boxplot.
par(
mfrow = c(1, 2)
)
boxplot(
pelanggan$pendapatan_imputasi,
horizontal = TRUE,
col = "skyblue",
main = "Sebelum Winsorizing",
xlab = "Pendapatan"
)
boxplot(
pelanggan$pendapatan_winsor,
horizontal = TRUE,
col = "lightblue",
main = "Sesudah Winsorizing",
xlab = "Pendapatan"
)Dari perbandingan tersebut dapat dilihat perubahan penyebaran data setelah nilai ekstrem dibatasi. Nilai pendapatan sebelum winsorizing tetap disimpan sehingga hasil sebelum dan sesudah perubahan masih dapat dibandingkan.
Setelah proses cleaning, imputasi, dan pemeriksaan outlier dilakukan, selanjutnya data numerik dapat ditransformasikan.
Transformasi digunakan untuk mengubah skala data. Hal ini berguna karena variabel usia dan pendapatan memiliki rentang nilai yang berbeda cukup jauh. Pada tugas ini digunakan tiga metode, yaitu Min-Max, Z-Score, dan Decimal Scaling.
Normalisasi Min-Max digunakan untuk mengubah nilai data ke dalam rentang 0 sampai 1.
Rumus Min-Max:
\[ x' = \frac{x - x_{\min}}{x_{\max} - x_{\min}} \]
Keterangan:
Fungsi Min-Max dibuat sebagai berikut.
minmax <- function(x) {
(
x - min(
x,
na.rm = TRUE
)
) /
(
max(
x,
na.rm = TRUE
) -
min(
x,
na.rm = TRUE
)
)
}Fungsi diterapkan pada usia dan pendapatan.
pelanggan$usia_minmax <-
minmax(
pelanggan$usia_imputasi
)
pelanggan$pendapatan_minmax <-
minmax(
pelanggan$pendapatan_imputasi
)Hasilnya ditampilkan.
pelanggan[
,
c(
"customer_id",
"usia_imputasi",
"usia_minmax",
"pendapatan_imputasi",
"pendapatan_minmax"
)
]## customer_id usia_imputasi usia_minmax pendapatan_imputasi pendapatan_minmax
## 1 C001 21 0.00000000 4.5e+06 0.0000000000
## 2 C002 25 0.28571429 4.9e+06 0.0008072654
## 3 C003 23 0.14285714 5.2e+06 0.0014127144
## 4 C004 27 0.42857143 4.8e+06 0.0006054490
## 5 C005 27 0.42857143 4.9e+06 0.0008072654
## 6 C006 27 0.42857143 5.1e+06 0.0012108981
## 7 C007 31 0.71428571 5.0e+08 1.0000000000
## 8 C008 29 0.57142857 4.7e+06 0.0004036327
## 9 C009 22 0.07142857 4.6e+06 0.0002018163
## 10 C010 35 1.00000000 5.3e+06 0.0016145308
## 12 C011 28 0.50000000 4.9e+06 0.0008072654
Nilai hasil Min-Max berada pada rentang 0 sampai 1.
Normalisasi Z-Score digunakan untuk mengubah data berdasarkan rata-rata dan simpangan baku.
Rumus Z-Score:
\[ z = \frac{x - \bar{x}}{s} \]
Keterangan:
Transformasi dilakukan menggunakan fungsi scale().
pelanggan$usia_z <-
as.numeric(
scale(
pelanggan$usia_imputasi
)
)
pelanggan$pendapatan_z <-
as.numeric(
scale(
pelanggan$pendapatan_imputasi
)
)Hasil transformasi ditampilkan.
## customer_id usia_z pendapatan_z
## 1 C001 -1.42958323 -0.3041235
## 2 C002 -0.44674476 -0.3014440
## 3 C003 -0.93816399 -0.2994343
## 4 C004 0.04467448 -0.3021138
## 5 C005 0.04467448 -0.3014440
## 6 C006 0.04467448 -0.3001042
## 7 C007 1.02751295 3.0151095
## 8 C008 0.53609371 -0.3027837
## 9 C009 -1.18387361 -0.3034536
## 10 C010 2.01035142 -0.2987645
## 12 C011 0.29038409 -0.3014440
Nilai Z-Score yang mendekati nol menunjukkan nilai yang dekat dengan rata-rata. Nilai positif menunjukkan nilai di atas rata-rata, sedangkan nilai negatif menunjukkan nilai di bawah rata-rata.
Decimal Scaling dilakukan dengan membagi data menggunakan pangkat sepuluh tertentu. Metode ini digunakan untuk memperkecil skala angka.
decimal_scale <- function(x) {
maks <- max(
abs(x),
na.rm = TRUE
)
if (maks == 0) {
return(x)
}
j <- ceiling(
log10(
maks + 1
)
)
x / (
10 ^ j
)
}Fungsi tersebut diterapkan pada pendapatan.
Rentang hasil transformasi diperiksa.
## [1] 0.0045 0.5000
Hasil ketiga metode dibandingkan agar perbedaannya dapat dilihat.
pelanggan[
,
c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_minmax",
"pendapatan_z",
"pendapatan_decimal"
)
]## 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
## 12 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
## 12 0.0049
Min-Max menghasilkan nilai antara 0 dan 1, Z-Score menghasilkan nilai yang berpusat pada rata-rata, sedangkan Decimal Scaling mengecilkan nilai dengan membaginya menggunakan pangkat sepuluh.
Setelah dataset pelanggan selesai diproses, data tersebut digabungkan dengan dataset transaksi.
Tujuan integrasi adalah menggabungkan informasi pelanggan dengan informasi transaksi sehingga kedua informasi dapat digunakan dalam satu dataset.
Identifier pada dataset pelanggan diperiksa.
## [1] "C001" "C002" "C003" "C004" "C005" "C006" "C007" "C008" "C009" "C010"
## [11] "C011"
Identifier pada dataset transaksi juga diperiksa.
## [1] "C001" "C002" "C003" "C004" "C005" "C006" "C007" "C008" "C009" "C010"
## [11] "C012"
Dari hasil tersebut terlihat bahwa terdapat beberapa ID yang hanya muncul pada salah satu dataset.
ID yang terdapat pada pelanggan tetapi tidak terdapat pada transaksi dicari menggunakan setdiff().
## [1] "C011"
Sebaliknya, ID yang terdapat pada transaksi tetapi tidak terdapat pada pelanggan juga diperiksa.
## [1] "C012"
Pemeriksaan ini dilakukan sebelum merge agar perbedaan data dapat diketahui.
Nama cust_id pada dataset transaksi diubah menjadi customer_id.
Nama variabel diperiksa kembali.
## [1] "customer_id" "jumlah_transaksi" "total_purchase"
Sekarang kedua dataset memiliki identifier dengan nama yang sama.
Penggabungan dilakukan menggunakan merge() dengan all.x = TRUE. Pengaturan ini digunakan agar seluruh pelanggan pada dataset utama tetap dipertahankan.
Hasil integrasi dilihat.
## customer_id nama usia pendapatan kota status usia_imputasi
## 1 C001 Ani 21 4500000 pekanbaru aktif 21
## 2 C002 Budi 25 NA pekanbaru aktif 25
## 3 C003 Citra 23 5200000 pekanbaru aktif 23
## 4 C004 Dodi NA 4800000 dumai aktif 27
## 5 C005 Eka 27 4900000 pekanbaru tidak aktif 27
## 6 C006 Fani NA 5100000 dumai tidak aktif 27
## pendapatan_imputasi kota_imputasi pendapatan_missing outlier_usia
## 1 4500000 pekanbaru FALSE FALSE
## 2 4900000 pekanbaru TRUE FALSE
## 3 5200000 pekanbaru FALSE FALSE
## 4 4800000 dumai FALSE FALSE
## 5 4900000 pekanbaru FALSE FALSE
## 6 5100000 dumai FALSE FALSE
## outlier_pendapatan pendapatan_winsor usia_minmax pendapatan_minmax
## 1 FALSE 4500000 0.0000000 0.0000000000
## 2 FALSE 4900000 0.2857143 0.0008072654
## 3 FALSE 5200000 0.1428571 0.0014127144
## 4 FALSE 4800000 0.4285714 0.0006054490
## 5 FALSE 4900000 0.4285714 0.0008072654
## 6 FALSE 5100000 0.4285714 0.0012108981
## usia_z pendapatan_z pendapatan_decimal jumlah_transaksi total_purchase
## 1 -1.42958323 -0.3041235 0.0045 5 1500000
## 2 -0.44674476 -0.3014440 0.0049 3 900000
## 3 -0.93816399 -0.2994343 0.0052 7 2700000
## 4 0.04467448 -0.3021138 0.0048 2 600000
## 5 0.04467448 -0.3014440 0.0049 6 2100000
## 6 0.04467448 -0.3001042 0.0051 4 1300000
Struktur data juga diperiksa.
## 'data.frame': 11 obs. of 20 variables:
## $ customer_id : chr "C001" "C002" "C003" "C004" ...
## $ nama : chr "Ani" "Budi" "Citra" "Dodi" ...
## $ usia : num 21 25 23 NA 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" "pekanbaru" "pekanbaru" "dumai" ...
## $ status : chr "aktif" "aktif" "aktif" "aktif" ...
## $ usia_imputasi : num 21 25 23 27 27 27 31 29 22 35 ...
## $ pendapatan_imputasi: num 4.5e+06 4.9e+06 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_imputasi : chr "pekanbaru" "pekanbaru" "pekanbaru" "dumai" ...
## $ pendapatan_missing : logi FALSE TRUE FALSE FALSE FALSE FALSE ...
## $ outlier_usia : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ outlier_pendapatan : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ pendapatan_winsor : num 4500000 4900000 5200000 4800000 4900000 5100000 5750000 4700000 4600000 5300000 ...
## $ usia_minmax : num 0 0.286 0.143 0.429 0.429 ...
## $ pendapatan_minmax : num 0 0.000807 0.001413 0.000605 0.000807 ...
## $ usia_z : num -1.4296 -0.4467 -0.9382 0.0447 0.0447 ...
## $ pendapatan_z : num -0.304 -0.301 -0.299 -0.302 -0.301 ...
## $ pendapatan_decimal : num 0.0045 0.0049 0.0052 0.0048 0.0049 0.0051 0.5 0.0047 0.0046 0.0053 ...
## $ jumlah_transaksi : num 5 3 7 2 6 4 20 5 3 8 ...
## $ total_purchase : num 1.5e+06 9.0e+05 2.7e+06 6.0e+05 2.1e+06 1.3e+06 2.5e+07 1.7e+06 8.0e+05 3.2e+06 ...
Jumlah baris sebelum dan sesudah integrasi dibandingkan.
## [1] 11
## [1] 11
Kemudian diperiksa apakah terdapat duplikasi customer_id.
## [1] 0
Missing value pada data transaksi juga diperiksa.
## customer_id nama usia pendapatan
## 0 0 2 2
## kota status usia_imputasi pendapatan_imputasi
## 1 0 0 0
## kota_imputasi pendapatan_missing outlier_usia outlier_pendapatan
## 0 0 0 0
## pendapatan_winsor usia_minmax pendapatan_minmax usia_z
## 0 0 0 0
## pendapatan_z pendapatan_decimal jumlah_transaksi total_purchase
## 0 0 1 1
Pelanggan yang tidak memiliki data transaksi ditampilkan.
data_terintegrasi[
is.na(
data_terintegrasi$jumlah_transaksi
),
c(
"customer_id",
"nama",
"jumlah_transaksi",
"total_purchase"
)
]## customer_id nama jumlah_transaksi total_purchase
## 11 C011 Kiki NA NA
Nilai NA pada bagian transaksi menunjukkan bahwa pelanggan tersebut tidak memiliki pasangan data pada dataset transaksi.
Jika NA pada transaksi menunjukkan bahwa pelanggan tidak memiliki transaksi, maka nilai tersebut dapat diubah menjadi nol.
Hasil penanganan disimpan pada variabel baru agar data transaksi asli tetap tersedia.
data_terintegrasi$jumlah_transaksi_final <-
data_terintegrasi$jumlah_transaksi
data_terintegrasi$total_purchase_final <-
data_terintegrasi$total_purchaseMissing value pada jumlah transaksi diganti dengan nol.
Missing value pada total pembelian juga diganti dengan nol.
Hasilnya diperiksa.
data_terintegrasi[
,
c(
"customer_id",
"nama",
"jumlah_transaksi",
"total_purchase",
"jumlah_transaksi_final",
"total_purchase_final"
)
]## customer_id nama jumlah_transaksi total_purchase jumlah_transaksi_final
## 1 C001 Ani 5 1.5e+06 5
## 2 C002 Budi 3 9.0e+05 3
## 3 C003 Citra 7 2.7e+06 7
## 4 C004 Dodi 2 6.0e+05 2
## 5 C005 Eka 6 2.1e+06 6
## 6 C006 Fani 4 1.3e+06 4
## 7 C007 Gilang 20 2.5e+07 20
## 8 C008 Hana 5 1.7e+06 5
## 9 C009 Indra 3 8.0e+05 3
## 10 C010 Joko 8 3.2e+06 8
## 11 C011 Kiki NA NA 0
## total_purchase_final
## 1 1.5e+06
## 2 9.0e+05
## 3 2.7e+06
## 4 6.0e+05
## 5 2.1e+06
## 6 1.3e+06
## 7 2.5e+07
## 8 1.7e+06
## 9 8.0e+05
## 10 3.2e+06
## 11 0.0e+00
Setelah preprocessing dan integrasi selesai, variabel yang akan digunakan dipilih untuk membentuk dataset akhir.
data_final <- data_terintegrasi[
,
c(
"customer_id",
"nama",
"usia_imputasi",
"kota_imputasi",
"status",
"pendapatan_imputasi",
"pendapatan_missing",
"outlier_usia",
"outlier_pendapatan",
"usia_minmax",
"pendapatan_minmax",
"usia_z",
"pendapatan_z",
"pendapatan_decimal",
"jumlah_transaksi_final",
"total_purchase_final"
)
]Beberapa nama variabel dibuat lebih sederhana agar lebih mudah dibaca.
names(data_final)[
names(data_final) == "usia_imputasi"
] <- "usia"
names(data_final)[
names(data_final) == "kota_imputasi"
] <- "kota"
names(data_final)[
names(data_final) == "pendapatan_imputasi"
] <- "pendapatan"Dataset akhir ditampilkan.
## customer_id nama usia kota status pendapatan pendapatan_missing
## 1 C001 Ani 21 pekanbaru aktif 4.5e+06 FALSE
## 2 C002 Budi 25 pekanbaru aktif 4.9e+06 TRUE
## 3 C003 Citra 23 pekanbaru aktif 5.2e+06 FALSE
## 4 C004 Dodi 27 dumai aktif 4.8e+06 FALSE
## 5 C005 Eka 27 pekanbaru tidak aktif 4.9e+06 FALSE
## 6 C006 Fani 27 dumai tidak aktif 5.1e+06 FALSE
## 7 C007 Gilang 31 pekanbaru aktif 5.0e+08 FALSE
## 8 C008 Hana 29 siak aktif 4.7e+06 FALSE
## 9 C009 Indra 22 pekanbaru aktif 4.6e+06 FALSE
## 10 C010 Joko 35 dumai tidak aktif 5.3e+06 FALSE
## 11 C011 Kiki 28 pekanbaru aktif 4.9e+06 TRUE
## outlier_usia outlier_pendapatan usia_minmax pendapatan_minmax usia_z
## 1 FALSE FALSE 0.00000000 0.0000000000 -1.42958323
## 2 FALSE FALSE 0.28571429 0.0008072654 -0.44674476
## 3 FALSE FALSE 0.14285714 0.0014127144 -0.93816399
## 4 FALSE FALSE 0.42857143 0.0006054490 0.04467448
## 5 FALSE FALSE 0.42857143 0.0008072654 0.04467448
## 6 FALSE FALSE 0.42857143 0.0012108981 0.04467448
## 7 FALSE TRUE 0.71428571 1.0000000000 1.02751295
## 8 FALSE FALSE 0.57142857 0.0004036327 0.53609371
## 9 FALSE FALSE 0.07142857 0.0002018163 -1.18387361
## 10 FALSE FALSE 1.00000000 0.0016145308 2.01035142
## 11 FALSE FALSE 0.50000000 0.0008072654 0.29038409
## pendapatan_z pendapatan_decimal jumlah_transaksi_final total_purchase_final
## 1 -0.3041235 0.0045 5 1.5e+06
## 2 -0.3014440 0.0049 3 9.0e+05
## 3 -0.2994343 0.0052 7 2.7e+06
## 4 -0.3021138 0.0048 2 6.0e+05
## 5 -0.3014440 0.0049 6 2.1e+06
## 6 -0.3001042 0.0051 4 1.3e+06
## 7 3.0151095 0.5000 20 2.5e+07
## 8 -0.3027837 0.0047 5 1.7e+06
## 9 -0.3034536 0.0046 3 8.0e+05
## 10 -0.2987645 0.0053 8 3.2e+06
## 11 -0.3014440 0.0049 0 0.0e+00
Setelah dataset akhir terbentuk, dilakukan pemeriksaan terakhir untuk melihat apakah seluruh proses preprocessing sudah berjalan dengan baik.
## 'data.frame': 11 obs. of 16 variables:
## $ customer_id : chr "C001" "C002" "C003" "C004" ...
## $ nama : chr "Ani" "Budi" "Citra" "Dodi" ...
## $ usia : num 21 25 23 27 27 27 31 29 22 35 ...
## $ kota : chr "pekanbaru" "pekanbaru" "pekanbaru" "dumai" ...
## $ status : chr "aktif" "aktif" "aktif" "aktif" ...
## $ pendapatan : num 4.5e+06 4.9e+06 5.2e+06 4.8e+06 4.9e+06 5.1e+06 5.0e+08 4.7e+06 4.6e+06 5.3e+06 ...
## $ pendapatan_missing : logi FALSE TRUE FALSE FALSE FALSE FALSE ...
## $ outlier_usia : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ outlier_pendapatan : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ usia_minmax : num 0 0.286 0.143 0.429 0.429 ...
## $ pendapatan_minmax : num 0 0.000807 0.001413 0.000605 0.000807 ...
## $ usia_z : num -1.4296 -0.4467 -0.9382 0.0447 0.0447 ...
## $ pendapatan_z : num -0.304 -0.301 -0.299 -0.302 -0.301 ...
## $ pendapatan_decimal : num 0.0045 0.0049 0.0052 0.0048 0.0049 0.0051 0.5 0.0047 0.0046 0.0053 ...
## $ jumlah_transaksi_final: num 5 3 7 2 6 4 20 5 3 8 ...
## $ total_purchase_final : num 1.5e+06 9.0e+05 2.7e+06 6.0e+05 2.1e+06 1.3e+06 2.5e+07 1.7e+06 8.0e+05 3.2e+06 ...
Pemeriksaan ini digunakan untuk memastikan tipe data setiap variabel sudah sesuai.
## [1] 11 16
Hasil tersebut menunjukkan jumlah baris dan kolom pada dataset akhir.
## customer_id nama usia kota
## Length:11 Length:11 Min. :21.00 Length:11
## Class :character Class :character 1st Qu.:24.00 Class :character
## Mode :character Mode :character Median :27.00 Mode :character
## Mean :26.82
## 3rd Qu.:28.50
## Max. :35.00
## status pendapatan pendapatan_missing outlier_usia
## Length:11 Min. :4.50e+06 Mode :logical Mode :logical
## Class :character 1st Qu.:4.75e+06 FALSE:9 FALSE:11
## Mode :character Median :4.90e+06 TRUE :2
## Mean :4.99e+07
## 3rd Qu.:5.15e+06
## Max. :5.00e+08
## outlier_pendapatan usia_minmax pendapatan_minmax usia_z
## Mode :logical Min. :0.0000 Min. :0.0000000 Min. :-1.42958
## FALSE:10 1st Qu.:0.2143 1st Qu.:0.0005045 1st Qu.:-0.69245
## TRUE :1 Median :0.4286 Median :0.0008073 Median : 0.04467
## Mean :0.4156 Mean :0.0916246 Mean : 0.00000
## 3rd Qu.:0.5357 3rd Qu.:0.0013118 3rd Qu.: 0.41324
## Max. :1.0000 Max. :1.0000000 Max. : 2.01035
## pendapatan_z pendapatan_decimal jumlah_transaksi_final
## Min. :-0.3041 Min. :0.00450 Min. : 0.000
## 1st Qu.:-0.3024 1st Qu.:0.00475 1st Qu.: 3.000
## Median :-0.3014 Median :0.00490 Median : 5.000
## Mean : 0.0000 Mean :0.04990 Mean : 5.727
## 3rd Qu.:-0.2998 3rd Qu.:0.00515 3rd Qu.: 6.500
## Max. : 3.0151 Max. :0.50000 Max. :20.000
## total_purchase_final
## Min. : 0
## 1st Qu.: 850000
## Median : 1500000
## Mean : 3618182
## 3rd Qu.: 2400000
## Max. :25000000
Ringkasan digunakan untuk melihat kondisi umum dataset setelah seluruh proses preprocessing dilakukan.
## 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 9
## 4 kota character 0 0 3
## 5 status character 0 0 2
## 6 pendapatan numeric 0 0 9
## 7 pendapatan_missing logical 0 0 2
## 8 outlier_usia logical 0 0 1
## 9 outlier_pendapatan logical 0 0 2
## 10 usia_minmax numeric 0 0 9
## 11 pendapatan_minmax numeric 0 0 9
## 12 usia_z numeric 0 0 9
## 13 pendapatan_z numeric 0 0 9
## 14 pendapatan_decimal numeric 0 0 9
## 15 jumlah_transaksi_final numeric 0 0 9
## 16 total_purchase_final numeric 0 0 11
Audit akhir digunakan untuk melihat jumlah missing value, persentase missing value, tipe data, dan jumlah nilai unik setelah preprocessing.
## [1] 0
Jika hasilnya 0, berarti tidak terdapat customer_id yang duplikat.
## customer_id nama usia
## 0 0 0
## kota status pendapatan
## 0 0 0
## pendapatan_missing outlier_usia outlier_pendapatan
## 0 0 0
## usia_minmax pendapatan_minmax usia_z
## 0 0 0
## pendapatan_z pendapatan_decimal jumlah_transaksi_final
## 0 0 0
## total_purchase_final
## 0
Pemeriksaan ini digunakan untuk mengetahui apakah masih terdapat nilai kosong pada dataset akhir.
Untuk melihat perubahan kondisi data, beberapa indikator dibandingkan antara dataset awal dan dataset akhir.
perbandingan <- data.frame(
indikator = c(
"Jumlah baris",
"Jumlah kolom",
"Duplikasi customer_id",
"Total missing value"
),
sebelum = c(
nrow(pelanggan_raw),
ncol(pelanggan_raw),
sum(
duplicated(
pelanggan_raw$customer_id
)
),
sum(
is.na(
pelanggan_raw
)
)
),
sesudah = c(
nrow(data_final),
ncol(data_final),
sum(
duplicated(
data_final$customer_id
)
),
sum(
is.na(
data_final
)
)
)
)
perbandingan## indikator sebelum sesudah
## 1 Jumlah baris 12 11
## 2 Jumlah kolom 6 16
## 3 Duplikasi customer_id 1 0
## 4 Total missing value 4 0
Tabel tersebut memberikan gambaran perubahan kondisi data sebelum dan sesudah preprocessing. Jumlah duplikasi dan missing value dapat digunakan sebagai indikator sederhana untuk melihat hasil proses cleaning.
## customer_id nama usia kota status pendapatan pendapatan_missing
## 1 C001 Ani 21 pekanbaru aktif 4.5e+06 FALSE
## 2 C002 Budi 25 pekanbaru aktif 4.9e+06 TRUE
## 3 C003 Citra 23 pekanbaru aktif 5.2e+06 FALSE
## 4 C004 Dodi 27 dumai aktif 4.8e+06 FALSE
## 5 C005 Eka 27 pekanbaru tidak aktif 4.9e+06 FALSE
## 6 C006 Fani 27 dumai tidak aktif 5.1e+06 FALSE
## 7 C007 Gilang 31 pekanbaru aktif 5.0e+08 FALSE
## 8 C008 Hana 29 siak aktif 4.7e+06 FALSE
## 9 C009 Indra 22 pekanbaru aktif 4.6e+06 FALSE
## 10 C010 Joko 35 dumai tidak aktif 5.3e+06 FALSE
## 11 C011 Kiki 28 pekanbaru aktif 4.9e+06 TRUE
## outlier_usia outlier_pendapatan usia_minmax pendapatan_minmax usia_z
## 1 FALSE FALSE 0.00000000 0.0000000000 -1.42958323
## 2 FALSE FALSE 0.28571429 0.0008072654 -0.44674476
## 3 FALSE FALSE 0.14285714 0.0014127144 -0.93816399
## 4 FALSE FALSE 0.42857143 0.0006054490 0.04467448
## 5 FALSE FALSE 0.42857143 0.0008072654 0.04467448
## 6 FALSE FALSE 0.42857143 0.0012108981 0.04467448
## 7 FALSE TRUE 0.71428571 1.0000000000 1.02751295
## 8 FALSE FALSE 0.57142857 0.0004036327 0.53609371
## 9 FALSE FALSE 0.07142857 0.0002018163 -1.18387361
## 10 FALSE FALSE 1.00000000 0.0016145308 2.01035142
## 11 FALSE FALSE 0.50000000 0.0008072654 0.29038409
## pendapatan_z pendapatan_decimal jumlah_transaksi_final total_purchase_final
## 1 -0.3041235 0.0045 5 1.5e+06
## 2 -0.3014440 0.0049 3 9.0e+05
## 3 -0.2994343 0.0052 7 2.7e+06
## 4 -0.3021138 0.0048 2 6.0e+05
## 5 -0.3014440 0.0049 6 2.1e+06
## 6 -0.3001042 0.0051 4 1.3e+06
## 7 3.0151095 0.5000 20 2.5e+07
## 8 -0.3027837 0.0047 5 1.7e+06
## 9 -0.3034536 0.0046 3 8.0e+05
## 10 -0.2987645 0.0053 8 3.2e+06
## 11 -0.3014440 0.0049 0 0.0e+00
Dataset ini merupakan hasil akhir setelah dilakukan pemeriksaan data, cleaning, penanganan missing value, pemeriksaan outlier, transformasi, dan integrasi dengan data transaksi.
Berdasarkan proses yang telah dilakukan, dataset pelanggan dan dataset transaksi berhasil dipersiapkan melalui beberapa tahap preprocessing.
Pada pemeriksaan awal ditemukan beberapa masalah pada dataset pelanggan, yaitu missing value, duplikasi customer_id, perbedaan penulisan kategori, serta nilai usia yang tidak wajar. Masalah tersebut diperbaiki secara bertahap agar data menjadi lebih konsisten dan lebih mudah digunakan pada analisis berikutnya.
Data kategorik seperti kota dan status diseragamkan dengan menghilangkan spasi yang tidak diperlukan, menyamakan penggunaan huruf, dan menyatukan kategori yang memiliki arti sama. Duplikasi customer_id kemudian dihapus dengan mempertahankan data yang muncul pertama kali.
Nilai usia yang tidak wajar, yaitu 150 tahun, diubah menjadi NA karena nilainya tidak sesuai dengan kondisi data. Missing value pada variabel numerik kemudian ditangani menggunakan median, sedangkan missing value pada variabel kategorik ditangani menggunakan modus.
Selanjutnya dilakukan pemeriksaan outlier menggunakan boxplot dan metode IQR. Outlier pada pendapatan tidak langsung dihapus karena belum tentu merupakan kesalahan. Sebagai alternatif, dilakukan winsorizing untuk membatasi nilai yang terlalu ekstrem tanpa menghilangkan observasi.
Data numerik kemudian ditransformasikan menggunakan tiga metode, yaitu Min-Max, Z-Score, dan Decimal Scaling. Ketiga metode tersebut menghasilkan skala data yang berbeda dan dapat digunakan sesuai kebutuhan analisis.
Tahap berikutnya adalah integrasi antara data pelanggan dan data transaksi. Sebelum digabungkan, nama identifier disamakan menjadi customer_id. Penggabungan dilakukan menggunakan merge() dengan all.x = TRUE sehingga seluruh pelanggan pada dataset utama tetap dipertahankan.
Setelah semua proses selesai, dataset akhir kembali diperiksa melalui pemeriksaan struktur, dimensi, missing value, duplikasi, dan audit data. Hasil tersebut menunjukkan kondisi dataset setelah melalui seluruh proses preprocessing.
Dengan demikian, data yang awalnya masih memiliki beberapa masalah telah menjadi lebih rapi, konsisten, dan lebih siap digunakan untuk tahap analisis data mining selanjutnya.