Proses pengolahan data pelanggan dan transaksi dari kondisi awal hingga menjadi data yang lebih siap untuk dianalisis.
Data yang digunakan dalam suatu analisis tidak selalu berada dalam kondisi yang langsung dapat digunakan. Data dapat mengandung nilai yang kosong, data yang tercatat lebih dari satu kali, penulisan kategori yang berbeda, maupun nilai yang terlalu jauh dari data lainnya. Jika kondisi tersebut tidak diperiksa dan ditangani dengan baik, hasil analisis yang diperoleh dapat menjadi kurang tepat.
Pada praktikum ini digunakan data pelanggan dan data transaksi yang memiliki beberapa permasalahan tersebut. Proses data preprocessing dilakukan menggunakan RStudio untuk melihat kondisi data, menemukan permasalahan, melakukan perbaikan, dan memeriksa kembali hasilnya. Tahapan yang digunakan meliputi pembangunan dataset, pemeriksaan kondisi data, pembersihan data, penanganan missing value, penanganan outlier, transformasi data, integrasi data, hingga pemeriksaan akhir.
Melalui proses ini, dapat dilihat secara langsung perubahan data sebelum dan sesudah preprocessing. Selain menggunakan tabel, hasil pengolahan juga ditampilkan dalam bentuk visualisasi seperti distribusi data, boxplot, serta perbandingan sebelum dan sesudah penanganan masalah data.
Praktikum ini bertujuan untuk:
Dataset memiliki beberapa masalah yang sengaja dibuat untuk latihan preprocessing: missing value, duplikat, format kategori yang tidak konsisten, serta outlier.
Dashboard ini merangkum perubahan utama dari data mentah sampai data siap analisis.
Data terdiri dari dua sumber: pelanggan_raw dan transaksi_raw.
kable(pelanggan_raw, caption="Data pelanggan mentah")
| customer_id | nama | usia | pendapatan | kota | status |
|---|---|---|---|---|---|
| C001 | Ani | 21 | 4.5e+06 | Pekanbaru | Aktif |
| C002 | Budi | 25 | NA | PKU | aktif |
| C003 | Citra | 23 | 5.2e+06 | PEKANBARU | ACTIVE |
| C004 | Dodi | 150 | 4.8e+06 | Dumai | A |
| C005 | Eka | 27 | 4.9e+06 | pekanbaru | Tidak Aktif |
| C006 | Fani | NA | 5.1e+06 | DUMAI | nonaktif |
| C007 | Gilang | 31 | 5.0e+08 | Pekanbaru | Aktif |
| C008 | Hana | 29 | 4.7e+06 | Siak | AKTIF |
| C009 | Indra | 22 | 4.6e+06 | PKU | A |
| C010 | Joko | 35 | 5.3e+06 | Dumai | Tidak aktif |
| C010 | Joko | 35 | 5.3e+06 | Dumai | Tidak aktif |
| C011 | Kiki | 28 | NA | NA | Aktif |
kable(transaksi_raw, caption="Data transaksi mentah")
| cust_id | jumlah_transaksi | total_purchase |
|---|---|---|
| C001 | 5 | 1.5e+06 |
| C002 | 3 | 9.0e+05 |
| C003 | 7 | 2.7e+06 |
| C004 | 2 | 6.0e+05 |
| C005 | 6 | 2.1e+06 |
| C006 | 4 | 1.3e+06 |
| C007 | 20 | 2.5e+07 |
| C008 | 5 | 1.7e+06 |
| C009 | 3 | 8.0e+05 |
| C010 | 8 | 3.2e+06 |
| C012 | 1 | 2.5e+05 |
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" ...
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
##
summary(transaksi_raw)
## cust_id jumlah_transaksi total_purchase
## Length :11 Min. : 1.000 Min. : 250000
## N.unique :11 1st Qu.: 3.000 1st Qu.: 850000
## N.blank : 0 Median : 5.000 Median : 1500000
## Min.nchar: 4 Mean : 5.818 Mean : 3640909
## Max.nchar: 4 3rd Qu.: 6.500 3rd Qu.: 2400000
## Max. :20.000 Max. :25000000
missing_awal_tabel <- data.frame(variabel=names(pelanggan_raw), jumlah_missing=sapply(pelanggan_raw, function(x) sum(is.na(x))))
kable(missing_awal_tabel, caption="Missing value pada data pelanggan")
| variabel | jumlah_missing | |
|---|---|---|
| customer_id | customer_id | 0 |
| nama | nama | 0 |
| usia | usia | 1 |
| pendapatan | pendapatan | 2 |
| kota | kota | 1 |
| status | status | 0 |
ggplot(missing_awal_tabel, aes(x=reorder(variabel,jumlah_missing), y=jumlah_missing)) +
geom_col() + coord_flip() +
labs(title="Missing Value Sebelum Imputasi", x=NULL, y="Jumlah Missing") +
theme_minimal()
sum(duplicated(pelanggan_raw$customer_id))
## [1] 1
pelanggan_raw[pelanggan_raw$customer_id == "C010",]
## customer_id nama usia pendapatan kota status
## 10 C010 Joko 35 5300000 Dumai Tidak aktif
## 11 C010 Joko 35 5300000 Dumai Tidak aktif
Pembersihan dilakukan dengan menghapus spasi, menyeragamkan kota dan
status, kemudian menghapus duplikat berdasarkan
customer_id.
pelanggan_clean_sebelum_imputasi <- pelanggan_raw %>%
mutate(across(where(is.character), trimws)) %>%
mutate(
kota = case_when(
toupper(kota) %in% c("PKU","PEKANBARU") ~ "Pekanbaru",
toupper(kota)=="DUMAI" ~ "Dumai",
toupper(kota)=="SIAK" ~ "Siak",
is.na(kota) ~ NA_character_, TRUE ~ kota),
status = case_when(
toupper(status) %in% c("AKTIF","ACTIVE","A") ~ "Aktif",
toupper(status) %in% c("TIDAK AKTIF","NONAKTIF") ~ "Tidak Aktif",
is.na(status) ~ NA_character_, TRUE ~ status)
) %>% distinct(customer_id, .keep_all=TRUE)
kable(pelanggan_clean_sebelum_imputasi, caption="Data setelah cleaning awal")
| customer_id | nama | usia | pendapatan | kota | status |
|---|---|---|---|---|---|
| C001 | Ani | 21 | 4.5e+06 | Pekanbaru | Aktif |
| C002 | Budi | 25 | NA | Pekanbaru | Aktif |
| C003 | Citra | 23 | 5.2e+06 | Pekanbaru | Aktif |
| C004 | Dodi | 150 | 4.8e+06 | Dumai | Aktif |
| C005 | Eka | 27 | 4.9e+06 | Pekanbaru | Tidak Aktif |
| C006 | Fani | NA | 5.1e+06 | Dumai | Tidak Aktif |
| C007 | Gilang | 31 | 5.0e+08 | Pekanbaru | Aktif |
| C008 | Hana | 29 | 4.7e+06 | Siak | Aktif |
| C009 | Indra | 22 | 4.6e+06 | Pekanbaru | Aktif |
| C010 | Joko | 35 | 5.3e+06 | Dumai | Tidak Aktif |
| C011 | Kiki | 28 | NA | NA | Aktif |
Missing value numerik diisi menggunakan median, sedangkan kota diisi menggunakan modus.
missing_setelah <- data.frame(variabel=names(pelanggan_imputed), jumlah_missing=sapply(pelanggan_imputed, function(x) sum(is.na(x))))
kable(missing_setelah, caption="Missing value setelah imputasi")
| variabel | jumlah_missing | |
|---|---|---|
| customer_id | customer_id | 0 |
| nama | nama | 0 |
| usia | usia | 0 |
| pendapatan | pendapatan | 0 |
| kota | kota | 0 |
| status | status | 0 |
Outlier dideteksi menggunakan metode IQR dan ditangani dengan capping/winsorization agar baris data tidak langsung dihapus.
Transformasi meliputi normalisasi Min-Max dan pembentukan kategori usia.
kable(
pelanggan_clean %>% select(customer_id,nama,usia,kategori_usia,pendapatan,pendapatan_normalisasi),
caption="Data pelanggan setelah transformasi"
)
| customer_id | nama | usia | kategori_usia | pendapatan | pendapatan_normalisasi |
|---|---|---|---|---|---|
| C001 | Ani | 21.0 | Muda | 4500000 | 0.00 |
| C002 | Budi | 25.0 | Dewasa | 4900000 | 0.32 |
| C003 | Citra | 23.0 | Muda | 5200000 | 0.56 |
| C004 | Dodi | 39.0 | Lebih dari 35 | 4800000 | 0.24 |
| C005 | Eka | 27.0 | Dewasa | 4900000 | 0.32 |
| C006 | Fani | 27.5 | Dewasa | 5100000 | 0.48 |
| C007 | Gilang | 31.0 | Dewasa | 5750000 | 1.00 |
| C008 | Hana | 29.0 | Dewasa | 4700000 | 0.16 |
| C009 | Indra | 22.0 | Muda | 4600000 | 0.08 |
| C010 | Joko | 35.0 | Dewasa | 5300000 | 0.64 |
| C011 | Kiki | 28.0 | Dewasa | 4900000 | 0.32 |
Data pelanggan dan transaksi digabungkan berdasarkan
customer_id.
kable(data_final, caption="Data hasil integrasi")
| customer_id | nama | usia | pendapatan | kota | status | pendapatan_normalisasi | kategori_usia | jumlah_transaksi | total_purchase | jumlah_transaksi_normalisasi | total_purchase_normalisasi |
|---|---|---|---|---|---|---|---|---|---|---|---|
| C001 | Ani | 21.0 | 4500000 | Pekanbaru | Aktif | 0.00 | Muda | 5.00 | 1500000 | 0.3720930 | 0.2793296 |
| C002 | Budi | 25.0 | 4900000 | Pekanbaru | Aktif | 0.32 | Dewasa | 3.00 | 900000 | 0.1860465 | 0.1452514 |
| C003 | Citra | 23.0 | 5200000 | Pekanbaru | Aktif | 0.56 | Muda | 7.00 | 2700000 | 0.5581395 | 0.5474860 |
| C004 | Dodi | 39.0 | 4800000 | Dumai | Aktif | 0.24 | Lebih dari 35 | 2.00 | 600000 | 0.0930233 | 0.0782123 |
| C005 | Eka | 27.0 | 4900000 | Pekanbaru | Tidak Aktif | 0.32 | Dewasa | 6.00 | 2100000 | 0.4651163 | 0.4134078 |
| C006 | Fani | 27.5 | 5100000 | Dumai | Tidak Aktif | 0.48 | Dewasa | 4.00 | 1300000 | 0.2790698 | 0.2346369 |
| C007 | Gilang | 31.0 | 5750000 | Pekanbaru | Aktif | 1.00 | Dewasa | 11.75 | 4725000 | 1.0000000 | 1.0000000 |
| C008 | Hana | 29.0 | 4700000 | Siak | Aktif | 0.16 | Dewasa | 5.00 | 1700000 | 0.3720930 | 0.3240223 |
| C009 | Indra | 22.0 | 4600000 | Pekanbaru | Aktif | 0.08 | Muda | 3.00 | 800000 | 0.1860465 | 0.1229050 |
| C010 | Joko | 35.0 | 5300000 | Dumai | Tidak Aktif | 0.64 | Dewasa | 8.00 | 3200000 | 0.6511628 | 0.6592179 |
| C011 | Kiki | 28.0 | 4900000 | Pekanbaru | Aktif | 0.32 | Dewasa | NA | NA | NA | NA |
kable(transaksi_tanpa_pelanggan, caption="Transaksi yang tidak memiliki data pelanggan")
| customer_id | jumlah_transaksi | total_purchase | jumlah_transaksi_normalisasi | total_purchase_normalisasi |
|---|---|---|---|---|
| C012 | 1 | 250000 | 0 | 0 |
cat("Jumlah baris pelanggan setelah cleaning:", nrow(pelanggan_clean), "\n")
## Jumlah baris pelanggan setelah cleaning: 11
cat("Jumlah ID pelanggan unik:", n_distinct(pelanggan_clean$customer_id), "\n")
## Jumlah ID pelanggan unik: 11
cat("Duplikat ID pelanggan:", sum(duplicated(pelanggan_clean$customer_id)), "\n")
## Duplikat ID pelanggan: 0
missing_final <- data.frame(
variabel=names(data_final),
jumlah_missing=sapply(data_final, function(x) sum(is.na(x)))
)
kable(missing_final, caption="Pemeriksaan missing value setelah integrasi")
| variabel | jumlah_missing | |
|---|---|---|
| customer_id | customer_id | 0 |
| nama | nama | 0 |
| usia | usia | 0 |
| pendapatan | pendapatan | 0 |
| kota | kota | 0 |
| status | status | 0 |
| pendapatan_normalisasi | pendapatan_normalisasi | 0 |
| kategori_usia | kategori_usia | 0 |
| jumlah_transaksi | jumlah_transaksi | 1 |
| total_purchase | total_purchase | 1 |
| jumlah_transaksi_normalisasi | jumlah_transaksi_normalisasi | 1 |
| total_purchase_normalisasi | total_purchase_normalisasi | 1 |
Data pelanggan sudah dibersihkan dari duplikat, kategori sudah diseragamkan, missing value pelanggan sudah ditangani, outlier numerik sudah dicapping, dan variabel numerik sudah ditransformasi.
kable(data_final, caption="Dataset hasil preprocessing dan integrasi")
| customer_id | nama | usia | pendapatan | kota | status | pendapatan_normalisasi | kategori_usia | jumlah_transaksi | total_purchase | jumlah_transaksi_normalisasi | total_purchase_normalisasi |
|---|---|---|---|---|---|---|---|---|---|---|---|
| C001 | Ani | 21.0 | 4500000 | Pekanbaru | Aktif | 0.00 | Muda | 5.00 | 1500000 | 0.3720930 | 0.2793296 |
| C002 | Budi | 25.0 | 4900000 | Pekanbaru | Aktif | 0.32 | Dewasa | 3.00 | 900000 | 0.1860465 | 0.1452514 |
| C003 | Citra | 23.0 | 5200000 | Pekanbaru | Aktif | 0.56 | Muda | 7.00 | 2700000 | 0.5581395 | 0.5474860 |
| C004 | Dodi | 39.0 | 4800000 | Dumai | Aktif | 0.24 | Lebih dari 35 | 2.00 | 600000 | 0.0930233 | 0.0782123 |
| C005 | Eka | 27.0 | 4900000 | Pekanbaru | Tidak Aktif | 0.32 | Dewasa | 6.00 | 2100000 | 0.4651163 | 0.4134078 |
| C006 | Fani | 27.5 | 5100000 | Dumai | Tidak Aktif | 0.48 | Dewasa | 4.00 | 1300000 | 0.2790698 | 0.2346369 |
| C007 | Gilang | 31.0 | 5750000 | Pekanbaru | Aktif | 1.00 | Dewasa | 11.75 | 4725000 | 1.0000000 | 1.0000000 |
| C008 | Hana | 29.0 | 4700000 | Siak | Aktif | 0.16 | Dewasa | 5.00 | 1700000 | 0.3720930 | 0.3240223 |
| C009 | Indra | 22.0 | 4600000 | Pekanbaru | Aktif | 0.08 | Muda | 3.00 | 800000 | 0.1860465 | 0.1229050 |
| C010 | Joko | 35.0 | 5300000 | Dumai | Tidak Aktif | 0.64 | Dewasa | 8.00 | 3200000 | 0.6511628 | 0.6592179 |
| C011 | Kiki | 28.0 | 4900000 | Pekanbaru | Aktif | 0.32 | Dewasa | NA | NA | NA | NA |
Preprocessing data merupakan tahap penting sebelum analisis dilakukan. Pada dataset ini, proses preprocessing mencakup pembangunan dataset, pemeriksaan kondisi awal, cleaning, imputasi missing value, deteksi dan penanganan outlier, transformasi, integrasi, serta pemeriksaan akhir.
Hasil akhir menunjukkan bahwa data menjadi lebih konsisten dan lebih siap digunakan untuk analisis lanjutan maupun pembuatan model.