Nama: Talitah Kinasih Sawity
NIM: 2403111547
Sebelum memulai proses pengolahan data, terlebih dahulu dibuat sebuah
proyek pada RStudio. Proyek ini digunakan sebagai tempat untuk menyimpan
file .Rmd, data, serta hasil preprocessing yang akan
dihasilkan.
Langkah-langkahnya adalah sebagai berikut:
praktikum_preprocessing..Rmd pada folder proyek tersebut.Langkah awal yang dapat dilakukan adalah mengetahui direktori kerja yang sedang digunakan oleh RStudio.
getwd()
## [1] "D:/Users/HP/Documents/SEMESTER 5/DATA MINING"
Selain itu, versi R yang digunakan juga dapat diperiksa.
R.version.string
## [1] "R version 4.6.1 (2026-06-24 ucrt)"
Dalam proses ini digunakan fungsi-fungsi dasar dari R sehingga tidak memerlukan instalasi package tambahan.
Pada praktikum ini digunakan dua dataset, yaitu dataset pelanggan dan dataset transaksi. Dataset tersebut dibuat sebagai contoh data yang masih memiliki beberapa permasalahan kualitas data.
Beberapa masalah yang terdapat dalam data antara lain:
pelanggan_raw <- data.frame(
customer_id = c(
"C001", "C002", "C003", "C004",
"C005", "C006", "C007", "C008",
"C009", "C010", "C010", "C011"
),
nama = c(
"Ani", "Budi", "Citra", "Dodi",
"Eka", "Fani", "Gilang", "Hana",
"Indra", "Joko", "Joko", "Kiki"
),
usia = c(
21, 25, 23, 150,
27, NA, 31, 29,
22, 35, 35, 28
),
pendapatan = c(
4500000, NA, 5200000, 4800000,
4900000, 5100000, 500000000,
4700000, 4600000, 5300000,
5300000, NA
),
kota = c(
"Pekanbaru", " PKU", "PEKANBARU",
"Dumai", "pekanbaru", "DUMAI",
"Pekanbaru ", "Siak", "PKU",
"Dumai", "Dumai", NA
),
status = c(
"Aktif", "aktif", "ACTIVE",
"A", "Tidak Aktif", "nonaktif",
"Aktif", "AKTIF", "A",
"Tidak aktif", "Tidak aktif", "Aktif"
),
stringsAsFactors = FALSE
)
transaksi_raw <- data.frame(
cust_id = c(
"C001", "C002", "C003", "C004",
"C005", "C006", "C007", "C008",
"C009", "C010", "C012"
),
jumlah_transaksi = c(
5, 3, 7, 2, 6,
4, 20, 5, 3,
8, 1
),
total_purchase = c(
1500000, 900000, 2700000,
600000, 2100000, 1300000,
25000000, 1700000, 800000,
3200000, 250000
),
stringsAsFactors = FALSE
)
pelanggan_raw
## customer_id nama usia pendapatan kota status
## 1 C001 Ani 21 4.5e+06 Pekanbaru Aktif
## 2 C002 Budi 25 NA PKU aktif
## 3 C003 Citra 23 5.2e+06 PEKANBARU ACTIVE
## 4 C004 Dodi 150 4.8e+06 Dumai A
## 5 C005 Eka 27 4.9e+06 pekanbaru Tidak Aktif
## 6 C006 Fani NA 5.1e+06 DUMAI nonaktif
## 7 C007 Gilang 31 5.0e+08 Pekanbaru Aktif
## 8 C008 Hana 29 4.7e+06 Siak AKTIF
## 9 C009 Indra 22 4.6e+06 PKU A
## 10 C010 Joko 35 5.3e+06 Dumai Tidak aktif
## 11 C010 Joko 35 5.3e+06 Dumai Tidak aktif
## 12 C011 Kiki 28 NA <NA> Aktif
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
Sebelum melakukan proses preprocessing, struktur data perlu diperiksa terlebih dahulu. Tahap ini dilakukan untuk mengetahui jumlah observasi, jumlah variabel, nama variabel, tipe data, serta gambaran umum dari dataset.
digunakan untuk melihat jumlah baris dan kolom pada dataset.
dim(pelanggan_raw)
## [1] 12 6
digunakan untuk menampilkan nama setiap variabel atau kolom.
names(pelanggan_raw)
## [1] "customer_id" "nama" "usia" "pendapatan" "kota"
## [6] "status"
digunakan untuk melihat struktur dataset secara keseluruhan, termasuk tipe data dari setiap variabel.
str(pelanggan_raw)
## '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" ...
head(pelanggan_raw)
## 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
summary(pelanggan_raw)
## customer_id nama usia pendapatan
## Length :12 Length :12 Min. : 21.00 Min. : 4500000
## N.unique :11 N.unique :11 1st Qu.: 24.00 1st Qu.: 4725000
## N.blank : 0 N.blank : 0 Median : 28.00 Median : 5000000
## Min.nchar: 4 Min.nchar: 3 Mean : 38.73 Mean : 54440000
## Max.nchar: 4 Max.nchar: 6 3rd Qu.: 33.00 3rd Qu.: 5275000
## Max. :150.00 Max. :500000000
## NAs :1 NAs :2
## kota status
## Length :12 Length :12
## N.unique : 9 N.unique : 8
## N.blank : 0 N.blank : 0
## Min.nchar: 3 Min.nchar: 1
## Max.nchar:10 Max.nchar:11
## NAs : 1
##
Pada tahap ini dilakukan pemeriksaan terhadap beberapa masalah yang mungkin terdapat dalam dataset.
Missing value merupakan data yang nilainya kosong atau tidak tersedia.
Jumlah missing value pada setiap variabel dapat diperiksa menggunakan kode berikut.
colSums(is.na(pelanggan_raw))
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
Persentase missing value juga dapat dihitung sebagai berikut.
round(colMeans(is.na(pelanggan_raw)) * 100, 2)
## customer_id nama usia pendapatan kota status
## 0.00 0.00 8.33 16.67 8.33 0.00
Data duplikat dapat terjadi ketika terdapat observasi yang sama atau identifier pelanggan yang muncul lebih dari satu kali.
sum(duplicated(pelanggan_raw))
## [1] 1
Pemeriksaan duplikasi berdasarkan customer_id dilakukan
dengan:
sum(duplicated(pelanggan_raw$customer_id))
## [1] 1
Selanjutnya dilakukan pemeriksaan terhadap kategori pada variabel
kota dan status.
sort(unique(pelanggan_raw$kota))
## [1] " PKU" "Dumai" "DUMAI" "pekanbaru" "Pekanbaru"
## [6] "PEKANBARU" "Pekanbaru " "PKU" "Siak"
sort(unique(pelanggan_raw$status))
## [1] "A" "ACTIVE" "aktif" "Aktif" "AKTIF"
## [6] "nonaktif" "Tidak aktif" "Tidak Aktif"
Dari hasil tersebut dapat terlihat bahwa terdapat beberapa kategori yang sebenarnya memiliki makna sama tetapi ditulis dengan format yang berbeda.
Nilai minimum dan maksimum dari variabel numerik dapat diperiksa sebagai berikut.
range(pelanggan_raw$usia, na.rm = TRUE)
## [1] 21 150
range(pelanggan_raw$pendapatan, na.rm = TRUE)
## [1] 4.5e+06 5.0e+08
Untuk mempermudah pemeriksaan kondisi dataset, dibuat sebuah fungsi audit data.
Fungsi ini digunakan untuk menampilkan:
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 data awal dilakukan menggunakan:
audit_awal <- audit_data(pelanggan_raw)
audit_awal
## atribut tipe jumlah_missing persen_missing jumlah_unik
## 1 customer_id character 0 0.00 11
## 2 nama character 0 0.00 11
## 3 usia numeric 1 8.33 11
## 4 pendapatan numeric 2 16.67 10
## 5 kota character 1 8.33 10
## 6 status character 0 0.00 8
Agar dataset asli tetap tersimpan, proses pembersihan dilakukan menggunakan salinan dari dataset awal.
pelanggan <- pelanggan_raw
Beberapa data pada variabel kota memiliki spasi yang
tidak diperlukan. Oleh karena itu digunakan fungsi
trimws().
pelanggan$kota <- trimws(pelanggan$kota)
pelanggan$status <- trimws(pelanggan$status)
Untuk memudahkan proses standardisasi, seluruh kategori sementara diubah menjadi huruf kecil.
pelanggan$kota <- tolower(pelanggan$kota)
pelanggan$status <- tolower(pelanggan$status)
Hasil kategori setelah dibersihkan dapat diperiksa kembali.
sort(unique(pelanggan$kota))
## [1] "dumai" "pekanbaru" "pku" "siak"
sort(unique(pelanggan$status))
## [1] "a" "active" "aktif" "nonaktif" "tidak aktif"
Beberapa kategori kota yang berbeda sebenarnya mengacu pada lokasi yang sama.
pelanggan$kota[
pelanggan$kota %in% c("pku", "pekanbaru")
] <- "Pekanbaru"
pelanggan$kota[
pelanggan$kota == "dumai"
] <- "Dumai"
pelanggan$kota[
pelanggan$kota == "siak"
] <- "Siak"
Hasil standardisasi kota:
sort(unique(pelanggan$kota))
## [1] "Dumai" "Pekanbaru" "Siak"
Kategori status juga diseragamkan agar memiliki format yang konsisten.
pelanggan$status[
pelanggan$status %in% c("aktif", "active", "a")
] <- "Aktif"
pelanggan$status[
pelanggan$status %in% c("tidak aktif", "nonaktif")
] <- "Tidak Aktif"
Hasil standardisasi status:
sort(unique(pelanggan$status))
## [1] "Aktif" "Tidak Aktif"
Data dengan customer_id yang muncul lebih dari satu kali
diperiksa terlebih dahulu.
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
Selanjutnya, data duplikat dihapus berdasarkan
customer_id.
pelanggan <- pelanggan[
!duplicated(pelanggan$customer_id),
]
rownames(pelanggan) <- NULL
dim(pelanggan)
## [1] 11 6
Pada variabel usia terdapat nilai 150 yang dianggap tidak wajar untuk data pelanggan pada contoh ini.
pelanggan[
pelanggan$usia < 15 |
pelanggan$usia > 100,
]
## customer_id nama usia pendapatan kota status
## 4 C004 Dodi 150 4800000 Dumai Aktif
## NA <NA> <NA> NA NA <NA> <NA>
Nilai tersebut kemudian dikoreksi menjadi 50.
pelanggan$usia[
pelanggan$customer_id == "C004"
] <- 50
Setiap perubahan yang dilakukan selama preprocessing dapat dicatat dalam sebuah log.
log_perubahan <- data.frame(
tahap = c(
"Standardisasi",
"Standardisasi",
"Deduplikasi",
"Koreksi domain"
),
atribut = c(
"kota",
"status",
"customer_id",
"usia"
),
tindakan = c(
"PKU dan variasi kapital diseragamkan menjadi Pekanbaru",
"ACTIVE dan A menjadi Aktif, sedangkan nonaktif menjadi Tidak Aktif",
"Menghapus data customer_id C010 yang muncul lebih dari satu kali",
"Usia C004 dikoreksi dari 150 menjadi 50"
),
stringsAsFactors = FALSE
)
log_perubahan
## tahap atribut
## 1 Standardisasi kota
## 2 Standardisasi status
## 3 Deduplikasi customer_id
## 4 Koreksi domain usia
## tindakan
## 1 PKU dan variasi kapital diseragamkan menjadi Pekanbaru
## 2 ACTIVE dan A menjadi Aktif, sedangkan nonaktif menjadi Tidak Aktif
## 3 Menghapus data customer_id C010 yang muncul lebih dari satu kali
## 4 Usia C004 dikoreksi dari 150 menjadi 50
Setelah proses cleaning, missing value kembali diperiksa.
colSums(is.na(pelanggan))
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
Baris yang memiliki missing value dapat ditampilkan dengan:
pelanggan[
!complete.cases(pelanggan),
]
## customer_id nama usia pendapatan kota status
## 2 C002 Budi 25 NA Pekanbaru Aktif
## 6 C006 Fani NA 5100000 Dumai Tidak Aktif
## 11 C011 Kiki 28 NA <NA> Aktif
Sebagai perbandingan, dapat dilihat jumlah data jika seluruh baris yang memiliki missing value dihapus.
pelanggan_complete <- pelanggan[
complete.cases(pelanggan),
]
nrow(pelanggan)
## [1] 11
nrow(pelanggan_complete)
## [1] 8
Persentase data yang hilang apabila seluruh baris missing dihapus adalah:
round(
(
1 -
nrow(pelanggan_complete) /
nrow(pelanggan)
) * 100,
2
)
## [1] 27.27
Pada variabel pendapatan terdapat nilai yang sangat besar sehingga mean dapat terpengaruh oleh nilai ekstrem.
Oleh karena itu dilakukan perbandingan antara mean dan median.
mean_pendapatan <- mean(
pelanggan$pendapatan,
na.rm = TRUE
)
median_pendapatan <- median(
pelanggan$pendapatan,
na.rm = TRUE
)
mean_pendapatan
## [1] 59900000
median_pendapatan
## [1] 4900000
Dalam kasus ini, median digunakan untuk mengisi missing value karena lebih tahan terhadap pengaruh outlier.
pelanggan$pendapatan_imputasi <- pelanggan$pendapatan
pelanggan$pendapatan_imputasi[
is.na(pelanggan$pendapatan_imputasi)
] <- median_pendapatan
Nilai usia yang hilang juga ditangani menggunakan median.
median_usia <- median(
pelanggan$usia,
na.rm = TRUE
)
pelanggan$usia_imputasi <- pelanggan$usia
pelanggan$usia_imputasi[
is.na(pelanggan$usia_imputasi)
] <- median_usia
Hasil imputasi dapat dilihat sebagai berikut.
pelanggan[
,
c(
"customer_id",
"usia",
"usia_imputasi",
"pendapatan",
"pendapatan_imputasi"
)
]
## customer_id usia usia_imputasi pendapatan pendapatan_imputasi
## 1 C001 21 21.0 4.5e+06 4.5e+06
## 2 C002 25 25.0 NA 4.9e+06
## 3 C003 23 23.0 5.2e+06 5.2e+06
## 4 C004 50 50.0 4.8e+06 4.8e+06
## 5 C005 27 27.0 4.9e+06 4.9e+06
## 6 C006 NA 27.5 5.1e+06 5.1e+06
## 7 C007 31 31.0 5.0e+08 5.0e+08
## 8 C008 29 29.0 4.7e+06 4.7e+06
## 9 C009 22 22.0 4.6e+06 4.6e+06
## 10 C010 35 35.0 5.3e+06 5.3e+06
## 11 C011 28 28.0 NA 4.9e+06
Missing value pada variabel kota diberikan kategori
Tidak diketahui.
pelanggan$kota_imputasi <- pelanggan$kota
pelanggan$kota_imputasi[
is.na(pelanggan$kota_imputasi)
] <- "Tidak diketahui"
table(
pelanggan$kota_imputasi,
useNA = "ifany"
)
##
## Dumai Pekanbaru Siak Tidak diketahui
## 3 6 1 1
Untuk mengetahui data mana yang sebelumnya memiliki missing value pada pendapatan, dibuat variabel indikator.
pelanggan$pendapatan_missing <- as.integer(
is.na(pelanggan$pendapatan)
)
table(pelanggan$pendapatan_missing)
##
## 0 1
## 9 2
Outlier pada pendapatan dapat dilihat menggunakan boxplot.
boxplot(
pelanggan$pendapatan_imputasi,
horizontal = TRUE,
main = "Boxplot Pendapatan",
xlab = "Pendapatan"
)
Identifikasi outlier dilakukan menggunakan metode Interquartile Range atau IQR.
q1 <- quantile(
pelanggan$pendapatan_imputasi,
0.25
)
q3 <- quantile(
pelanggan$pendapatan_imputasi,
0.75
)
iqr <- IQR(
pelanggan$pendapatan_imputasi
)
batas_bawah <- q1 - 1.5 * iqr
batas_atas <- q3 + 1.5 * iqr
c(
Q1 = q1,
Q3 = q3,
IQR = iqr,
batas_bawah = batas_bawah,
batas_atas = batas_atas
)
## Q1.25% Q3.75% IQR batas_bawah.25% batas_atas.75%
## 4750000 5150000 400000 4150000 5750000
pelanggan$outlier_pendapatan <-
pelanggan$pendapatan_imputasi < batas_bawah |
pelanggan$pendapatan_imputasi > batas_atas
Data yang termasuk outlier:
pelanggan[
pelanggan$outlier_pendapatan,
c(
"customer_id",
"nama",
"pendapatan_imputasi"
)
]
## customer_id nama pendapatan_imputasi
## 7 C007 Gilang 5e+08
Nilai ekstrem tidak langsung dihapus. Sebagai contoh penanganan, dilakukan winsorizing dengan membatasi nilai berdasarkan batas IQR.
pelanggan$pendapatan_winsor <- pmin(
pmax(
pelanggan$pendapatan_imputasi,
batas_bawah
),
batas_atas
)
Perbandingan nilai sebelum dan sesudah winsorizing:
pelanggan[
pelanggan$outlier_pendapatan,
c(
"customer_id",
"pendapatan_imputasi",
"pendapatan_winsor"
)
]
## customer_id pendapatan_imputasi pendapatan_winsor
## 7 C007 5e+08 5750000
Transformasi data dilakukan agar variabel numerik dapat memiliki skala yang lebih sesuai dengan kebutuhan analisis.
Rumus normalisasi Min-Max adalah:
\[ x' = \frac{x - min(x)} {max(x) - min(x)} \]
Fungsi normalisasi:
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
}
Normalisasi dilakukan pada variabel usia dan pendapatan.
pelanggan$usia_minmax <- minmax(
pelanggan$usia_imputasi
)
pelanggan$pendapatan_minmax <- minmax(
pelanggan$pendapatan_imputasi
)
Hasil normalisasi:
pelanggan[
,
c(
"customer_id",
"usia",
"usia_minmax",
"pendapatan_imputasi",
"pendapatan_minmax"
)
]
## customer_id usia usia_minmax pendapatan_imputasi pendapatan_minmax
## 1 C001 21 0.00000000 4.5e+06 0.0000000000
## 2 C002 25 0.13793103 4.9e+06 0.0008072654
## 3 C003 23 0.06896552 5.2e+06 0.0014127144
## 4 C004 50 1.00000000 4.8e+06 0.0006054490
## 5 C005 27 0.20689655 4.9e+06 0.0008072654
## 6 C006 NA 0.22413793 5.1e+06 0.0012108981
## 7 C007 31 0.34482759 5.0e+08 1.0000000000
## 8 C008 29 0.27586207 4.7e+06 0.0004036327
## 9 C009 22 0.03448276 4.6e+06 0.0002018163
## 10 C010 35 0.48275862 5.3e+06 0.0016145308
## 11 C011 28 0.24137931 4.9e+06 0.0008072654
Rumus standardisasi Z-Score adalah:
\[ z = \frac{x - \bar{x}}{s} \]
pelanggan$usia_z <- as.numeric(
scale(
pelanggan$usia_imputasi
)
)
pelanggan$pendapatan_z <- as.numeric(
scale(
pelanggan$pendapatan_imputasi
)
)
round(
pelanggan[
,
c(
"usia_z",
"pendapatan_z"
)
],
3
)
## usia_z pendapatan_z
## 1 -0.984 -0.304
## 2 -0.489 -0.301
## 3 -0.737 -0.299
## 4 2.604 -0.302
## 5 -0.242 -0.301
## 6 -0.180 -0.300
## 7 0.253 3.015
## 8 0.006 -0.303
## 9 -0.860 -0.303
## 10 0.748 -0.299
## 11 -0.118 -0.301
Decimal scaling dilakukan dengan membagi nilai berdasarkan pangkat 10 tertentu.
decimal_scale <- function(x) {
maks <- max(
abs(x),
na.rm = TRUE
)
if (maks == 0) {
return(x)
}
j <- ceiling(
log10(maks + 1)
)
x / (10^j)
}
pelanggan$pendapatan_decimal <-
decimal_scale(
pelanggan$pendapatan_imputasi
)
range(
pelanggan$pendapatan_decimal,
na.rm = TRUE
)
## [1] 0.0045 0.5000
Setelah data pelanggan dibersihkan, dataset tersebut digabungkan dengan data transaksi.
Sebelum melakukan penggabungan, dilakukan pemeriksaan terhadap identifier pada kedua dataset.
sum(
duplicated(
pelanggan$customer_id
)
)
## [1] 0
sum(
duplicated(
transaksi_raw$cust_id
)
)
## [1] 0
Pemeriksaan ID yang tidak memiliki pasangan:
setdiff(
pelanggan$customer_id,
transaksi_raw$cust_id
)
## [1] "C011"
setdiff(
transaksi_raw$cust_id,
pelanggan$customer_id
)
## [1] "C012"
Variabel cust_id pada dataset transaksi diubah menjadi
customer_id.
transaksi <- transaksi_raw
names(transaksi)[
names(transaksi) == "cust_id"
] <- "customer_id"
Penggabungan dilakukan menggunakan fungsi merge().
data_terintegrasi <- merge(
pelanggan,
transaksi,
by = "customer_id",
all.x = TRUE
)
Hasil integrasi:
data_terintegrasi[
,
c(
"customer_id",
"nama",
"jumlah_transaksi",
"total_purchase"
)
]
## customer_id nama jumlah_transaksi total_purchase
## 1 C001 Ani 5 1.5e+06
## 2 C002 Budi 3 9.0e+05
## 3 C003 Citra 7 2.7e+06
## 4 C004 Dodi 2 6.0e+05
## 5 C005 Eka 6 2.1e+06
## 6 C006 Fani 4 1.3e+06
## 7 C007 Gilang 20 2.5e+07
## 8 C008 Hana 5 1.7e+06
## 9 C009 Indra 3 8.0e+05
## 10 C010 Joko 8 3.2e+06
## 11 C011 Kiki NA NA
Jumlah data sebelum dan sesudah penggabungan diperiksa kembali.
c(
sebelum = nrow(pelanggan),
sesudah = nrow(data_terintegrasi)
)
## sebelum sesudah
## 11 11
Pemeriksaan duplikasi:
sum(
duplicated(
data_terintegrasi$customer_id
)
)
## [1] 0
Pemeriksaan missing value setelah integrasi:
colSums(
is.na(
data_terintegrasi[
,
c(
"jumlah_transaksi",
"total_purchase"
)
]
)
)
## jumlah_transaksi total_purchase
## 1 1
Data yang belum memiliki transaksi:
data_terintegrasi[
is.na(
data_terintegrasi$jumlah_transaksi
),
c(
"customer_id",
"nama"
)
]
## customer_id nama
## 11 C011 Kiki
Jika nilai NA berarti pelanggan belum pernah melakukan
transaksi, maka nilai tersebut dapat diganti menjadi nol.
data_terintegrasi$jumlah_transaksi_final <-
data_terintegrasi$jumlah_transaksi
data_terintegrasi$total_purchase_final <-
data_terintegrasi$total_purchase
data_terintegrasi$jumlah_transaksi_final[
is.na(
data_terintegrasi$jumlah_transaksi_final
)
] <- 0
data_terintegrasi$total_purchase_final[
is.na(
data_terintegrasi$total_purchase_final
)
] <- 0
Setelah seluruh proses preprocessing selesai, dipilih variabel yang akan digunakan sebagai dataset akhir.
data_final <- data_terintegrasi[
,
c(
"customer_id",
"nama",
"usia_imputasi",
"kota_imputasi",
"status",
"pendapatan_imputasi",
"pendapatan_missing",
"outlier_pendapatan",
"usia_minmax",
"pendapatan_minmax",
"jumlah_transaksi_final",
"total_purchase_final"
)
]
Nama beberapa variabel kemudian disederhanakan.
names(data_final)[
names(data_final) == "kota_imputasi"
] <- "kota"
names(data_final)[
names(data_final) == "usia_imputasi"
] <- "usia"
Menampilkan dataset akhir:
data_final
## customer_id nama usia kota status pendapatan_imputasi
## 1 C001 Ani 21.0 Pekanbaru Aktif 4.5e+06
## 2 C002 Budi 25.0 Pekanbaru Aktif 4.9e+06
## 3 C003 Citra 23.0 Pekanbaru Aktif 5.2e+06
## 4 C004 Dodi 50.0 Dumai Aktif 4.8e+06
## 5 C005 Eka 27.0 Pekanbaru Tidak Aktif 4.9e+06
## 6 C006 Fani 27.5 Dumai Tidak Aktif 5.1e+06
## 7 C007 Gilang 31.0 Pekanbaru Aktif 5.0e+08
## 8 C008 Hana 29.0 Siak Aktif 4.7e+06
## 9 C009 Indra 22.0 Pekanbaru Aktif 4.6e+06
## 10 C010 Joko 35.0 Dumai Tidak Aktif 5.3e+06
## 11 C011 Kiki 28.0 Tidak diketahui Aktif 4.9e+06
## pendapatan_missing outlier_pendapatan usia_minmax pendapatan_minmax
## 1 0 FALSE 0.00000000 0.0000000000
## 2 1 FALSE 0.13793103 0.0008072654
## 3 0 FALSE 0.06896552 0.0014127144
## 4 0 FALSE 1.00000000 0.0006054490
## 5 0 FALSE 0.20689655 0.0008072654
## 6 0 FALSE 0.22413793 0.0012108981
## 7 0 TRUE 0.34482759 1.0000000000
## 8 0 FALSE 0.27586207 0.0004036327
## 9 0 FALSE 0.03448276 0.0002018163
## 10 0 FALSE 0.48275862 0.0016145308
## 11 1 FALSE 0.24137931 0.0008072654
## jumlah_transaksi_final total_purchase_final
## 1 5 1.5e+06
## 2 3 9.0e+05
## 3 7 2.7e+06
## 4 2 6.0e+05
## 5 6 2.1e+06
## 6 4 1.3e+06
## 7 20 2.5e+07
## 8 5 1.7e+06
## 9 3 8.0e+05
## 10 8 3.2e+06
## 11 0 0.0e+00
Audit kembali dilakukan untuk memastikan data hasil preprocessing sudah lebih siap digunakan.
audit_akhir <- audit_data(
data_final
)
audit_akhir
## atribut tipe jumlah_missing persen_missing jumlah_unik
## 1 customer_id character 0 0 11
## 2 nama character 0 0 11
## 3 usia numeric 0 0 11
## 4 kota character 0 0 4
## 5 status character 0 0 2
## 6 pendapatan_imputasi numeric 0 0 9
## 7 pendapatan_missing integer 0 0 2
## 8 outlier_pendapatan logical 0 0 2
## 9 usia_minmax numeric 0 0 11
## 10 pendapatan_minmax numeric 0 0 9
## 11 jumlah_transaksi_final numeric 0 0 9
## 12 total_purchase_final numeric 0 0 11
Pemeriksaan duplikasi:
sum(
duplicated(
data_final$customer_id
)
)
## [1] 0
Pemeriksaan missing value:
colSums(
is.na(data_final)
)
## customer_id nama usia
## 0 0 0
## kota status pendapatan_imputasi
## 0 0 0
## pendapatan_missing outlier_pendapatan usia_minmax
## 0 0 0
## pendapatan_minmax jumlah_transaksi_final total_purchase_final
## 0 0 0
Untuk melihat perubahan kualitas data, dilakukan perbandingan antara dataset sebelum dan sesudah preprocessing.
perbandingan <- data.frame(
indikator = c(
"Jumlah baris",
"Duplikasi customer_id",
"Total missing value",
"Kategori kota unik",
"Kategori status unik"
),
sebelum = c(
nrow(pelanggan_raw),
sum(
duplicated(
pelanggan_raw$customer_id
)
),
sum(
is.na(pelanggan_raw)
),
length(
unique(
pelanggan_raw$kota
)
),
length(
unique(
pelanggan_raw$status
)
)
),
sesudah = c(
nrow(data_final),
sum(
duplicated(
data_final$customer_id
)
),
sum(
is.na(data_final)
),
length(
unique(
data_final$kota
)
),
length(
unique(
data_final$status
)
)
)
)
perbandingan
## indikator sebelum sesudah
## 1 Jumlah baris 12 11
## 2 Duplikasi customer_id 1 0
## 3 Total missing value 4 0
## 4 Kategori kota unik 10 4
## 5 Kategori status unik 8 2
Dataset akhir dapat disimpan dalam format CSV.
write.csv(
data_final,
"data_pelanggan_setelah_preprocessing.csv",
row.names = FALSE
)
Log perubahan juga dapat disimpan.
write.csv(
log_perubahan,
"log_perubahan_preprocessing.csv",
row.names = FALSE
)
Berdasarkan proses yang telah dilakukan, preprocessing data dilakukan melalui beberapa tahapan utama, yaitu pemeriksaan struktur data, evaluasi kualitas data, data cleaning, penanganan missing value, identifikasi outlier, transformasi data, dan integrasi data.
Pada tahap data cleaning, dilakukan penyeragaman penulisan kategori, penghapusan data duplikat, serta perbaikan nilai yang dianggap tidak sesuai dengan kondisi data. Missing value pada variabel numerik ditangani menggunakan metode imputasi median, sedangkan missing value pada data kategorik diberikan kategori khusus.
Selanjutnya, keberadaan outlier pada variabel pendapatan diidentifikasi menggunakan metode IQR. Nilai ekstrem tersebut kemudian ditandai dan dilakukan contoh penanganan menggunakan metode winsorizing.
Transformasi data juga dilakukan melalui normalisasi Min-Max,
standardisasi Z-Score, dan decimal scaling. Setelah itu, dataset
pelanggan digabungkan dengan dataset transaksi berdasarkan
customer_id.
Melalui seluruh tahapan tersebut, kualitas dataset menjadi lebih baik, lebih konsisten, dan lebih siap untuk digunakan pada proses analisis data maupun tahap data mining selanjutnya.
Han, J., Kamber, M., & Pei, J. (2012). Data Mining: Concepts and Techniques (3rd ed.). Morgan Kaufmann.
````