Data Preprocessing Menggunakan RStudio
Pendahuluan
Dalam analisis data, data yang tersedia tidak selalu berada dalam kondisi siap digunakan. Pada praktikum ini, saya melakukan data preprocessing menggunakan RStudio dengan bahasa pemrograman R pada data pelanggan dan data transaksi sebuah perusahaan e-commerce. Data pelanggan memuat informasi identitas, usia, kota, pendapatan, dan status pelanggan, sedangkan data transaksi memuat jumlah transaksi dan total pembelian.
Kedua sumber data tersebut masih memiliki beberapa permasalahan, seperti missing values, kategori yang tidak konsisten, duplikasi, nilai ekstrem, serta perbedaan nama identifier. Oleh karena itu, dilakukan serangkaian tahapan preprocessing yang meliputi pemeriksaan kualitas data, data cleaning, penanganan missing values dan outlier, transformasi data numerik, serta integrasi kedua sumber data hingga diperoleh satu dataset yang lebih bersih dan terstruktur.
Dalam prosesnya, setiap perubahan terhadap data dilakukan berdasarkan alasan dan aturan yang jelas, bukan hanya karena suatu nilai terlihat berbeda atau tidak biasa. Dengan demikian, proses preprocessing tidak hanya bertujuan menghasilkan data yang lebih rapi, tetapi juga menjaga agar informasi yang terkandung di dalam data tetap dapat dipertanggungjawabkan dan siap digunakan untuk analisis selanjutnya.
Memeriksa Lingkungan Kerja
Praktikum dilakukan menggunakan RStudio dengan bahasa pemrograman R sebagai perangkat pengolahan data. Pemeriksaan lingkungan kerja dilakukan untuk mengetahui lokasi working directory dan versi R yang digunakan.
## [1] "C:/Sem 5"
## [1] "R version 4.5.1 (2025-06-13 ucrt)"
Membangun Dataset Praktikum
Dataset praktikum terdiri atas dua sumber data, yaitu data pelanggan dan data transaksi yang dibentuk menggunakan R sebagai data awal untuk proses preprocessing.
pelanggan_raw <- data.frame(
customer_id = c(
"C001", "C002", "C003", "C004", "C005", "C006",
"C007", "C008", "C009", "C010", "C010", "C011",
"C012", "C013", "C014", "C015", "C015", "C016",
"C017", "C018", "C019", "C020", "C021", "C022",
"C023", "C024", "C025", "C026", "C027", "C028"
),
nama = c(
"Ani", "Budi", "Citra", "Dodi", "Eka", "Fani",
"Gilang", "Hana", "Indra", "Joko", "Joko", "Kiki",
"Lina", "Maya", "Nanda", "Oki", "Oki", "Putri",
"Raka", "Salsa", "Tio", "Uli", "Vina", "Wawan",
"Yani", "Zaki", "Aldi", "Bella", "Caca", "Dian"
),
usia = c(
21, 25, 23, 150, 27, NA,
31, 29, 22, 35, 35, 28,
24, 26, 30, 32, 32, 27,
34, 23, 29, NA, 31, 28,
25, 33, 140, 22, 36, 27
),
pendapatan = c(
4500000, NA, 5200000, 4800000, 4900000, 5100000,
500000000, 4700000, 4600000, 5300000, 5300000, NA,
4800000, 5500000, NA, 5100000, 5100000, 4900000,
6000000, 4700000, 5200000, NA, 5400000, 5000000,
5600000, 4800000, 350000000, 4500000, NA, 5100000
),
kota = c(
"Pekanbaru", " PKU", "PEKANBARU", "Dumai", "pekanbaru",
"DUMAI", "Pekanbaru ", "Siak", "PKU", "Dumai",
"Dumai", NA,
"Pekanbaru", "pekanbaru", " PKU", "DUMAI", "DUMAI",
"Siak", "Pekanbaru ", "PEKANBARU", "Dumai", "PKU",
"pekanbaru", "Pekanbaru", "DUMAI", "Siak", NA,
"PEKANBARU", "Dumai", "Pekanbaru"
),
status = c(
"Aktif", "aktif", "ACTIVE", "A", "Tidak Aktif", "nonaktif",
"Aktif", "AKTIF", "A", "Tidak aktif", "Tidak aktif", "Aktif",
"aktif", "ACTIVE", "A", "Tidak Aktif", "Tidak Aktif", "AKTIF",
"Aktif", "active", "A", "nonaktif", "Tidak aktif", "AKTIF",
"aktif", "ACTIVE", "A", "Tidak Aktif", "nonaktif", "Aktif"
),
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
## 13 C012 Lina 24 4.8e+06 Pekanbaru aktif
## 14 C013 Maya 26 5.5e+06 pekanbaru ACTIVE
## 15 C014 Nanda 30 NA PKU A
## 16 C015 Oki 32 5.1e+06 DUMAI Tidak Aktif
## 17 C015 Oki 32 5.1e+06 DUMAI Tidak Aktif
## 18 C016 Putri 27 4.9e+06 Siak AKTIF
## 19 C017 Raka 34 6.0e+06 Pekanbaru Aktif
## 20 C018 Salsa 23 4.7e+06 PEKANBARU active
## 21 C019 Tio 29 5.2e+06 Dumai A
## 22 C020 Uli NA NA PKU nonaktif
## 23 C021 Vina 31 5.4e+06 pekanbaru Tidak aktif
## 24 C022 Wawan 28 5.0e+06 Pekanbaru AKTIF
## 25 C023 Yani 25 5.6e+06 DUMAI aktif
## 26 C024 Zaki 33 4.8e+06 Siak ACTIVE
## 27 C025 Aldi 140 3.5e+08 <NA> A
## 28 C026 Bella 22 4.5e+06 PEKANBARU Tidak Aktif
## 29 C027 Caca 36 NA Dumai nonaktif
## 30 C028 Dian 27 5.1e+06 Pekanbaru Aktif
transaksi_raw <- data.frame(
cust_id = c(
"C001", "C002", "C003", "C004", "C005", "C006",
"C007", "C008", "C009", "C010", "C012",
"C013", "C014", "C015", "C016", "C017", "C018",
"C019", "C020", "C021", "C022", "C023", "C024",
"C025", "C026", "C027", "C028", "C029", "C030", "C031"
),
jumlah_transaksi = c(
5, 3, 7, 2, 6, 4,
20, 5, 3, 8, 1,
4, 6, 5, 9, 3, 7,
2, 8, 4, 6, 5, 10,
3, 7, 25, 4, 6, 2, 5
),
total_purchase = c(
1500000, 900000, 2700000, 600000, 2100000, 1300000,
25000000, 1700000, 800000, 3200000, 250000,
1200000, 2400000, 1800000, 3500000, 900000, 2800000,
700000, 3100000, 1500000, 2200000, 1900000, 4200000,
30000000, 1300000, 2700000, 950000, 2100000, 600000, 1600000
),
stringsAsFactors = FALSE
)
transaksi_raw## 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
## 12 C013 4 1.2e+06
## 13 C014 6 2.4e+06
## 14 C015 5 1.8e+06
## 15 C016 9 3.5e+06
## 16 C017 3 9.0e+05
## 17 C018 7 2.8e+06
## 18 C019 2 7.0e+05
## 19 C020 8 3.1e+06
## 20 C021 4 1.5e+06
## 21 C022 6 2.2e+06
## 22 C023 5 1.9e+06
## 23 C024 10 4.2e+06
## 24 C025 3 3.0e+07
## 25 C026 7 1.3e+06
## 26 C027 25 2.7e+06
## 27 C028 4 9.5e+05
## 28 C029 6 2.1e+06
## 29 C030 2 6.0e+05
## 30 C031 5 1.6e+06
Bagian I — Konsep Data Preprocessing
Memahami Struktur Data
Sebelum melakukan perubahan, periksa struktur, dimensi, tipe atribut, dan beberapa observasi awal.
## [1] 30 6
Interpretasi: Dataset pelanggan terdiri atas 30 observasi dan 6 atribut, sehingga terdapat enam variabel yang akan diperiksa dan diproses pada tahap selanjutnya.
## [1] 30 3
Interpretasi: Dataset transaksi terdiri atas 30 observasi dan 3 atribut.
## [1] "customer_id" "nama" "usia" "pendapatan" "kota"
## [6] "status"
Interpretasi: Dataset pelanggan memiliki atribut customer_id, nama, usia, pendapatan, kota, dan status yang mencakup informasi identitas maupun karakteristik pelanggan.
## [1] "cust_id" "jumlah_transaksi" "total_purchase"
Interpretasi: Dataset transaksi memiliki atribut cust_id, jumlah_transaksi, dan total_purchase.
## 'data.frame': 30 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" ...
Interpretasi: Struktur data menunjukkan bahwa customer_id, nama, kota, dan status bertipe karakter, sedangkan usia dan pendapatan bertipe numerik sehingga dapat digunakan untuk pemeriksaan statistik.
## 'data.frame': 30 obs. of 3 variables:
## $ cust_id : chr "C001" "C002" "C003" "C004" ...
## $ 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 ...
Interpretasi: Struktur data menunjukkan bahwa customer_id bertipe karakter, sedangkan jumlah_transaksi dan total_purchase bertipe numerik sehingga dapat digunakan untuk pemeriksaan statistik.
## 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
Interpretasi: Beberapa observasi awal memperlihatkan bahwa data memiliki variasi penulisan pada atribut kategori serta terdapat nilai yang perlu diperiksa lebih lanjut.
## cust_id jumlah_transaksi total_purchase
## 1 C001 5 1500000
## 2 C002 3 900000
## 3 C003 7 2700000
## 4 C004 2 600000
## 5 C005 6 2100000
## 6 C006 4 1300000
## customer_id nama usia pendapatan
## Length:30 Length:30 Min. : 21.00 Min. : 4500000
## Class :character Class :character 1st Qu.: 25.00 1st Qu.: 4800000
## Mode :character Mode :character Median : 28.50 Median : 5100000
## Mean : 36.61 Mean : 38644000
## 3rd Qu.: 32.25 3rd Qu.: 5300000
## Max. :150.00 Max. :500000000
## NA's :2 NA's :5
## kota status
## Length:30 Length:30
## Class :character Class :character
## Mode :character Mode :character
##
##
##
##
Interpretasi: Ringkasan data menunjukkan adanya nilai hilang pada usia dan pendapatan, serta rentang nilai yang cukup ekstrem sehingga kedua atribut tersebut perlu diperiksa lebih lanjut.
## cust_id jumlah_transaksi total_purchase
## Length:30 Min. : 1.000 Min. : 250000
## Class :character 1st Qu.: 3.250 1st Qu.: 1012500
## Mode :character Median : 5.000 Median : 1750000
## Mean : 6.167 Mean : 3516667
## 3rd Qu.: 7.000 3rd Qu.: 2700000
## Max. :25.000 Max. :30000000
Interpretasi: Ringkasan menunjukkan bahwa kedua atribut numerik memiliki rentang nilai yang cukup lebar, sehingga perlu diperiksa lebih lanjut untuk memastikan adanya atau tidaknya nilai ekstrem.
Mengukur Kualitas Awal
Setelah mengetahui struktur awal dataset, tahap berikutnya adalah memeriksa kualitas data untuk mengidentifikasi permasalahan yang perlu ditangani sebelum proses preprocessing dilakukan. Pemeriksaan ini berfokus pada kondisi yang dapat diketahui langsung dari dataset, seperti kelengkapan data, konsistensi nilai, duplikasi, serta kesesuaian nilai dengan aturan yang berlaku.
## customer_id nama usia pendapatan kota status
## 0 0 2 5 2 0
Interpretasi: Hasil pemeriksaan menunjukkan bahwa terdapat missing value pada atribut usia sebanyak 2 nilai, pendapatan sebanyak 5 nilai, dan kota sebanyak 2 nilai. Atribut lainnya tidak memiliki nilai yang hilang.
## customer_id nama usia pendapatan kota status
## 0.00 0.00 6.67 16.67 6.67 0.00
Interpretasi: Secara persentase, missing value terdapat pada usia sebesar 6,67%, pendapatan sebesar 16,67%, dan kota sebesar 6,67%, dengan persentase tertinggi terdapat pada atribut pendapatan.
## cust_id jumlah_transaksi total_purchase
## 0 0 0
Interpretasi: Tidak ditemukan missing value pada seluruh atribut data transaksi, sehingga ketiga atribut memiliki kelengkapan data sebesar 100%.
## [1] 2
Interpretasi: Ditemukan 2 baris yang teridentifikasi sebagai duplikat penuh pada data pelanggan. Kondisi ini perlu diperiksa lebih lanjut untuk menentukan apakah baris tersebut merupakan data yang benar-benar berulang.
## [1] 2
Interpretasi: Ditemukan 2 customer_id yang berulang, sehingga keunikan identifier pelanggan belum sepenuhnya terpenuhi. Kondisi ini perlu ditangani sebelum proses integrasi dengan data transaksi.
## [1] 0
Interpretasi: Tidak ditemukan baris duplikat pada data transaksi, sehingga setiap observasi tercatat secara unik berdasarkan seluruh atribut yang diperiksa.
## [1] " PKU" "Dumai" "DUMAI" "pekanbaru" "Pekanbaru"
## [6] "PEKANBARU" "Pekanbaru " "PKU" "Siak"
Interpretasi: Atribut kota memiliki beberapa variasi penulisan untuk kategori yang sama, seperti PKU dan Pekanbaru dengan perbedaan kapitalisasi maupun spasi. Hal ini menunjukkan adanya ketidakkonsistenan kategori yang perlu distandardisasi.
## [1] "A" "active" "ACTIVE" "aktif" "Aktif"
## [6] "AKTIF" "nonaktif" "Tidak aktif" "Tidak Aktif"
Interpretasi: Atribut status memiliki beberapa bentuk penulisan yang merujuk pada kategori yang sama, seperti Aktif, aktif, ACTIVE, dan A. Variasi tersebut menunjukkan adanya ketidakkonsistenan kategori yang perlu diperbaiki.
## [1] 21 150
Interpretasi: Atribut usia memiliki rentang nilai 21–150 tahun. Nilai maksimum 150 tahun terlihat tidak wajar sehingga perlu dievaluasi lebih lanjut berdasarkan aturan domain dan metode deteksi yang digunakan.
## [1] 4.5e+06 5.0e+08
Interpretasi: Atribut pendapatan memiliki rentang Rp4,5 juta hingga Rp500 juta, dengan nilai maksimum yang jauh lebih tinggi dibandingkan sebagian besar data. Nilai tersebut menjadi kandidat outlier yang perlu diperiksa lebih lanjut.
## [1] 1 25
Interpretasi: Atribut jumlah_transaksi memiliki rentang 1–25 transaksi. Nilai maksimum 25 relatif lebih tinggi dibandingkan sebagian besar observasi sehingga dapat diperiksa lebih lanjut sebagai kandidat nilai ekstrem.
## [1] 2.5e+05 3.0e+07
Interpretasi: Atribut total_purchase memiliki rentang Rp250 ribu hingga Rp30 juta. Nilai maksimum Rp30 juta terlihat cukup jauh dari sebagian besar observasi sehingga perlu dievaluasi lebih lanjut sebagai kandidat outlier.
Membuat Fungsi Ringkasan Kualitas
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 28
## 2 nama character 0 0.00 28
## 3 usia numeric 2 6.67 19
## 4 pendapatan numeric 5 16.67 16
## 5 kota character 2 6.67 10
## 6 status character 0 0.00 9
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(transaksi_raw)
audit_awal## atribut tipe jumlah_missing persen_missing jumlah_unik
## 1 cust_id character 0 0 30
## 2 jumlah_transaksi numeric 0 0 12
## 3 total_purchase numeric 0 0 24
Interpretasi: hasil audit bukan keputusan cleaning. Hasil audit digunakan untuk mengidentifikasi atribut yang memerlukan pemeriksaan lebih lanjut sebelum menentukan tindakan preprocessing.
Bagian II — Implementasi Data Cleaning
Membuat Salinan Kerja
Data mentah dipertahankan sebagai data awal, sedangkan proses pembersihan dilakukan pada salinan kerja agar perubahan yang dilakukan tetap dapat ditelusuri.
Membersihkan Spasi dan Kapitalisasi
Berdasarkan hasil pemeriksaan sebelumnya, atribut kota dan status memiliki variasi spasi dan kapitalisasi. Oleh karena itu, dilakukan pembersihan spasi terlebih dahulu dan penyeragaman huruf untuk memudahkan proses standardisasi kategori.
# Menghapus spasi di awal dan akhir
pelanggan$kota <- trimws(pelanggan$kota)
pelanggan$status <- trimws(pelanggan$status)
# Menyeragamkan huruf menjadi kecil
pelanggan$kota <- tolower(pelanggan$kota)
pelanggan$status <- tolower(pelanggan$status)## [1] "dumai" "pekanbaru" "pku" "siak"
## [1] "a" "active" "aktif" "nonaktif" "tidak aktif"
Interpretasi: Setelah proses tersebut, kategori akan menjadi lebih mudah dibandingkan karena perbedaan seperti “Pekanbaru”, “PEKANBARU”, dan “pekanbaru” sudah diseragamkan menjadi “pekanbaru”.
Menyeragamkan Kategori
Berdasarkan hasil pemeriksaan, terdapat beberapa kategori yang sebenarnya merujuk pada wilayah atau status yang sama. Oleh karena itu, kategori tersebut distandardisasi berdasarkan aturan yang telah ditentukan.
Standardisasi Kota
pelanggan$kota[pelanggan$kota %in% c("pku", "pekanbaru")] <- "Pekanbaru"
pelanggan$kota[pelanggan$kota == "dumai"] <- "Dumai"
pelanggan$kota[pelanggan$kota == "siak"] <- "Siak"
sort(unique(pelanggan$kota))## [1] "Dumai" "Pekanbaru" "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$status))## [1] "Aktif" "Tidak Aktif"
Catatan: NA pada kota tidak ikut diubah karena merupakan missing value dan akan ditangani pada tahap tersendiri.
Mendeteksi dan Menangani Duplikasi
Pada pemeriksaan awal ditemukan 2 baris duplikat penuh dan terdapat 2 customer_id yang berulang, yaitu C010 dan C015.
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
## 16 C015 Oki 32 5100000 Dumai Tidak Aktif
## 17 C015 Oki 32 5100000 Dumai Tidak Aktif
Karena setiap customer_id dalam data ini merepresentasikan satu pelanggan, kemunculan identifier yang berulang diperlakukan sebagai duplikasi. Satu observasi dipertahankan dan kemunculan berikutnya dihapus.
pelanggan <- pelanggan[!duplicated(pelanggan$customer_id), ]
# Mengatur kembali nomor baris
rownames(pelanggan) <- NULL
dim(pelanggan)## [1] 28 6
Memeriksa Aturan Domain
Pada tahap pemeriksaan sebelumnya ditemukan nilai usia 150 dan 140 tahun. Karena atribut usia memiliki aturan domain, dilakukan pemeriksaan berdasarkan rentang usia yang dianggap wajar, misalnya digunakan aturan 15–100 tahun:
## customer_id nama usia pendapatan kota status
## 4 C004 Dodi 150 4.8e+06 Dumai Aktif
## 25 C025 Aldi 140 3.5e+08 <NA> Aktif
Interpretasi: Nilai 140 dan 150 melanggar aturan domain, tetapi nilai sebenarnya tidak diketahui. Oleh karena itu, keduanya tidak digantikan dengan nilai estimasi tanpa dasar yang memadai.
Nilai yang melanggar aturan domain tidak langsung diganti dengan nilai tertentu karena tidak tersedia informasi yang dapat memastikan nilai sebenarnya. Oleh karena itu, nilai tersebut diubah menjadi NA dan selanjutnya ditangani bersama missing values.
Membuat Log Perubahan
log_perubahan <- data.frame(
tahap = c(
"Standardisasi",
"Standardisasi",
"Deduplikasi",
"Deduplikasi",
"Penanganan domain"
),
atribut = c(
"kota",
"status",
"customer_id",
"customer_id",
"usia"
),
tindakan = c(
"Menyeragamkan variasi PKU dan Pekanbaru menjadi Pekanbaru",
"Menyeragamkan variasi Aktif dan Tidak Aktif menjadi dua kategori standar",
"Menghapus kemunculan kedua C010",
"Menghapus kemunculan kedua C015",
"Mengubah usia 140 dan 150 menjadi NA karena melanggar aturan domain dan nilai sebenarnya tidak diketahui"
),
stringsAsFactors = FALSE
)
log_perubahan## tahap atribut
## 1 Standardisasi kota
## 2 Standardisasi status
## 3 Deduplikasi customer_id
## 4 Deduplikasi customer_id
## 5 Penanganan domain usia
## tindakan
## 1 Menyeragamkan variasi PKU dan Pekanbaru menjadi Pekanbaru
## 2 Menyeragamkan variasi Aktif dan Tidak Aktif menjadi dua kategori standar
## 3 Menghapus kemunculan kedua C010
## 4 Menghapus kemunculan kedua C015
## 5 Mengubah usia 140 dan 150 menjadi NA karena melanggar aturan domain dan nilai sebenarnya tidak diketahui
Bagian III — Penanganan Missing Values
Mengidentifikasi Lokasi Nilai Hilang
Setelah proses data cleaning, dilakukan pemeriksaan kembali untuk mengetahui jumlah dan lokasi missing values yang masih terdapat pada data.
## customer_id nama usia pendapatan kota status
## 0 0 4 5 2 0
Untuk melihat observasi yang masih memiliki setidaknya satu nilai hilang:
# Menampilkan baris yang memiliki sedikitnya satu missing value
pelanggan[!complete.cases(pelanggan), ]## customer_id nama usia pendapatan kota status
## 2 C002 Budi 25 NA Pekanbaru Aktif
## 4 C004 Dodi NA 4.8e+06 Dumai Aktif
## 6 C006 Fani NA 5.1e+06 Dumai Tidak Aktif
## 11 C011 Kiki 28 NA <NA> Aktif
## 14 C014 Nanda 30 NA Pekanbaru Aktif
## 20 C020 Uli NA NA Pekanbaru Tidak Aktif
## 25 C025 Aldi NA 3.5e+08 <NA> Aktif
## 27 C027 Caca 36 NA Dumai Tidak Aktif
Interpretasi: Berdasarkan hasil pemeriksaan, missing values terdapat pada atribut usia, pendapatan, dan kota. Nilai hilang pada usia berasal dari nilai yang sebelumnya melanggar aturan domain, sedangkan nilai hilang pada pendapatan dan kota memang terdapat pada data awal.
Menilai Proporsi Missing Values
Sebelum menentukan strategi penanganan, persentase missing values perlu diperiksa untuk mengetahui seberapa besar bagian data yang terdampak.
## customer_id nama usia pendapatan kota status
## 0.00 0.00 14.29 17.86 7.14 0.00
Hasil ini digunakan sebagai pertimbangan dalam menentukan apakah penghapusan baris masih layak dilakukan atau diperlukan metode imputasi.
Strategi 1 — Menghapus Baris yang Memiliki Missing Values
Penghapusan baris digunakan sebagai salah satu strategi pembanding. Data asli tidak langsung diganti, sehingga dampak metode ini dapat dievaluasi terlebih dahulu.
Jumlah baris sebelum dan sesudah penghapusan:
## [1] 28
## [1] 20
Persentase baris yang akan hilang:
## [1] 28.57
Interpretasi: Penghapusan baris menyebabkan sebagian observasi tidak dapat digunakan karena memiliki setidaknya satu missing value. Jika proporsi baris yang hilang cukup besar, metode ini dapat mengurangi jumlah data yang tersedia untuk analisis.
Strategi 2 — Imputasi Numerik dengan Median
Untuk atribut numerik usia dan pendapatan, dilakukan perbandingan antara nilai mean dan median sebelum menentukan metode imputasi.
Imputasi Pendapatan
## [1] 41552174
## [1] 5100000
Berdasarkan pemeriksaan sebelumnya, pendapatan memiliki nilai ekstrem hingga Rp500.000.000. Kondisi tersebut dapat menyebabkan mean menjadi lebih besar dan kurang mewakili sebagian besar data. Oleh karena itu, median dipilih sebagai nilai imputasi karena lebih tahan terhadap pengaruh nilai ekstrem.
Imputasi Usia
Untuk usia, nilai 140 dan 150 sebelumnya telah ditangani sebagai missing values karena melanggar aturan domain. Selain itu, terdapat missing values pada data awal.
Median usia dihitung sebagai berikut:
## [1] 27.5
Kemudian dilakukan imputasi:
pelanggan$usia_imputasi <- pelanggan$usia
pelanggan$usia_imputasi[
is.na(pelanggan$usia_imputasi)
] <- median_usiapelanggan[
is.na(pelanggan$usia) |
is.na(pelanggan$pendapatan),
c(
"customer_id",
"usia",
"usia_imputasi",
"pendapatan",
"pendapatan_imputasi"
)
]## customer_id usia usia_imputasi pendapatan pendapatan_imputasi
## 2 C002 25 25.0 NA 5.1e+06
## 4 C004 NA 27.5 4.8e+06 4.8e+06
## 6 C006 NA 27.5 5.1e+06 5.1e+06
## 11 C011 28 28.0 NA 5.1e+06
## 14 C014 30 30.0 NA 5.1e+06
## 20 C020 NA 27.5 NA 5.1e+06
## 25 C025 NA 27.5 3.5e+08 3.5e+08
## 27 C027 36 36.0 NA 5.1e+06
Interpretasi: Missing values pada atribut numerik diisi menggunakan median agar jumlah observasi tetap dipertahankan. Median dipilih karena lebih stabil terhadap nilai ekstrem, terutama pada atribut pendapatan.
Strategi 3 — Imputasi Nilai Kategorik
Pada atribut kota, nilai yang hilang tidak langsung diisi menggunakan modus karena pengisian tersebut dapat membuat nilai yang tidak diketahui seolah-olah benar-benar berasal dari kategori tertentu.
Oleh karena itu, digunakan kategori eksplisit “Tidak diketahui”.
pelanggan$kota_imputasi <- pelanggan$kota
pelanggan$kota_imputasi[
is.na(pelanggan$kota_imputasi)
] <- "Tidak diketahui"##
## Dumai Pekanbaru Siak Tidak diketahui
## 7 16 3 2
Interpretasi: Nilai kota yang hilang diberi kategori “Tidak diketahui” agar informasi mengenai ketidakpastian tetap dipertahankan dan tidak dianggap sebagai kategori kota tertentu.
Menambahkan Indikator Missing
Selain melakukan imputasi, informasi bahwa suatu nilai sebelumnya hilang dapat dipertahankan melalui variabel indikator.
Untuk pendapatan:
pelanggan$pendapatan_missing <- as.integer(
is.na(pelanggan$pendapatan)
)
table(pelanggan$pendapatan_missing)##
## 0 1
## 23 5
Untuk usia:
##
## 0 1
## 24 4
Interpretasi: Variabel indikator menunjukkan observasi yang sebelumnya memiliki nilai hilang, sehingga informasi mengenai keberadaan missing value tetap dapat dipertahankan setelah proses imputasi.
Membandingkan Kondisi Sebelum dan Sesudah Imputasi
Karena pendapatan memiliki nilai ekstrem, distribusi sebelum dan sesudah imputasi perlu dibandingkan untuk melihat perubahan yang terjadi.
par(mfrow = c(1, 2))
hist(
pelanggan$pendapatan,
main = "Sebelum Imputasi",
xlab = "Pendapatan",
breaks = 8
)
hist(
pelanggan$pendapatan_imputasi,
main = "Sesudah Imputasi Median",
xlab = "Pendapatan",
breaks = 8
)Kemudian kembalikan tampilan grafik:
Imputasi median mengisi nilai yang hilang tanpa menambahkan nilai ekstrem baru ke dalam data. Namun, karena nilai yang hilang digantikan dengan satu nilai yang sama, variasi pada atribut tersebut dapat sedikit berkurang.
Bagian IV — Penanganan Outlier
Visualisasi dengan Boxplot
Setelah missing values ditangani, pemeriksaan dilanjutkan terhadap nilai ekstrem pada atribut numerik. Boxplot digunakan untuk memberikan gambaran awal mengenai penyebaran data dan mengidentifikasi observasi yang berada jauh dari sebagian besar nilai lainnya.
boxplot(
pelanggan$pendapatan_imputasi,
horizontal = TRUE,
main = "Boxplot Pendapatan",
xlab = "Pendapatan"
)Interpretasi: Boxplot menunjukkan adanya beberapa nilai pendapatan yang berada jauh di atas sebagian besar observasi. Kondisi tersebut menjadi kandidat outlier yang perlu diperiksa lebih lanjut menggunakan batas IQR.
Menghitung Batas IQR
Untuk menentukan kandidat outlier, digunakan metode Interquartile Range (IQR). Nilai yang berada di bawah Q1 - 1.5 × IQR atau di atas Q3 + 1.5 × IQR ditandai sebagai kandidat outlier.
q1_pendapatan <- quantile(
pelanggan$pendapatan_imputasi,
0.25,
na.rm = TRUE
)
q3_pendapatan <- quantile(
pelanggan$pendapatan_imputasi,
0.75,
na.rm = TRUE
)
iqr_pendapatan <- IQR(
pelanggan$pendapatan_imputasi,
na.rm = TRUE
)
batas_bawah_pendapatan <- q1_pendapatan -
1.5 * iqr_pendapatan
batas_atas_pendapatan <- q3_pendapatan +
1.5 * iqr_pendapatan
c(
Q1 = q1_pendapatan,
Q3 = q3_pendapatan,
IQR = iqr_pendapatan,
batas_bawah = batas_bawah_pendapatan,
batas_atas = batas_atas_pendapatan
)## Q1.25% Q3.75% IQR batas_bawah.25% batas_atas.75%
## 4800000 5225000 425000 4162500 5862500
Menandai Kandidat Outlier
Selanjutnya, setiap observasi dibandingkan dengan batas IQR yang telah diperoleh.
pelanggan$outlier_pendapatan <-
pelanggan$pendapatan_imputasi < batas_bawah_pendapatan |
pelanggan$pendapatan_imputasi > batas_atas_pendapatanUntuk melihat observasi yang teridentifikasi sebagai kandidat outlier:
## customer_id nama pendapatan_imputasi
## 7 C007 Gilang 5.0e+08
## 17 C017 Raka 6.0e+06
## 25 C025 Aldi 3.5e+08
Interpretasi: Hasil metode IQR menunjukkan observasi dengan pendapatan yang berada di atas batas atas sebagai kandidat outlier. Nilai tersebut kemudian perlu dievaluasi berdasarkan konteks data sebelum ditentukan apakah akan dipertahankan atau ditangani lebih lanjut.
Mengevaluasi Kandidat Outlier
Nilai ekstrem tidak langsung dianggap sebagai kesalahan. Pada data kamu, pendapatan yang sangat tinggi perlu diperiksa terlebih dahulu untuk menentukan apakah nilai tersebut merupakan kesalahan pencatatan atau memang mencerminkan kondisi pelanggan yang sebenarnya.
Beberapa kemungkinan yang dapat dipertimbangkan adalah:
Kesalahan input, jika nilai tidak sesuai dengan sumber data asli dan dapat diverifikasi. Observasi valid tetapi ekstrem, jika nilai tersebut memang mencerminkan pelanggan dengan pendapatan tinggi. Perbedaan karakteristik pelanggan, jika pelanggan dengan pendapatan sangat tinggi berasal dari kelompok atau segmen yang berbeda.
Karena tidak terdapat informasi tambahan yang dapat memastikan bahwa nilai ekstrem tersebut merupakan kesalahan input, nilai pendapatan ekstrem tidak langsung dihapus.
Membuat Versi Winsorized Sebagai Perbandingan
Untuk melihat bagaimana pembatasan nilai ekstrem dapat memengaruhi data, dibuat versi winsorized dari pendapatan. Nilai yang berada di luar batas IQR dibatasi pada nilai batas tersebut.
pelanggan$pendapatan_winsor <- pmin(
pmax(
pelanggan$pendapatan_imputasi,
batas_bawah_pendapatan
),
batas_atas_pendapatan
)Kemudian dibandingkan nilai sebelum dan sesudah winsorization:
pelanggan[
pelanggan$outlier_pendapatan,
c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_winsor"
)
]## customer_id pendapatan_imputasi pendapatan_winsor
## 7 C007 5.0e+08 5862500
## 17 C017 6.0e+06 5862500
## 25 C025 3.5e+08 5862500
Interpretasi: Winsorization membatasi nilai pendapatan yang melewati batas IQR tanpa menghapus observasinya. Hasil ini dapat digunakan sebagai pembanding untuk melihat dampak penanganan nilai ekstrem terhadap data.
Catatan: Winsorization hanya digunakan sebagai alternatif pembanding dan tidak otomatis menjadi data akhir. Penggunaannya perlu disesuaikan dengan tujuan analisis dan karakteristik data.
Pemeriksaan Outlier pada Jumlah Transaksi
boxplot(
transaksi$jumlah_transaksi,
horizontal = TRUE,
main = "Boxplot Jumlah Transaksi",
xlab = "Jumlah Transaksi"
)q1_transaksi <- quantile(
transaksi$jumlah_transaksi,
0.25
)
q3_transaksi <- quantile(
transaksi$jumlah_transaksi,
0.75
)
iqr_transaksi <- IQR(
transaksi$jumlah_transaksi
)
batas_bawah_transaksi <- q1_transaksi -
1.5 * iqr_transaksi
batas_atas_transaksi <- q3_transaksi +
1.5 * iqr_transaksi
c(
Q1 = q1_transaksi,
Q3 = q3_transaksi,
IQR = iqr_transaksi,
batas_bawah = batas_bawah_transaksi,
batas_atas = batas_atas_transaksi
)## Q1.25% Q3.75% IQR batas_bawah.25% batas_atas.75%
## 3.250 7.000 3.750 -2.375 12.625
transaksi$outlier_jumlah_transaksi <-
transaksi$jumlah_transaksi < batas_bawah_transaksi |
transaksi$jumlah_transaksi > batas_atas_transaksi
transaksi[
transaksi$outlier_jumlah_transaksi,
c(
"cust_id",
"jumlah_transaksi"
)
]## cust_id jumlah_transaksi
## 7 C007 20
## 26 C027 25
Interpretasi: Kandidat outlier pada jumlah_transaksi dievaluasi terlebih dahulu. Karena tidak terdapat bukti bahwa nilai tersebut merupakan kesalahan pencatatan, nilai dipertahankan dalam dataset asli.
Pemeriksaan Outlier pada total_purchase
boxplot(
transaksi$total_purchase,
horizontal = TRUE,
main = "Boxplot Total Pembelian",
xlab = "Total Pembelian"
)q1_purchase <- quantile(
transaksi$total_purchase,
0.25
)
q3_purchase <- quantile(
transaksi$total_purchase,
0.75
)
iqr_purchase <- IQR(
transaksi$total_purchase
)
batas_bawah_purchase <- q1_purchase -
1.5 * iqr_purchase
batas_atas_purchase <- q3_purchase +
1.5 * iqr_purchase
c(
Q1 = q1_purchase,
Q3 = q3_purchase,
IQR = iqr_purchase,
batas_bawah = batas_bawah_purchase,
batas_atas = batas_atas_purchase
)## Q1.25% Q3.75% IQR batas_bawah.25% batas_atas.75%
## 1012500 2700000 1687500 -1518750 5231250
transaksi$outlier_total_purchase <-
transaksi$total_purchase < batas_bawah_purchase |
transaksi$total_purchase > batas_atas_purchase
transaksi[
transaksi$outlier_total_purchase,
c(
"cust_id",
"total_purchase"
)
]## cust_id total_purchase
## 7 C007 2.5e+07
## 24 C025 3.0e+07
Interpretasi: Nilai ekstrem pada total_purchase tidak langsung dihapus karena belum terdapat informasi yang menunjukkan bahwa nilai tersebut merupakan kesalahan. Nilai dipertahankan sebagai bagian dari data transaksi yang sebenarnya.
Bagian V — Transformasi Data
Setelah proses data cleaning dan penanganan missing value dilakukan, atribut numerik perlu ditransformasikan agar memiliki skala yang lebih sesuai untuk analisis. Pada data ini, transformasi diterapkan pada atribut numerik dari data pelanggan dan data transaksi dengan menggunakan tiga metode, yaitu normalisasi min–maks, z-score, dan decimal scaling. Hasil dari masing-masing metode kemudian dibandingkan untuk melihat perubahan skala data.
Normalisasi Min–Maks
Normalisasi min–maks digunakan untuk mengubah nilai numerik ke dalam rentang 0 hingga 1. Transformasi ini dilakukan menggunakan data usia dan pendapatan yang telah melalui tahap penanganan missing value.
Data Pelanggan
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_imputasi",
"usia_minmax",
"pendapatan_imputasi",
"pendapatan_minmax"
)]## customer_id usia_imputasi usia_minmax pendapatan_imputasi pendapatan_minmax
## 1 C001 21.0 0.00000000 4.5e+06 0.0000000000
## 2 C002 25.0 0.26666667 5.1e+06 0.0012108981
## 3 C003 23.0 0.13333333 5.2e+06 0.0014127144
## 4 C004 27.5 0.43333333 4.8e+06 0.0006054490
## 5 C005 27.0 0.40000000 4.9e+06 0.0008072654
## 6 C006 27.5 0.43333333 5.1e+06 0.0012108981
## 7 C007 31.0 0.66666667 5.0e+08 1.0000000000
## 8 C008 29.0 0.53333333 4.7e+06 0.0004036327
## 9 C009 22.0 0.06666667 4.6e+06 0.0002018163
## 10 C010 35.0 0.93333333 5.3e+06 0.0016145308
## 11 C011 28.0 0.46666667 5.1e+06 0.0012108981
## 12 C012 24.0 0.20000000 4.8e+06 0.0006054490
## 13 C013 26.0 0.33333333 5.5e+06 0.0020181635
## 14 C014 30.0 0.60000000 5.1e+06 0.0012108981
## 15 C015 32.0 0.73333333 5.1e+06 0.0012108981
## 16 C016 27.0 0.40000000 4.9e+06 0.0008072654
## 17 C017 34.0 0.86666667 6.0e+06 0.0030272452
## 18 C018 23.0 0.13333333 4.7e+06 0.0004036327
## 19 C019 29.0 0.53333333 5.2e+06 0.0014127144
## 20 C020 27.5 0.43333333 5.1e+06 0.0012108981
## 21 C021 31.0 0.66666667 5.4e+06 0.0018163471
## 22 C022 28.0 0.46666667 5.0e+06 0.0010090817
## 23 C023 25.0 0.26666667 5.6e+06 0.0022199798
## 24 C024 33.0 0.80000000 4.8e+06 0.0006054490
## 25 C025 27.5 0.43333333 3.5e+08 0.6972754793
## 26 C026 22.0 0.06666667 4.5e+06 0.0000000000
## 27 C027 36.0 1.00000000 5.1e+06 0.0012108981
## 28 C028 27.0 0.40000000 5.1e+06 0.0012108981
Interpretasi: Normalisasi min–maks mengubah usia dan pendapatan ke skala yang sama, yaitu 0–1, tanpa mengubah urutan relatif antarobservasi. Metode ini memudahkan perbandingan atribut yang memiliki satuan dan rentang nilai berbeda.
Data Transaksi
Karena jumlah_transaksi dan total_purchase tidak memiliki missing value, kedua atribut dapat langsung ditransformasikan.
transaksi$jumlah_transaksi_minmax <- minmax(
transaksi$jumlah_transaksi
)
transaksi$total_purchase_minmax <- minmax(
transaksi$total_purchase
)transaksi[, c(
"cust_id",
"jumlah_transaksi",
"jumlah_transaksi_minmax",
"total_purchase",
"total_purchase_minmax"
)]## cust_id jumlah_transaksi jumlah_transaksi_minmax total_purchase
## 1 C001 5 0.16666667 1.5e+06
## 2 C002 3 0.08333333 9.0e+05
## 3 C003 7 0.25000000 2.7e+06
## 4 C004 2 0.04166667 6.0e+05
## 5 C005 6 0.20833333 2.1e+06
## 6 C006 4 0.12500000 1.3e+06
## 7 C007 20 0.79166667 2.5e+07
## 8 C008 5 0.16666667 1.7e+06
## 9 C009 3 0.08333333 8.0e+05
## 10 C010 8 0.29166667 3.2e+06
## 11 C012 1 0.00000000 2.5e+05
## 12 C013 4 0.12500000 1.2e+06
## 13 C014 6 0.20833333 2.4e+06
## 14 C015 5 0.16666667 1.8e+06
## 15 C016 9 0.33333333 3.5e+06
## 16 C017 3 0.08333333 9.0e+05
## 17 C018 7 0.25000000 2.8e+06
## 18 C019 2 0.04166667 7.0e+05
## 19 C020 8 0.29166667 3.1e+06
## 20 C021 4 0.12500000 1.5e+06
## 21 C022 6 0.20833333 2.2e+06
## 22 C023 5 0.16666667 1.9e+06
## 23 C024 10 0.37500000 4.2e+06
## 24 C025 3 0.08333333 3.0e+07
## 25 C026 7 0.25000000 1.3e+06
## 26 C027 25 1.00000000 2.7e+06
## 27 C028 4 0.12500000 9.5e+05
## 28 C029 6 0.20833333 2.1e+06
## 29 C030 2 0.04166667 6.0e+05
## 30 C031 5 0.16666667 1.6e+06
## total_purchase_minmax
## 1 0.04201681
## 2 0.02184874
## 3 0.08235294
## 4 0.01176471
## 5 0.06218487
## 6 0.03529412
## 7 0.83193277
## 8 0.04873950
## 9 0.01848739
## 10 0.09915966
## 11 0.00000000
## 12 0.03193277
## 13 0.07226891
## 14 0.05210084
## 15 0.10924370
## 16 0.02184874
## 17 0.08571429
## 18 0.01512605
## 19 0.09579832
## 20 0.04201681
## 21 0.06554622
## 22 0.05546218
## 23 0.13277311
## 24 1.00000000
## 25 0.03529412
## 26 0.08235294
## 27 0.02352941
## 28 0.06218487
## 29 0.01176471
## 30 0.04537815
Interpretasi: Normalisasi min–maks mengubah jumlah transaksi dan total pembelian ke rentang 0–1. Dengan demikian, kedua atribut transaksi dapat dibandingkan tanpa dipengaruhi oleh perbedaan satuan dan besar nilai awal.
Normalisasi Z-Score
Selain min–maks, dilakukan normalisasi z-score untuk menunjukkan posisi setiap nilai terhadap rata-rata atribut dalam satuan simpangan baku.
Data Pelanggan
pelanggan$usia_z <- as.numeric(
scale(pelanggan$usia_imputasi)
)
pelanggan$pendapatan_z <- as.numeric(
scale(pelanggan$pendapatan_imputasi)
)hasil_zscore <- pelanggan[, c(
"customer_id",
"usia_z",
"pendapatan_z"
)]
hasil_zscore$usia_z <- round(hasil_zscore$usia_z, 3)
hasil_zscore$pendapatan_z <- round(hasil_zscore$pendapatan_z, 3)
hasil_zscore## customer_id usia_z pendapatan_z
## 1 C001 -1.709 -0.273
## 2 C002 -0.702 -0.267
## 3 C003 -1.205 -0.266
## 4 C004 -0.072 -0.270
## 5 C005 -0.198 -0.269
## 6 C006 -0.072 -0.267
## 7 C007 0.809 4.151
## 8 C008 0.306 -0.271
## 9 C009 -1.457 -0.272
## 10 C010 1.817 -0.266
## 11 C011 0.054 -0.267
## 12 C012 -0.953 -0.270
## 13 C013 -0.450 -0.264
## 14 C014 0.558 -0.267
## 15 C015 1.061 -0.267
## 16 C016 -0.198 -0.269
## 17 C017 1.565 -0.259
## 18 C018 -1.205 -0.271
## 19 C019 0.306 -0.266
## 20 C020 -0.072 -0.267
## 21 C021 0.809 -0.265
## 22 C022 0.054 -0.268
## 23 C023 -0.702 -0.263
## 24 C024 1.313 -0.270
## 25 C025 -0.072 2.812
## 26 C026 -1.457 -0.273
## 27 C027 2.069 -0.267
## 28 C028 -0.198 -0.267
Interpretasi: Nilai z-score menunjukkan seberapa jauh suatu observasi berada dari rata-rata atributnya. Nilai positif menunjukkan posisi di atas rata-rata, sedangkan nilai negatif menunjukkan posisi di bawah rata-rata.
Data Transaksi
transaksi$jumlah_transaksi_z <- as.numeric(
scale(transaksi$jumlah_transaksi)
)
transaksi$total_purchase_z <- as.numeric(
scale(transaksi$total_purchase)
)## jumlah_transaksi_z total_purchase_z
## 1 -0.234 -0.305
## 2 -0.635 -0.395
## 3 0.167 -0.123
## 4 -0.835 -0.440
## 5 -0.033 -0.214
## 6 -0.434 -0.335
## 7 2.772 3.244
## 8 -0.234 -0.274
## 9 -0.635 -0.410
## 10 0.367 -0.048
## 11 -1.035 -0.493
## 12 -0.434 -0.350
## 13 -0.033 -0.169
## 14 -0.234 -0.259
## 15 0.568 -0.003
## 16 -0.635 -0.395
## 17 0.167 -0.108
## 18 -0.835 -0.425
## 19 0.367 -0.063
## 20 -0.434 -0.305
## 21 -0.033 -0.199
## 22 -0.234 -0.244
## 23 0.768 0.103
## 24 -0.635 3.999
## 25 0.167 -0.335
## 26 3.774 -0.123
## 27 -0.434 -0.388
## 28 -0.033 -0.214
## 29 -0.835 -0.440
## 30 -0.234 -0.289
Interpretasi: Hasil z-score menunjukkan posisi jumlah transaksi dan total pembelian relatif terhadap rata-rata masing-masing atribut. Nilai yang semakin positif menunjukkan nilai yang semakin tinggi dibandingkan rata-ratanya.
Decimal Scaling
Decimal scaling dilakukan dengan memindahkan posisi desimal berdasarkan besar nilai maksimum absolut sehingga skala data menjadi lebih kecil.
decimal_scale <- function(x) {
maks <- max(abs(x), na.rm = TRUE)
if (maks == 0) return(x)
j <- ceiling(log10(maks + 1))
x / (10 ^ j)
}Data Pelanggan
pelanggan$usia_decimal <-
decimal_scale(pelanggan$usia_imputasi)
pelanggan$pendapatan_decimal <-
decimal_scale(pelanggan$pendapatan_imputasi)pelanggan[, c(
"customer_id",
"usia_imputasi",
"usia_decimal",
"pendapatan_imputasi",
"pendapatan_decimal"
)]## customer_id usia_imputasi usia_decimal pendapatan_imputasi
## 1 C001 21.0 0.210 4.5e+06
## 2 C002 25.0 0.250 5.1e+06
## 3 C003 23.0 0.230 5.2e+06
## 4 C004 27.5 0.275 4.8e+06
## 5 C005 27.0 0.270 4.9e+06
## 6 C006 27.5 0.275 5.1e+06
## 7 C007 31.0 0.310 5.0e+08
## 8 C008 29.0 0.290 4.7e+06
## 9 C009 22.0 0.220 4.6e+06
## 10 C010 35.0 0.350 5.3e+06
## 11 C011 28.0 0.280 5.1e+06
## 12 C012 24.0 0.240 4.8e+06
## 13 C013 26.0 0.260 5.5e+06
## 14 C014 30.0 0.300 5.1e+06
## 15 C015 32.0 0.320 5.1e+06
## 16 C016 27.0 0.270 4.9e+06
## 17 C017 34.0 0.340 6.0e+06
## 18 C018 23.0 0.230 4.7e+06
## 19 C019 29.0 0.290 5.2e+06
## 20 C020 27.5 0.275 5.1e+06
## 21 C021 31.0 0.310 5.4e+06
## 22 C022 28.0 0.280 5.0e+06
## 23 C023 25.0 0.250 5.6e+06
## 24 C024 33.0 0.330 4.8e+06
## 25 C025 27.5 0.275 3.5e+08
## 26 C026 22.0 0.220 4.5e+06
## 27 C027 36.0 0.360 5.1e+06
## 28 C028 27.0 0.270 5.1e+06
## pendapatan_decimal
## 1 0.0045
## 2 0.0051
## 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.0051
## 12 0.0048
## 13 0.0055
## 14 0.0051
## 15 0.0051
## 16 0.0049
## 17 0.0060
## 18 0.0047
## 19 0.0052
## 20 0.0051
## 21 0.0054
## 22 0.0050
## 23 0.0056
## 24 0.0048
## 25 0.3500
## 26 0.0045
## 27 0.0051
## 28 0.0051
Interpretasi: Decimal scaling mengecilkan nilai usia dan pendapatan dengan membaginya menggunakan pangkat 10 tertentu, tetapi tetap mempertahankan perbandingan antarobservasi.
Data Transaksi
transaksi$jumlah_transaksi_decimal <-
decimal_scale(transaksi$jumlah_transaksi)
transaksi$total_purchase_decimal <-
decimal_scale(transaksi$total_purchase)transaksi[, c(
"cust_id",
"jumlah_transaksi",
"jumlah_transaksi_decimal",
"total_purchase",
"total_purchase_decimal"
)]## cust_id jumlah_transaksi jumlah_transaksi_decimal total_purchase
## 1 C001 5 0.05 1.5e+06
## 2 C002 3 0.03 9.0e+05
## 3 C003 7 0.07 2.7e+06
## 4 C004 2 0.02 6.0e+05
## 5 C005 6 0.06 2.1e+06
## 6 C006 4 0.04 1.3e+06
## 7 C007 20 0.20 2.5e+07
## 8 C008 5 0.05 1.7e+06
## 9 C009 3 0.03 8.0e+05
## 10 C010 8 0.08 3.2e+06
## 11 C012 1 0.01 2.5e+05
## 12 C013 4 0.04 1.2e+06
## 13 C014 6 0.06 2.4e+06
## 14 C015 5 0.05 1.8e+06
## 15 C016 9 0.09 3.5e+06
## 16 C017 3 0.03 9.0e+05
## 17 C018 7 0.07 2.8e+06
## 18 C019 2 0.02 7.0e+05
## 19 C020 8 0.08 3.1e+06
## 20 C021 4 0.04 1.5e+06
## 21 C022 6 0.06 2.2e+06
## 22 C023 5 0.05 1.9e+06
## 23 C024 10 0.10 4.2e+06
## 24 C025 3 0.03 3.0e+07
## 25 C026 7 0.07 1.3e+06
## 26 C027 25 0.25 2.7e+06
## 27 C028 4 0.04 9.5e+05
## 28 C029 6 0.06 2.1e+06
## 29 C030 2 0.02 6.0e+05
## 30 C031 5 0.05 1.6e+06
## total_purchase_decimal
## 1 0.0150
## 2 0.0090
## 3 0.0270
## 4 0.0060
## 5 0.0210
## 6 0.0130
## 7 0.2500
## 8 0.0170
## 9 0.0080
## 10 0.0320
## 11 0.0025
## 12 0.0120
## 13 0.0240
## 14 0.0180
## 15 0.0350
## 16 0.0090
## 17 0.0280
## 18 0.0070
## 19 0.0310
## 20 0.0150
## 21 0.0220
## 22 0.0190
## 23 0.0420
## 24 0.3000
## 25 0.0130
## 26 0.0270
## 27 0.0095
## 28 0.0210
## 29 0.0060
## 30 0.0160
Interpretasi: Decimal scaling mengurangi besar angka pada atribut transaksi tanpa mengubah hubungan relatif antarobservasi. Metode ini menghasilkan nilai dengan skala yang lebih kecil sehingga lebih mudah digunakan dalam proses analisis tertentu.
Membandingkan Hasil Transformasi
Untuk melihat perbedaan skala yang dihasilkan oleh ketiga metode, hasil transformasi pendapatan dan total pembelian dapat dibandingkan.
Perbandingan Data Pelanggan
transformasi_pelanggan <- pelanggan[, c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_minmax",
"pendapatan_z",
"pendapatan_decimal"
)]
transformasi_pelanggan## customer_id pendapatan_imputasi pendapatan_minmax pendapatan_z
## 1 C001 4.5e+06 0.0000000000 -0.2726667
## 2 C002 5.1e+06 0.0012108981 -0.2673103
## 3 C003 5.2e+06 0.0014127144 -0.2664175
## 4 C004 4.8e+06 0.0006054490 -0.2699885
## 5 C005 4.9e+06 0.0008072654 -0.2690957
## 6 C006 5.1e+06 0.0012108981 -0.2673103
## 7 C007 5.0e+08 1.0000000000 4.1508335
## 8 C008 4.7e+06 0.0004036327 -0.2708812
## 9 C009 4.6e+06 0.0002018163 -0.2717739
## 10 C010 5.3e+06 0.0016145308 -0.2655248
## 11 C011 5.1e+06 0.0012108981 -0.2673103
## 12 C012 4.8e+06 0.0006054490 -0.2699885
## 13 C013 5.5e+06 0.0020181635 -0.2637393
## 14 C014 5.1e+06 0.0012108981 -0.2673103
## 15 C015 5.1e+06 0.0012108981 -0.2673103
## 16 C016 4.9e+06 0.0008072654 -0.2690957
## 17 C017 6.0e+06 0.0030272452 -0.2592756
## 18 C018 4.7e+06 0.0004036327 -0.2708812
## 19 C019 5.2e+06 0.0014127144 -0.2664175
## 20 C020 5.1e+06 0.0012108981 -0.2673103
## 21 C021 5.4e+06 0.0018163471 -0.2646321
## 22 C022 5.0e+06 0.0010090817 -0.2682030
## 23 C023 5.6e+06 0.0022199798 -0.2628466
## 24 C024 4.8e+06 0.0006054490 -0.2699885
## 25 C025 3.5e+08 0.6972754793 2.8117316
## 26 C026 4.5e+06 0.0000000000 -0.2726667
## 27 C027 5.1e+06 0.0012108981 -0.2673103
## 28 C028 5.1e+06 0.0012108981 -0.2673103
## pendapatan_decimal
## 1 0.0045
## 2 0.0051
## 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.0051
## 12 0.0048
## 13 0.0055
## 14 0.0051
## 15 0.0051
## 16 0.0049
## 17 0.0060
## 18 0.0047
## 19 0.0052
## 20 0.0051
## 21 0.0054
## 22 0.0050
## 23 0.0056
## 24 0.0048
## 25 0.3500
## 26 0.0045
## 27 0.0051
## 28 0.0051
Perbandingan Data Transaksi
transformasi_transaksi <- transaksi[, c(
"cust_id",
"total_purchase",
"total_purchase_minmax",
"total_purchase_z",
"total_purchase_decimal"
)]
transformasi_transaksi## cust_id total_purchase total_purchase_minmax total_purchase_z
## 1 C001 1.5e+06 0.04201681 -0.304546285
## 2 C002 9.0e+05 0.02184874 -0.395155097
## 3 C003 2.7e+06 0.08235294 -0.123328661
## 4 C004 6.0e+05 0.01176471 -0.440459502
## 5 C005 2.1e+06 0.06218487 -0.213937473
## 6 C006 1.3e+06 0.03529412 -0.334749222
## 7 C007 2.5e+07 0.83193277 3.244298850
## 8 C008 1.7e+06 0.04873950 -0.274343347
## 9 C009 8.0e+05 0.01848739 -0.410256565
## 10 C010 3.2e+06 0.09915966 -0.047821317
## 11 C012 2.5e+05 0.00000000 -0.493314643
## 12 C013 1.2e+06 0.03193277 -0.349850691
## 13 C014 2.4e+06 0.07226891 -0.168633067
## 14 C015 1.8e+06 0.05210084 -0.259241879
## 15 C016 3.5e+06 0.10924370 -0.002516911
## 16 C017 9.0e+05 0.02184874 -0.395155097
## 17 C018 2.8e+06 0.08571429 -0.108227192
## 18 C019 7.0e+05 0.01512605 -0.425358034
## 19 C020 3.1e+06 0.09579832 -0.062922786
## 20 C021 1.5e+06 0.04201681 -0.304546285
## 21 C022 2.2e+06 0.06554622 -0.198836004
## 22 C023 1.9e+06 0.05546218 -0.244140410
## 23 C024 4.2e+06 0.13277311 0.103193369
## 24 C025 3.0e+07 1.00000000 3.999372282
## 25 C026 1.3e+06 0.03529412 -0.334749222
## 26 C027 2.7e+06 0.08235294 -0.123328661
## 27 C028 9.5e+05 0.02352941 -0.387604362
## 28 C029 2.1e+06 0.06218487 -0.213937473
## 29 C030 6.0e+05 0.01176471 -0.440459502
## 30 C031 1.6e+06 0.04537815 -0.289444816
## total_purchase_decimal
## 1 0.0150
## 2 0.0090
## 3 0.0270
## 4 0.0060
## 5 0.0210
## 6 0.0130
## 7 0.2500
## 8 0.0170
## 9 0.0080
## 10 0.0320
## 11 0.0025
## 12 0.0120
## 13 0.0240
## 14 0.0180
## 15 0.0350
## 16 0.0090
## 17 0.0280
## 18 0.0070
## 19 0.0310
## 20 0.0150
## 21 0.0220
## 22 0.0190
## 23 0.0420
## 24 0.3000
## 25 0.0130
## 26 0.0270
## 27 0.0095
## 28 0.0210
## 29 0.0060
## 30 0.0160
Interpretasi: Ketiga metode menghasilkan skala yang berbeda, tetapi informasi urutan nilai tetap dipertahankan. Pemilihan metode transformasi selanjutnya dapat disesuaikan dengan kebutuhan analisis yang akan dilakukan.
Dampak Outlier Terhadap Transformasi
Pada tahap sebelumnya ditemukan nilai ekstrem pada atribut pendapatan pelanggan dan beberapa nilai ekstrem pada atribut transaksi. Nilai tersebut tidak langsung dihapus karena belum terdapat bukti bahwa nilai tersebut merupakan kesalahan pencatatan.
Oleh karena itu, pengaruh outlier terhadap normalisasi min–maks dapat dibandingkan menggunakan data yang telah melalui winsorization.
Data Pelanggan
pelanggan[, c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_minmax",
"pendapatan_winsor",
"pendapatan_winsor_minmax"
)]## customer_id pendapatan_imputasi pendapatan_minmax pendapatan_winsor
## 1 C001 4.5e+06 0.0000000000 4500000
## 2 C002 5.1e+06 0.0012108981 5100000
## 3 C003 5.2e+06 0.0014127144 5200000
## 4 C004 4.8e+06 0.0006054490 4800000
## 5 C005 4.9e+06 0.0008072654 4900000
## 6 C006 5.1e+06 0.0012108981 5100000
## 7 C007 5.0e+08 1.0000000000 5862500
## 8 C008 4.7e+06 0.0004036327 4700000
## 9 C009 4.6e+06 0.0002018163 4600000
## 10 C010 5.3e+06 0.0016145308 5300000
## 11 C011 5.1e+06 0.0012108981 5100000
## 12 C012 4.8e+06 0.0006054490 4800000
## 13 C013 5.5e+06 0.0020181635 5500000
## 14 C014 5.1e+06 0.0012108981 5100000
## 15 C015 5.1e+06 0.0012108981 5100000
## 16 C016 4.9e+06 0.0008072654 4900000
## 17 C017 6.0e+06 0.0030272452 5862500
## 18 C018 4.7e+06 0.0004036327 4700000
## 19 C019 5.2e+06 0.0014127144 5200000
## 20 C020 5.1e+06 0.0012108981 5100000
## 21 C021 5.4e+06 0.0018163471 5400000
## 22 C022 5.0e+06 0.0010090817 5000000
## 23 C023 5.6e+06 0.0022199798 5600000
## 24 C024 4.8e+06 0.0006054490 4800000
## 25 C025 3.5e+08 0.6972754793 5862500
## 26 C026 4.5e+06 0.0000000000 4500000
## 27 C027 5.1e+06 0.0012108981 5100000
## 28 C028 5.1e+06 0.0012108981 5100000
## pendapatan_winsor_minmax
## 1 0.0000000
## 2 0.4403670
## 3 0.5137615
## 4 0.2201835
## 5 0.2935780
## 6 0.4403670
## 7 1.0000000
## 8 0.1467890
## 9 0.0733945
## 10 0.5871560
## 11 0.4403670
## 12 0.2201835
## 13 0.7339450
## 14 0.4403670
## 15 0.4403670
## 16 0.2935780
## 17 1.0000000
## 18 0.1467890
## 19 0.5137615
## 20 0.4403670
## 21 0.6605505
## 22 0.3669725
## 23 0.8073394
## 24 0.2201835
## 25 1.0000000
## 26 0.0000000
## 27 0.4403670
## 28 0.4403670
plot(
pelanggan$pendapatan_minmax,
pelanggan$pendapatan_winsor_minmax,
pch = 19,
xlab = "Min–Maks Pendapatan",
ylab = "Min–Maks Setelah Winsorization",
main = "Perbandingan Normalisasi Sebelum dan Sesudah Winsorization"
)
abline(0, 1, lty = 2)Interpretasi: Perbandingan menunjukkan bahwa nilai ekstrem pada pendapatan dapat memengaruhi rentang hasil normalisasi min–maks. Winsorization dapat digunakan sebagai pembanding untuk melihat bagaimana pembatasan nilai ekstrem memengaruhi hasil transformasi.
Data Transaksi
Pada data transaksi, nilai ekstrem juga ditemukan pada jumlah_transaksi dan total_purchase. Namun, nilai tersebut tidak langsung diubah atau dihapus, karena nilai transaksi yang besar masih dapat merupakan transaksi yang valid.
Untuk melihat pengaruhnya terhadap normalisasi, dapat dibuat versi winsorized sebagai pembanding:
q1_jumlah <- quantile(transaksi$jumlah_transaksi, 0.25)
q3_jumlah <- quantile(transaksi$jumlah_transaksi, 0.75)
iqr_jumlah <- IQR(transaksi$jumlah_transaksi)
batas_atas_jumlah <- q3_jumlah + 1.5 * iqr_jumlah
transaksi$jumlah_transaksi_winsor <- pmin(
transaksi$jumlah_transaksi,
batas_atas_jumlah
)q1_purchase <- quantile(transaksi$total_purchase, 0.25)
q3_purchase <- quantile(transaksi$total_purchase, 0.75)
iqr_purchase <- IQR(transaksi$total_purchase)
batas_atas_purchase <- q3_purchase + 1.5 * iqr_purchase
transaksi$total_purchase_winsor <- pmin(
transaksi$total_purchase,
batas_atas_purchase
)transaksi$jumlah_transaksi_winsor_minmax <-
minmax(transaksi$jumlah_transaksi_winsor)
transaksi$total_purchase_winsor_minmax <-
minmax(transaksi$total_purchase_winsor)transaksi[, c(
"cust_id",
"jumlah_transaksi",
"jumlah_transaksi_minmax",
"jumlah_transaksi_winsor",
"jumlah_transaksi_winsor_minmax",
"total_purchase",
"total_purchase_minmax",
"total_purchase_winsor",
"total_purchase_winsor_minmax"
)]## cust_id jumlah_transaksi jumlah_transaksi_minmax jumlah_transaksi_winsor
## 1 C001 5 0.16666667 5.000
## 2 C002 3 0.08333333 3.000
## 3 C003 7 0.25000000 7.000
## 4 C004 2 0.04166667 2.000
## 5 C005 6 0.20833333 6.000
## 6 C006 4 0.12500000 4.000
## 7 C007 20 0.79166667 12.625
## 8 C008 5 0.16666667 5.000
## 9 C009 3 0.08333333 3.000
## 10 C010 8 0.29166667 8.000
## 11 C012 1 0.00000000 1.000
## 12 C013 4 0.12500000 4.000
## 13 C014 6 0.20833333 6.000
## 14 C015 5 0.16666667 5.000
## 15 C016 9 0.33333333 9.000
## 16 C017 3 0.08333333 3.000
## 17 C018 7 0.25000000 7.000
## 18 C019 2 0.04166667 2.000
## 19 C020 8 0.29166667 8.000
## 20 C021 4 0.12500000 4.000
## 21 C022 6 0.20833333 6.000
## 22 C023 5 0.16666667 5.000
## 23 C024 10 0.37500000 10.000
## 24 C025 3 0.08333333 3.000
## 25 C026 7 0.25000000 7.000
## 26 C027 25 1.00000000 12.625
## 27 C028 4 0.12500000 4.000
## 28 C029 6 0.20833333 6.000
## 29 C030 2 0.04166667 2.000
## 30 C031 5 0.16666667 5.000
## jumlah_transaksi_winsor_minmax total_purchase total_purchase_minmax
## 1 0.34408602 1.5e+06 0.04201681
## 2 0.17204301 9.0e+05 0.02184874
## 3 0.51612903 2.7e+06 0.08235294
## 4 0.08602151 6.0e+05 0.01176471
## 5 0.43010753 2.1e+06 0.06218487
## 6 0.25806452 1.3e+06 0.03529412
## 7 1.00000000 2.5e+07 0.83193277
## 8 0.34408602 1.7e+06 0.04873950
## 9 0.17204301 8.0e+05 0.01848739
## 10 0.60215054 3.2e+06 0.09915966
## 11 0.00000000 2.5e+05 0.00000000
## 12 0.25806452 1.2e+06 0.03193277
## 13 0.43010753 2.4e+06 0.07226891
## 14 0.34408602 1.8e+06 0.05210084
## 15 0.68817204 3.5e+06 0.10924370
## 16 0.17204301 9.0e+05 0.02184874
## 17 0.51612903 2.8e+06 0.08571429
## 18 0.08602151 7.0e+05 0.01512605
## 19 0.60215054 3.1e+06 0.09579832
## 20 0.25806452 1.5e+06 0.04201681
## 21 0.43010753 2.2e+06 0.06554622
## 22 0.34408602 1.9e+06 0.05546218
## 23 0.77419355 4.2e+06 0.13277311
## 24 0.17204301 3.0e+07 1.00000000
## 25 0.51612903 1.3e+06 0.03529412
## 26 1.00000000 2.7e+06 0.08235294
## 27 0.25806452 9.5e+05 0.02352941
## 28 0.43010753 2.1e+06 0.06218487
## 29 0.08602151 6.0e+05 0.01176471
## 30 0.34408602 1.6e+06 0.04537815
## total_purchase_winsor total_purchase_winsor_minmax
## 1 1500000 0.25094103
## 2 900000 0.13048934
## 3 2700000 0.49184442
## 4 600000 0.07026349
## 5 2100000 0.37139272
## 6 1300000 0.21079046
## 7 5231250 1.00000000
## 8 1700000 0.29109159
## 9 800000 0.11041405
## 10 3200000 0.59222083
## 11 250000 0.00000000
## 12 1200000 0.19071518
## 13 2400000 0.43161857
## 14 1800000 0.31116688
## 15 3500000 0.65244668
## 16 900000 0.13048934
## 17 2800000 0.51191970
## 18 700000 0.09033877
## 19 3100000 0.57214555
## 20 1500000 0.25094103
## 21 2200000 0.39146801
## 22 1900000 0.33124216
## 23 4200000 0.79297365
## 24 5231250 1.00000000
## 25 1300000 0.21079046
## 26 2700000 0.49184442
## 27 950000 0.14052698
## 28 2100000 0.37139272
## 29 600000 0.07026349
## 30 1600000 0.27101631
Interpretasi: Perbandingan ini menunjukkan seberapa besar nilai ekstrem pada transaksi memengaruhi hasil normalisasi. Data winsorized hanya digunakan sebagai pembanding, sedangkan data transaksi asli tetap dipertahankan karena belum terdapat bukti bahwa nilai ekstrem tersebut merupakan kesalahan.
Untuk data transaksi, winsorization tidak harus digunakan sebagai data final. Tujuannya di sini adalah menunjukkan bahwa keputusan penanganan outlier perlu mempertimbangkan konteks data, bukan hanya berdasarkan hasil deteksi statistik.
Bagian VI — Integrasi Data
Setelah masing-masing sumber data diperiksa dan dibersihkan, tahap berikutnya adalah menggabungkan data pelanggan dengan data transaksi. Integrasi dilakukan berdasarkan identifier pelanggan agar informasi karakteristik pelanggan dapat dihubungkan dengan informasi transaksinya.
Memeriksa Kunci pada Kedua Sumber Data
Pada data pelanggan, identifier yang digunakan adalah customer_id, sedangkan pada data transaksi digunakan cust_id. Sebelum dilakukan penggabungan, kedua kolom tersebut perlu diperiksa untuk memastikan keunikan dan kesesuaian identitas pelanggan.
## [1] 0
## [1] 0
Interpretasi: Hasil pemeriksaan menunjukkan bahwa customer_id pada data pelanggan telah dibuat unik setelah proses deduplikasi, sedangkan cust_id pada data transaksi juga tidak memiliki duplikasi. Kondisi ini memungkinkan kedua data dihubungkan berdasarkan identifier pelanggan.
Memeriksa Perbedaan Identifier
Karena nama identifier pada kedua sumber berbeda, dilakukan pemeriksaan terhadap ID yang hanya terdapat pada salah satu dataset.
## [1] "C011"
## [1] "C029" "C030" "C031"
Interpretasi: Hasil setdiff() menunjukkan adanya perbedaan cakupan pelanggan antara kedua sumber data. Beberapa pelanggan pada data pelanggan tidak memiliki catatan transaksi, sedangkan terdapat pula ID transaksi yang tidak memiliki pasangan pada data pelanggan.
Menyelaraskan Nama Identifier
Agar kedua sumber data memiliki nama kunci yang sama, cust_id pada data transaksi diubah menjadi customer_id.
## [1] "customer_id" "jumlah_transaksi"
## [3] "total_purchase" "outlier_jumlah_transaksi"
## [5] "outlier_total_purchase" "jumlah_transaksi_minmax"
## [7] "total_purchase_minmax" "jumlah_transaksi_z"
## [9] "total_purchase_z" "jumlah_transaksi_decimal"
## [11] "total_purchase_decimal" "jumlah_transaksi_winsor"
## [13] "total_purchase_winsor" "jumlah_transaksi_winsor_minmax"
## [15] "total_purchase_winsor_minmax"
Interpretasi: Setelah nama identifier diseragamkan, kedua dataset memiliki kolom kunci dengan nama customer_id, sehingga proses integrasi dapat dilakukan dengan lebih mudah.
Mengintegrasikan Data Pelanggan dan Transaksi
Karena tujuan integrasi adalah mempertahankan seluruh pelanggan yang telah dibersihkan, digunakan left join melalui fungsi merge().
data_terintegrasi[, c(
"customer_id",
"nama",
"usia_imputasi",
"pendapatan_imputasi",
"kota_imputasi",
"status",
"jumlah_transaksi",
"total_purchase"
)]## customer_id nama usia_imputasi pendapatan_imputasi kota_imputasi
## 1 C001 Ani 21.0 4.5e+06 Pekanbaru
## 2 C002 Budi 25.0 5.1e+06 Pekanbaru
## 3 C003 Citra 23.0 5.2e+06 Pekanbaru
## 4 C004 Dodi 27.5 4.8e+06 Dumai
## 5 C005 Eka 27.0 4.9e+06 Pekanbaru
## 6 C006 Fani 27.5 5.1e+06 Dumai
## 7 C007 Gilang 31.0 5.0e+08 Pekanbaru
## 8 C008 Hana 29.0 4.7e+06 Siak
## 9 C009 Indra 22.0 4.6e+06 Pekanbaru
## 10 C010 Joko 35.0 5.3e+06 Dumai
## 11 C011 Kiki 28.0 5.1e+06 Tidak diketahui
## 12 C012 Lina 24.0 4.8e+06 Pekanbaru
## 13 C013 Maya 26.0 5.5e+06 Pekanbaru
## 14 C014 Nanda 30.0 5.1e+06 Pekanbaru
## 15 C015 Oki 32.0 5.1e+06 Dumai
## 16 C016 Putri 27.0 4.9e+06 Siak
## 17 C017 Raka 34.0 6.0e+06 Pekanbaru
## 18 C018 Salsa 23.0 4.7e+06 Pekanbaru
## 19 C019 Tio 29.0 5.2e+06 Dumai
## 20 C020 Uli 27.5 5.1e+06 Pekanbaru
## 21 C021 Vina 31.0 5.4e+06 Pekanbaru
## 22 C022 Wawan 28.0 5.0e+06 Pekanbaru
## 23 C023 Yani 25.0 5.6e+06 Dumai
## 24 C024 Zaki 33.0 4.8e+06 Siak
## 25 C025 Aldi 27.5 3.5e+08 Tidak diketahui
## 26 C026 Bella 22.0 4.5e+06 Pekanbaru
## 27 C027 Caca 36.0 5.1e+06 Dumai
## 28 C028 Dian 27.0 5.1e+06 Pekanbaru
## status jumlah_transaksi total_purchase
## 1 Aktif 5 1.5e+06
## 2 Aktif 3 9.0e+05
## 3 Aktif 7 2.7e+06
## 4 Aktif 2 6.0e+05
## 5 Tidak Aktif 6 2.1e+06
## 6 Tidak Aktif 4 1.3e+06
## 7 Aktif 20 2.5e+07
## 8 Aktif 5 1.7e+06
## 9 Aktif 3 8.0e+05
## 10 Tidak Aktif 8 3.2e+06
## 11 Aktif NA NA
## 12 Aktif 1 2.5e+05
## 13 Aktif 4 1.2e+06
## 14 Aktif 6 2.4e+06
## 15 Tidak Aktif 5 1.8e+06
## 16 Aktif 9 3.5e+06
## 17 Aktif 3 9.0e+05
## 18 Aktif 7 2.8e+06
## 19 Aktif 2 7.0e+05
## 20 Tidak Aktif 8 3.1e+06
## 21 Tidak Aktif 4 1.5e+06
## 22 Aktif 6 2.2e+06
## 23 Aktif 5 1.9e+06
## 24 Aktif 10 4.2e+06
## 25 Aktif 3 3.0e+07
## 26 Tidak Aktif 7 1.3e+06
## 27 Tidak Aktif 25 2.7e+06
## 28 Aktif 4 9.5e+05
Interpretasi: Data pelanggan menjadi tabel utama, sehingga seluruh pelanggan tetap dipertahankan meskipun tidak memiliki pasangan transaksi. Informasi transaksi akan terisi pada pelanggan yang memiliki customer_id yang sesuai.
Memvalidasi Hasil Integrasi
Setelah penggabungan dilakukan, hasilnya perlu diperiksa untuk memastikan tidak terjadi perubahan jumlah baris atau duplikasi identifier yang tidak diharapkan.
Membandingkan Jumlah Baris
## sebelum sesudah
## 28 28
Interpretasi: Jumlah baris setelah integrasi seharusnya tetap sama dengan jumlah pelanggan sebelum integrasi karena digunakan all.x = TRUE dan setiap customer_id pada data transaksi bersifat unik.
Memeriksa Kembali Keunikan Customer_id
## [1] 0
Interpretasi: Jika hasilnya 0, berarti tidak terdapat customer_id yang berulang setelah integrasi sehingga hubungan satu pelanggan dengan satu baris data tetap terjaga.
Memeriksa Missing Value Akibat Integrasi
## jumlah_transaksi total_purchase
## 1 1
Interpretasi: NA pada atribut transaksi setelah integrasi menunjukkan bahwa terdapat pelanggan yang tidak memiliki pasangan data transaksi. Kondisi ini berbeda dari missing value pada data pelanggan karena muncul akibat ketidaksesuaian identifier antar sumber.
Mengidentifikasi Pelanggan Tanpa Transaksi
## customer_id nama
## 11 C011 Kiki
Interpretasi: Hasil tersebut menunjukkan pelanggan yang tercatat dalam data pelanggan tetapi tidak memiliki pasangan pada data transaksi. Dalam dataset ini, kondisi tersebut perlu dipertahankan terlebih dahulu karena belum diketahui apakah pelanggan memang belum bertransaksi atau data transaksinya tidak tersedia.
Memeriksa Transaksi yang Tidak Memiliki Data Pelanggan
Karena pada pemeriksaan sebelumnya ditemukan C029, C030, dan C031 pada data transaksi tetapi tidak terdapat pada data pelanggan, kondisi tersebut juga perlu didokumentasikan.
## customer_id jumlah_transaksi total_purchase outlier_jumlah_transaksi
## 28 C029 6 2100000 FALSE
## 29 C030 2 600000 FALSE
## 30 C031 5 1600000 FALSE
## outlier_total_purchase jumlah_transaksi_minmax total_purchase_minmax
## 28 FALSE 0.20833333 0.06218487
## 29 FALSE 0.04166667 0.01176471
## 30 FALSE 0.16666667 0.04537815
## jumlah_transaksi_z total_purchase_z jumlah_transaksi_decimal
## 28 -0.03339866 -0.2139375 0.06
## 29 -0.83496647 -0.4404595 0.02
## 30 -0.23379061 -0.2894448 0.05
## total_purchase_decimal jumlah_transaksi_winsor total_purchase_winsor
## 28 0.021 6 2100000
## 29 0.006 2 600000
## 30 0.016 5 1600000
## jumlah_transaksi_winsor_minmax total_purchase_winsor_minmax
## 28 0.43010753 0.37139272
## 29 0.08602151 0.07026349
## 30 0.34408602 0.27101631
Interpretasi: Hasil tersebut menunjukkan adanya data transaksi yang tidak memiliki pasangan pada data pelanggan. Data tersebut tidak langsung dihapus karena perlu dipastikan terlebih dahulu apakah transaksi berasal dari pelanggan yang belum tercatat pada sumber data pelanggan atau terdapat kesalahan pada identifier.
Menentukan Penanganan NA pada Data Transaksi
Setelah data pelanggan dan data transaksi diintegrasikan, terdapat nilai NA pada atribut transaksi untuk pelanggan yang tidak memiliki pasangan data transaksi. Dalam dataset ini, kondisi tersebut diperlakukan sebagai tidak adanya catatan transaksi sehingga nilai NA diubah menjadi 0.
Pada tahap integrasi, nilai NA pada atribut transaksi diubah menjadi 0 untuk merepresentasikan pelanggan yang tidak memiliki catatan transaksi. Dengan demikian, atribut transaksi pada dataset akhir tidak lagi memiliki nilai NA.
Bagian VII — Dataset Akhir dan Evaluasi
Setelah seluruh tahapan data preprocessing dilakukan, data pelanggan dan transaksi yang telah dibersihkan kemudian digunakan untuk membentuk dataset akhir. Tahap ini bertujuan untuk memastikan bahwa hasil preprocessing telah sesuai dengan kebutuhan analisis dan tidak menimbulkan masalah baru pada struktur maupun kualitas data.
Menentukan Atribut pada Dataset Akhir
Dataset akhir memuat informasi utama pelanggan yang telah melalui proses preprocessing serta informasi transaksi yang berhasil dipadankan berdasarkan customer_id. Atribut hasil transformasi tetap dapat dipertahankan apabila diperlukan untuk analisis lanjutan.
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",
"total_purchase"
)]
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 5.1e+06
## 3 C003 Citra 23.0 Pekanbaru Aktif 5.2e+06
## 4 C004 Dodi 27.5 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 5.1e+06
## 12 C012 Lina 24.0 Pekanbaru Aktif 4.8e+06
## 13 C013 Maya 26.0 Pekanbaru Aktif 5.5e+06
## 14 C014 Nanda 30.0 Pekanbaru Aktif 5.1e+06
## 15 C015 Oki 32.0 Dumai Tidak Aktif 5.1e+06
## 16 C016 Putri 27.0 Siak Aktif 4.9e+06
## 17 C017 Raka 34.0 Pekanbaru Aktif 6.0e+06
## 18 C018 Salsa 23.0 Pekanbaru Aktif 4.7e+06
## 19 C019 Tio 29.0 Dumai Aktif 5.2e+06
## 20 C020 Uli 27.5 Pekanbaru Tidak Aktif 5.1e+06
## 21 C021 Vina 31.0 Pekanbaru Tidak Aktif 5.4e+06
## 22 C022 Wawan 28.0 Pekanbaru Aktif 5.0e+06
## 23 C023 Yani 25.0 Dumai Aktif 5.6e+06
## 24 C024 Zaki 33.0 Siak Aktif 4.8e+06
## 25 C025 Aldi 27.5 Tidak diketahui Aktif 3.5e+08
## 26 C026 Bella 22.0 Pekanbaru Tidak Aktif 4.5e+06
## 27 C027 Caca 36.0 Dumai Tidak Aktif 5.1e+06
## 28 C028 Dian 27.0 Pekanbaru Aktif 5.1e+06
## pendapatan_missing outlier_pendapatan usia_minmax pendapatan_minmax
## 1 0 FALSE 0.00000000 0.0000000000
## 2 1 FALSE 0.26666667 0.0012108981
## 3 0 FALSE 0.13333333 0.0014127144
## 4 0 FALSE 0.43333333 0.0006054490
## 5 0 FALSE 0.40000000 0.0008072654
## 6 0 FALSE 0.43333333 0.0012108981
## 7 0 TRUE 0.66666667 1.0000000000
## 8 0 FALSE 0.53333333 0.0004036327
## 9 0 FALSE 0.06666667 0.0002018163
## 10 0 FALSE 0.93333333 0.0016145308
## 11 1 FALSE 0.46666667 0.0012108981
## 12 0 FALSE 0.20000000 0.0006054490
## 13 0 FALSE 0.33333333 0.0020181635
## 14 1 FALSE 0.60000000 0.0012108981
## 15 0 FALSE 0.73333333 0.0012108981
## 16 0 FALSE 0.40000000 0.0008072654
## 17 0 TRUE 0.86666667 0.0030272452
## 18 0 FALSE 0.13333333 0.0004036327
## 19 0 FALSE 0.53333333 0.0014127144
## 20 1 FALSE 0.43333333 0.0012108981
## 21 0 FALSE 0.66666667 0.0018163471
## 22 0 FALSE 0.46666667 0.0010090817
## 23 0 FALSE 0.26666667 0.0022199798
## 24 0 FALSE 0.80000000 0.0006054490
## 25 0 TRUE 0.43333333 0.6972754793
## 26 0 FALSE 0.06666667 0.0000000000
## 27 1 FALSE 1.00000000 0.0012108981
## 28 0 FALSE 0.40000000 0.0012108981
## jumlah_transaksi total_purchase
## 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
## 12 1 2.5e+05
## 13 4 1.2e+06
## 14 6 2.4e+06
## 15 5 1.8e+06
## 16 9 3.5e+06
## 17 3 9.0e+05
## 18 7 2.8e+06
## 19 2 7.0e+05
## 20 8 3.1e+06
## 21 4 1.5e+06
## 22 6 2.2e+06
## 23 5 1.9e+06
## 24 10 4.2e+06
## 25 3 3.0e+07
## 26 7 1.3e+06
## 27 25 2.7e+06
## 28 4 9.5e+05
Interpretasi: Dataset akhir berisi atribut pelanggan yang telah dibersihkan dan ditangani missing value-nya, serta informasi transaksi yang berhasil dipadankan. Variabel indikator seperti pendapatan_missing dan outlier_pendapatan tetap dipertahankan untuk menunjukkan informasi yang berkaitan dengan proses preprocessing sebelumnya.
jumlah_transaksi (final) dan total_purchase (final) hanya diisi 0 apabila sebelumnya telah ditetapkan bahwa pelanggan tanpa pasangan transaksi memang berarti belum melakukan transaksi. Jika makna NA belum dapat dipastikan, sebaiknya nilai tersebut tetap dipertahankan sebagai NA.
Melakukan Audit Akhir
Audit akhir dilakukan untuk memastikan kondisi dataset setelah seluruh tahapan preprocessing selesai. Pemeriksaan meliputi struktur atribut, missing values, dan keunikan customer_id.
## atribut tipe jumlah_missing persen_missing jumlah_unik
## 1 customer_id character 0 0 28
## 2 nama character 0 0 28
## 3 usia numeric 0 0 17
## 4 kota character 0 0 4
## 5 status character 0 0 2
## 6 pendapatan_imputasi numeric 0 0 15
## 7 pendapatan_missing integer 0 0 2
## 8 outlier_pendapatan logical 0 0 2
## 9 usia_minmax numeric 0 0 17
## 10 pendapatan_minmax numeric 0 0 15
## 11 jumlah_transaksi numeric 0 0 13
## 12 total_purchase numeric 0 0 24
Interpretasi: Audit akhir memberikan gambaran kondisi setiap atribut setelah preprocessing, termasuk tipe data, jumlah missing value, dan jumlah nilai unik. Hasil ini digunakan untuk memastikan bahwa perubahan yang dilakukan telah menghasilkan data dengan struktur yang lebih konsisten.
Memeriksa Duplikasi customer_id
## [1] 0
Interpretasi: Hasil pemeriksaan digunakan untuk memastikan bahwa setiap customer_id hanya muncul satu kali pada dataset akhir. Nilai 0 menunjukkan bahwa tidak terdapat lagi duplikasi identifier.
Memeriksa Missing Values
## customer_id nama usia kota
## 0 0 0 0
## status pendapatan_imputasi pendapatan_missing outlier_pendapatan
## 0 0 0 0
## usia_minmax pendapatan_minmax jumlah_transaksi total_purchase
## 0 0 0 0
Interpretasi: Pemeriksaan ini menunjukkan apakah masih terdapat missing values setelah proses imputasi dan integrasi. Missing values yang masih tersisa perlu dibedakan antara nilai yang belum tersedia dan nilai yang sengaja dipertahankan karena maknanya belum dapat dipastikan.
Membandingkan Kondisi Sebelum dan Sesudah Preprocessing
Untuk mengevaluasi perubahan yang terjadi, kondisi data sebelum dan sesudah preprocessing dibandingkan berdasarkan beberapa indikator utama, yaitu jumlah baris, duplikasi customer_id, jumlah missing value, serta jumlah kategori pada atribut kota dan status.
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(na.omit(pelanggan_raw$kota))),
length(unique(na.omit(pelanggan_raw$status)))
),
sesudah = c(
nrow(data_final),
sum(duplicated(data_final$customer_id)),
sum(is.na(data_final)),
length(unique(na.omit(data_final$kota))),
length(unique(data_final$status))
)
)
perbandingan## indikator sebelum sesudah
## 1 Jumlah baris 30 28
## 2 Duplikasi customer_id 2 0
## 3 Total missing value 9 0
## 4 Kategori kota unik 9 4
## 5 Kategori status unik 9 2
Interpretasi: Perbandingan ini menunjukkan perubahan kualitas data dari kondisi awal hingga dataset akhir. Berkurangnya duplikasi dan kategori yang tidak konsisten menunjukkan bahwa proses cleaning berhasil memperbaiki struktur data, sedangkan perubahan jumlah missing values menunjukkan dampak dari strategi penanganan nilai hilang yang diterapkan.
Mengevaluasi Hasil Integrasi
Karena praktikum menggunakan dua sumber data, evaluasi akhir juga perlu memastikan bahwa proses integrasi tidak menyebabkan duplikasi pelanggan atau kehilangan pasangan data secara tidak teridentifikasi.
c(
jumlah_pelanggan = nrow(pelanggan),
jumlah_data_akhir = nrow(data_final),
duplikasi_customer_id = sum(duplicated(data_final$customer_id))
)## jumlah_pelanggan jumlah_data_akhir duplikasi_customer_id
## 28 28 0
Interpretasi: Jumlah baris pada dataset akhir dibandingkan dengan jumlah pelanggan setelah deduplikasi untuk memastikan bahwa proses left join tidak menggandakan data pelanggan. Tidak adanya duplikasi customer_id menunjukkan bahwa integrasi berlangsung sesuai struktur satu pelanggan untuk satu baris data.
Memeriksa Pelanggan yang Tidak Memiliki Transaksi
## [1] customer_id nama
## <0 rows> (or 0-length row.names)
Interpretasi: Hasil ini menunjukkan pelanggan yang tidak memiliki pasangan pada data transaksi. Kondisi tersebut tidak langsung dianggap sebagai kesalahan karena dapat menunjukkan bahwa pelanggan belum melakukan transaksi atau data transaksinya tidak tersedia.
Memeriksa Transaksi yang Tidak Memiliki Pasangan Pelanggan
Karena sebelumnya terdapat C029, C030, dan C031 pada data transaksi, sedangkan identifier tersebut tidak terdapat pada data pelanggan, ketiganya perlu diperiksa secara terpisah.
## [1] "C029" "C030" "C031"
Interpretasi: Hasil pemeriksaan menunjukkan identifier transaksi yang tidak memiliki pasangan pada data pelanggan. Identifier tersebut tidak dapat dimasukkan ke dataset akhir melalui left join dari sisi pelanggan sehingga perlu dicatat sebagai data transaksi yang belum memiliki pasangan pelanggan.
Catatan: C011 juga termasuk kondisi penting pada data awal karena terdapat pada data pelanggan tetapi tidak terdapat pada data transaksi. Kondisi ini tidak perlu diperbaiki pada tahap cleaning, karena bukan kesalahan pada nilai atribut pelanggan. Ketidaksesuaian tersebut ditangani dan dijelaskan pada tahap integrasi data.
Menyimpan Dataset Hasil Preprocessing
Setelah dataset akhir dinyatakan sesuai, hasil preprocessing dapat disimpan untuk digunakan pada tahap analisis selanjutnya.
Ringkasan
Secara keseluruhan, proses data preprocessing pada praktikum ini dilakukan secara bertahap, mulai dari: 1. memeriksa struktur dan kondisi awal data pelanggan dan transaksi; 2. membersihkan data melalui standardisasi kategori dan penanganan duplikasi serta nilai yang tidak sesuai aturan; 3. menangani missing values berdasarkan karakteristik masing-masing atribut; 4. mendeteksi dan mengevaluasi nilai ekstrem pada data pelanggan dan transaksi; 5. melakukan transformasi atribut numerik menggunakan min–maks, z-score, dan decimal scaling; 6. mengintegrasikan data pelanggan dan transaksi berdasarkan customer_id dan memvalidasi hasil integrasinya.
Hasil akhir menunjukkan bahwa data telah menjadi lebih terstruktur, konsisten, dan lebih siap digunakan untuk analisis selanjutnya. Namun, setiap perubahan tetap perlu didasarkan pada kondisi data dan alasan yang jelas, karena data preprocessing bukan sekadar menjalankan kode, melainkan proses menentukan tindakan yang tepat terhadap setiap permasalahan data.