Data preprocessing merupakan tahap awal dalam proses data mining yang bertujuan mempersiapkan data agar memiliki kualitas yang baik sebelum digunakan untuk analisis atau pemodelan. Tahapan yang dilakukan dalam praktikum ini meliputi pemeriksaan struktur data, penanganan missing value, penghapusan data duplikat, standardisasi kategori, deteksi dan penanganan outlier, integrasi data pelanggan dengan data transaksi, serta audit akhir.
Dataset yang digunakan terdiri atas data pelanggan dan data transaksi. Data pelanggan memiliki informasi mengenai identitas pelanggan, nama, usia, pendapatan, kota, dan status. Data transaksi berisi jumlah transaksi dan total pembelian setiap pelanggan.
# Menghapus seluruh objek dari Environment
rm(list = ls())
# Pengaturan agar data karakter tidak otomatis menjadi faktor
options(stringsAsFactors = FALSE)
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")
)
# Menghapus kolom yang tidak diperlukan apabila terbentuk
pelanggan_raw$stringAsFactors <- NULL
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
Interpretasi: Data mentah pelanggan terdiri atas 12 observasi dan 6 variabel. Data sengaja memuat beberapa permasalahan kualitas data, yaitu missing value, duplikasi, ketidakkonsistenan kategori, serta nilai ekstrem yang akan ditangani pada tahap preprocessing.
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)
)
transaksi_raw$stringAsFactors <- NULL
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
Interpretasi: Data transaksi terdiri atas 11
observasi dan 3 variabel. Identifier pada data transaksi awalnya bernama
cust_id, sedangkan data pelanggan menggunakan
customer_id. Perbedaan tersebut akan diseragamkan sebelum
integrasi.
dim(pelanggan_raw)
## [1] 12 6
dim(transaksi_raw)
## [1] 11 3
Interpretasi: Data pelanggan awal terdiri atas 12 baris dan 6 kolom, sedangkan data transaksi terdiri atas 11 baris dan 3 kolom.
names(pelanggan_raw)
## [1] "customer_id" "nama" "usia" "pendapatan" "kota"
## [6] "status"
names(transaksi_raw)
## [1] "cust_id" "jumlah_transaksi" "total_purchase"
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" ...
str(transaksi_raw)
## 'data.frame': 11 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: Pemeriksaan struktur dilakukan untuk
mengetahui tipe data setiap variabel dan memastikan data dapat diproses
sesuai karakteristiknya. Variabel usia,
pendapatan, jumlah_transaksi, dan
total_purchase bersifat numerik, sedangkan identifier,
nama, kota, dan status berupa karakter.
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
head(transaksi_raw)
## 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
colSums(is.na(pelanggan_raw))
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
colSums(is.na(transaksi_raw))
## cust_id jumlah_transaksi total_purchase
## 0 0 0
Interpretasi: Pada data pelanggan terdapat 1 missing
value pada usia, 2 pada pendapatan, dan 1 pada
kota. Data transaksi tidak memiliki missing value.
sum(duplicated(pelanggan_raw))
## [1] 1
pelanggan_raw[
duplicated(pelanggan_raw),
]
## customer_id nama usia pendapatan kota status
## 11 C010 Joko 35 5300000 Dumai Tidak aktif
Interpretasi: Ditemukan 1 baris duplikat, yaitu data customer C010 atas nama Joko.
pelanggan_clean <- pelanggan_raw[
!duplicated(pelanggan_raw),
]
dim(pelanggan_clean)
## [1] 11 6
Interpretasi: Setelah penghapusan duplikasi, data pelanggan berkurang dari 12 menjadi 11 observasi. Tidak ada kolom yang berubah sehingga data menjadi 11 observasi dan 6 variabel.
table(pelanggan_clean$kota, useNA = "ifany")
##
## PKU Dumai DUMAI pekanbaru Pekanbaru PEKANBARU PKU Siak
## 1 2 1 1 2 1 1 1
## <NA>
## 1
Interpretasi: Variabel kota memiliki
beberapa bentuk penulisan untuk kategori yang sama, misalnya
Pekanbaru, PEKANBARU, dan PKU.
Selain itu, terdapat satu missing value.
pelanggan_clean$kota <- trimws(
pelanggan_clean$kota
)
pelanggan_clean$kota <- toupper(
pelanggan_clean$kota
)
table(pelanggan_clean$kota, useNA = "ifany")
##
## DUMAI PEKANBARU PKU SIAK <NA>
## 3 4 2 1 1
pelanggan_clean$kota[
pelanggan_clean$kota == "PKU"
] <- "PEKANBARU"
table(pelanggan_clean$kota, useNA = "ifany")
##
## DUMAI PEKANBARU SIAK <NA>
## 3 6 1 1
Interpretasi: Kategori PKU diseragamkan
menjadi PEKANBARU, sehingga kategori kota menjadi lebih
konsisten. Missing value pada kota akan ditangani pada tahap
imputasi.
pelanggan_clean$status <- toupper(
trimws(pelanggan_clean$status)
)
table(pelanggan_clean$status)
##
## A ACTIVE AKTIF NONAKTIF TIDAK AKTIF
## 2 1 5 1 2
Interpretasi: Setelah huruf dan spasi diseragamkan,
masih terdapat beberapa kategori yang memiliki arti sama, yaitu
A, ACTIVE, dan AKTIF, serta
NONAKTIF dan TIDAK AKTIF.
pelanggan_clean$status[
pelanggan_clean$status %in% c("A", "ACTIVE")
] <- "AKTIF"
pelanggan_clean$status[
pelanggan_clean$status == "TIDAK AKTIF"
] <- "NONAKTIF"
table(pelanggan_clean$status)
##
## AKTIF NONAKTIF
## 8 3
Interpretasi: Setelah standardisasi, variabel status
hanya memiliki dua kategori, yaitu AKTIF dan
NONAKTIF.
colSums(is.na(pelanggan_clean))
## customer_id nama usia pendapatan kota status
## 0 0 1 2 1 0
Median digunakan sebagai nilai pengganti untuk missing value pada variabel numerik.
median_usia <- median(
pelanggan_clean$usia,
na.rm = TRUE
)
median_usia
## [1] 27.5
pelanggan_clean$usia[
is.na(pelanggan_clean$usia)
] <- median_usia
Interpretasi: Missing value pada usia
diganti menggunakan median usia karena median relatif tidak mudah
dipengaruhi oleh nilai ekstrem.
median_pendapatan <- median(
pelanggan_clean$pendapatan,
na.rm = TRUE
)
median_pendapatan
## [1] 4900000
pelanggan_clean$pendapatan[
is.na(pelanggan_clean$pendapatan)
] <- median_pendapatan
Interpretasi: Missing value pada
pendapatan juga diimputasi menggunakan median
pendapatan.
Karena kota merupakan variabel kategorik, nilai yang
hilang diisi menggunakan modus.
modus_kota <- names(
sort(
table(pelanggan_clean$kota),
decreasing = TRUE
)
)[1]
modus_kota
## [1] "PEKANBARU"
pelanggan_clean$kota[
is.na(pelanggan_clean$kota)
] <- modus_kota
Interpretasi: Missing value pada kota diisi dengan kategori yang paling sering muncul.
colSums(is.na(pelanggan_clean))
## customer_id nama usia pendapatan kota status
## 0 0 0 0 0 0
Interpretasi: Setelah proses imputasi, seluruh missing value pada data pelanggan telah ditangani.
boxplot(
pelanggan_clean$usia,
main = "Boxplot Usia",
ylab = "Usia"
)
Q1 <- quantile(
pelanggan_clean$usia,
0.25
)
Q3 <- quantile(
pelanggan_clean$usia,
0.75
)
IQR_usia <- IQR(
pelanggan_clean$usia
)
batas_bawah <- Q1 - 1.5 * IQR_usia
batas_atas <- Q3 + 1.5 * IQR_usia
batas_bawah
## 25%
## 15
batas_atas
## 75%
## 39
pelanggan_clean[
pelanggan_clean$usia < batas_bawah |
pelanggan_clean$usia > batas_atas,
]
## customer_id nama usia pendapatan kota status
## 4 C004 Dodi 150 4800000 DUMAI AKTIF
Interpretasi: Berdasarkan perhitungan IQR, batas bawah usia adalah 15 tahun dan batas atas 39 tahun. Ditemukan satu observasi yang berada di luar batas, yaitu C004 dengan usia 150 tahun.
Nilai usia 150 tahun dianggap tidak wajar sehingga diubah menjadi missing value dan kemudian diimputasi dengan median.
pelanggan_clean$usia[
pelanggan_clean$usia > 100
] <- NA
pelanggan_clean$usia[
is.na(pelanggan_clean$usia)
] <- median(
pelanggan_clean$usia,
na.rm = TRUE
)
Interpretasi: Outlier usia 150 tahun telah ditangani menggunakan imputasi median sehingga tidak lagi memengaruhi distribusi usia.
boxplot(
pelanggan_clean$pendapatan,
main = "Boxplot Pendapatan",
ylab = "Pendapatan"
)
Q1_pendapatan <- quantile(
pelanggan_clean$pendapatan,
0.25
)
Q3_pendapatan <- quantile(
pelanggan_clean$pendapatan,
0.75
)
IQR_pendapatan <- IQR(
pelanggan_clean$pendapatan
)
batas_bawah_pendapatan <-
Q1_pendapatan - 1.5 * IQR_pendapatan
batas_atas_pendapatan <-
Q3_pendapatan + 1.5 * IQR_pendapatan
batas_bawah_pendapatan
## 25%
## 4150000
batas_atas_pendapatan
## 75%
## 5750000
pelanggan_clean[
pelanggan_clean$pendapatan < batas_bawah_pendapatan |
pelanggan_clean$pendapatan > batas_atas_pendapatan,
]
## customer_id nama usia pendapatan kota status
## 7 C007 Gilang 31 5e+08 PEKANBARU AKTIF
Interpretasi: Batas bawah pendapatan adalah Rp4.150.000 dan batas atas Rp5.750.000. Ditemukan satu outlier, yaitu C007 dengan pendapatan Rp500.000.000.
pelanggan_clean$pendapatan[
pelanggan_clean$pendapatan > batas_atas_pendapatan
] <- NA
median_pendapatan <- median(
pelanggan_clean$pendapatan,
na.rm = TRUE
)
pelanggan_clean$pendapatan[
is.na(pelanggan_clean$pendapatan)
] <- median_pendapatan
Interpretasi: Nilai Rp500.000.000 dianggap sebagai nilai ekstrem yang tidak konsisten dengan sebagian besar data, sehingga diubah menjadi missing value dan kemudian diimputasi menggunakan median.
Data pelanggan menggunakan customer_id, sedangkan data
transaksi menggunakan cust_id. Nama identifier diseragamkan
terlebih dahulu.
names(transaksi_raw)[
names(transaksi_raw) == "cust_id"
] <- "customer_id"
names(transaksi_raw)
## [1] "customer_id" "jumlah_transaksi" "total_purchase"
setdiff(
transaksi_raw$customer_id,
pelanggan_clean$customer_id
)
## [1] "C012"
Interpretasi: Ditemukan C012 pada data transaksi yang tidak terdapat pada data pelanggan.
setdiff(
pelanggan_clean$customer_id,
transaksi_raw$customer_id
)
## [1] "C011"
Interpretasi: Ditemukan C011 pada data pelanggan yang tidak memiliki pasangan data pada transaksi.
data_final <- merge(
pelanggan_clean,
transaksi_raw,
by = "customer_id",
all.x = TRUE
)
data_final
## customer_id nama usia pendapatan kota status jumlah_transaksi
## 1 C001 Ani 21.00 4500000 PEKANBARU AKTIF 5
## 2 C002 Budi 25.00 4900000 PEKANBARU AKTIF 3
## 3 C003 Citra 23.00 5200000 PEKANBARU AKTIF 7
## 4 C004 Dodi 27.25 4800000 DUMAI AKTIF 2
## 5 C005 Eka 27.00 4900000 PEKANBARU NONAKTIF 6
## 6 C006 Fani 27.50 5100000 DUMAI NONAKTIF 4
## 7 C007 Gilang 31.00 4900000 PEKANBARU AKTIF 20
## 8 C008 Hana 29.00 4700000 SIAK AKTIF 5
## 9 C009 Indra 22.00 4600000 PEKANBARU AKTIF 3
## 10 C010 Joko 35.00 5300000 DUMAI NONAKTIF 8
## 11 C011 Kiki 28.00 4900000 PEKANBARU AKTIF NA
## total_purchase
## 1 1.5e+06
## 2 9.0e+05
## 3 2.7e+06
## 4 6.0e+05
## 5 2.1e+06
## 6 1.3e+06
## 7 2.5e+07
## 8 1.7e+06
## 9 8.0e+05
## 10 3.2e+06
## 11 NA
dim(data_final)
## [1] 11 8
Interpretasi: Penggabungan dilakukan menggunakan
customer_id sebagai kunci. Metode all.x = TRUE
digunakan agar seluruh pelanggan tetap dipertahankan. Hasil integrasi
menghasilkan 11 observasi dan 8 variabel.
Customer C011 terdapat pada data pelanggan tetapi tidak memiliki data
transaksi. Dalam konteks dataset ini, kondisi tersebut diinterpretasikan
sebagai tidak terdapat transaksi sehingga nilai NA pada
variabel transaksi diubah menjadi 0.
data_final$jumlah_transaksi[
is.na(data_final$jumlah_transaksi)
] <- 0
data_final$total_purchase[
is.na(data_final$total_purchase)
] <- 0
colSums(is.na(data_final))
## customer_id nama usia pendapatan
## 0 0 0 0
## kota status jumlah_transaksi total_purchase
## 0 0 0 0
Interpretasi: Hasil audit menunjukkan bahwa seluruh variabel pada dataset akhir tidak memiliki missing value.
sum(duplicated(data_final))
## [1] 0
Interpretasi: Tidak ditemukan data duplikat pada dataset akhir.
str(data_final)
## 'data.frame': 11 obs. of 8 variables:
## $ customer_id : chr "C001" "C002" "C003" "C004" ...
## $ nama : chr "Ani" "Budi" "Citra" "Dodi" ...
## $ usia : num 21 25 23 27.2 27 ...
## $ pendapatan : num 4500000 4900000 5200000 4800000 4900000 5100000 4900000 4700000 4600000 5300000 ...
## $ kota : chr "PEKANBARU" "PEKANBARU" "PEKANBARU" "DUMAI" ...
## $ status : chr "AKTIF" "AKTIF" "AKTIF" "AKTIF" ...
## $ 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: Dataset akhir terdiri atas 11
observasi dan 8 variabel. Variabel kategorik berupa karakter, sedangkan
variabel numerik berupa usia, pendapatan,
jumlah_transaksi, dan total_purchase.
summary(data_final)
## customer_id nama usia pendapatan kota
## Length :11 Length :11 Min. :21.00 Min. :4500000 Length :11
## N.unique :11 N.unique :11 1st Qu.:24.00 1st Qu.:4750000 N.unique : 3
## N.blank : 0 N.blank : 0 Median :27.25 Median :4900000 N.blank : 0
## Min.nchar: 4 Min.nchar: 3 Mean :26.89 Mean :4890909 Min.nchar: 4
## Max.nchar: 4 Max.nchar: 6 3rd Qu.:28.50 3rd Qu.:5000000 Max.nchar: 9
## Max. :35.00 Max. :5300000
## status jumlah_transaksi total_purchase
## Length :11 Min. : 0.000 Min. : 0
## N.unique : 2 1st Qu.: 3.000 1st Qu.: 850000
## N.blank : 0 Median : 5.000 Median : 1500000
## Min.nchar: 5 Mean : 5.727 Mean : 3618182
## Max.nchar: 8 3rd Qu.: 6.500 3rd Qu.: 2400000
## Max. :20.000 Max. :25000000
Interpretasi: Setelah preprocessing, usia pelanggan berada pada rentang 21–35 tahun dengan rata-rata 26,89 tahun. Pendapatan berada pada rentang Rp4.500.000–Rp5.300.000 dengan rata-rata sekitar Rp4.890.909. Jumlah transaksi berkisar antara 0–20 transaksi, sedangkan total pembelian berkisar antara Rp0–Rp25.000.000.
| Aspek | Sebelum Preprocessing | Sesudah Preprocessing |
|---|---|---|
| Jumlah observasi pelanggan | 12 | 11 |
| Jumlah variabel pelanggan | 6 | 6 |
| Missing value | 4 | 0 |
| Data duplikat | 1 | 0 |
| Outlier usia | 1 | 0 |
| Outlier pendapatan | 1 | 0 |
| Kategori kota | Tidak konsisten | Konsisten |
| Kategori status | Tidak konsisten | Konsisten |
| Data akhir setelah integrasi | - | 11 observasi × 8 variabel |
Interpretasi: Preprocessing berhasil meningkatkan kualitas data. Satu data duplikat dihapus, missing value ditangani, kategori diseragamkan, outlier usia dan pendapatan ditangani, serta data pelanggan dan transaksi berhasil diintegrasikan. Dataset akhir tidak memiliki missing value dan duplikasi.
Berdasarkan proses data preprocessing yang telah dilakukan, data
pelanggan dan transaksi berhasil dipersiapkan untuk tahap analisis atau
pemodelan data mining. Proses dimulai dengan pemeriksaan struktur data
dan kualitas data, kemudian dilanjutkan dengan penanganan missing value,
penghapusan duplikasi, standardisasi kategori, serta deteksi dan
penanganan outlier menggunakan metode IQR. Selanjutnya, identifier
antara data pelanggan dan transaksi diseragamkan dan kedua dataset
diintegrasikan menggunakan customer_id. Hasil audit akhir
menunjukkan bahwa dataset terdiri atas 11 observasi dan 8 variabel,
tidak memiliki missing value maupun data duplikat, serta memiliki
kategori yang lebih konsisten. Dengan demikian, data akhir telah melalui
tahapan preprocessing dan siap digunakan untuk tahap analisis atau
pemodelan data mining.
write.csv(
data_final,
"data_final_preprocessing.csv",
row.names = FALSE
)
getwd()
## [1] "C:/Users/ainiq/Downloads"
File data_final_preprocessing.csv dapat digunakan
kembali sebagai dataset yang telah melalui proses preprocessing.