Clustering adalah salah satu teknik Machine Learning, yang memiliki kemampuan untuk mengelompokkan kumpulan data yang tidak berlabel. Setiap data yang tidak berlabel nantinya akan diklasifikasikan ke dalam kelompok tertentu dimana, titik data yang berada dalam kelompok yang sama akan memiliki sifat atau fitur yang serupa, sedangkan titik data dalam kelompok yang berbeda diharapkan memiliki sifat atau fitur yang sangat berbeda.
Dalam ilmu data, kita dapat menggunakan clustering untuk mendapatkan beberapa wawasan berharga dari data kita dengan melihat hasil pengelompokan yang terjadi. Informasi yang berharga tersebut bisa kita bawa untuk membantu kita dalam menentukan segmentasi market, segmentasi kustomer, social netwrok analysis, dan masih banyak lagi. Di luar semua manfaat yang bisa kita dapatkan dari metode clustering, masih ada sebuah stigma yang menempel terhadap metode clustering. Pada artikel ini nantinya akan membahas metode clustering yang dapat digunakan untuk mengatasi stigma yang menempel terhadap metode clustering.
Stigma yang menempel pada clustering adalah hanya bisa digunakan untuk data-data numerik. Hal tersebut terjadi karena banyak sekali implementasi atau contoh dari clustering yang hanya menggunakan data numerik.
Sesungguhnya clustering juga bisa digunakan terhadap data-data kategorikal, dan pada kesempatan kali ini kita akan mencoba menggunakan clustering untuk mengelompokan data kategorikal dan data numerik. Tipe algoritma yang akan kita gunakan nantinya bernama Partitioning Around Medoids dan metode perhitungan jarak yang akan digunakan adalah Gower Distance.
Kita telah mengetahui bahwa clustering merupakan pengelompokan data-data yang memiliki banyak manfaat. Pengelompokan data ini dapat berdasarkan umur, status menikah, pendapatan dll. Pada kasus clustering yang hanya melibatkan sedikit faktor seperti umur saja, kita dapat dengan mudah mengelompokan mereka misal 0-5 (balita), 5-12 (anak-anak), 13-18 (remaja) dan lain sebagainya. Namun, pada kasus yang melibatkan informasi yang banyak misal ada umur, jenis kelamin, pendapatan, pendidikan, status menikah dll, cenderung kita sulit mengelompokannya secara efektif dan efisien.
Pada kasus nyata sering kali setiap orang memiliki informasi yang sangat banyak dan berbeda-beda sehingga akan memakan waktu dalam menganalis hal tersebut, ditambah lagi apabila jumlah data yang kita ingin observasi sangat banyak. Oleh karena itu, dibutuhkan Machine Learning agar dapat memproses pengelompokan data (clustering) secara efisien dan efektif.
knitr::include_graphics("assets/contoh_clustering.png")
Pada gambar di atas terlihat data yang dimiliki cenderung abstrak atau
sulit menemukan pola pengelompokan data. Namun, dengan menggunakan
Machine Learning kita dapat mengelompokan data tersebut dengan
lebih baik karena memiliki berbagai dasar bukan sekedar kira-kira.
Install packages yang diperlukan
#install.packages("tidyverse","Himsc","cluster","factorextra","Rtsne")
Panggil packages yang telah di install
# Data Wrangling
library(tidyverse)
library(Hmisc)
# Machine Learning - Clustering
library(cluster)
library(factoextra)
# Visualization
library(Rtsne)
Dalam pembuatan report LBB ini, kami juga sudah menyediakan sebuah data yang dapat digunakan. Data tersebut berisikan behavior dari para pengguna kartu kredit disebuah bank. Data tersebut kami letakan di foder data dengan nama file creditcard_usage_behavior.csv.
# Membaca dataset
creditcard <- read.csv("data/creditcard_usage_behavior.csv")
# Menampilkan 5 data teratas
creditcard %>%
head()
Deskripsi singkat:
CLIENTNUM : Unique ID ClientCustomer_Age: Umur customerGender: gender customerEducation_Level: Tingkat pendidikanMarital_Status: Status PernikahanIncome_Category: Range pendapatanMonths_Inactive_12_mon: Selama 12 bulan terakhir sempat
tidak menggunakan kartu kredit berapa lamaCredit_Limit: Limmit dari creditcardTotal_Trans_Amt: Jumlah amount transaksi yang dilakukan
selama 12 bulan terakhirTotal_Trans_Ct: Total transaksi yang dilakukan selama
12 bulan terakhirRole Play Bisnis Question
Kita selaku tim Data dari Bank, diminta tolong oleh tim marketing untuk membuat segmentasi customer dari keseluruhan customer yang terdaftar karena tim marketing merasa khawatir jika promo dibuat secara general atau sama rata antar setiap customer, promo tersebut menjadi sia-sia. Harapan dari tim marketing dengan adanya segmentasi kustomer, kita dapat memahami kebiasaan dari setiap kelompok customer sehingga kita dapat menawarkan berbagai promo yang ada dan menghasilkan berbagai promo baru yang menarik dan tepat sasaran dengan tetap memperhatikan tingkat resikonya.
creditcard %>% glimpse()
#> Rows: 10,127
#> Columns: 10
#> $ CLIENTNUM <int> 768805383, 818770008, 713982108, 769911858, 709…
#> $ Customer_Age <int> 45, 49, 51, 40, 40, 44, 51, 32, 37, 48, 42, 65,…
#> $ Gender <chr> "M", "F", "M", "F", "M", "M", "M", "M", "M", "M…
#> $ Education_Level <chr> "High School", "Graduate", "Graduate", "High Sc…
#> $ Marital_Status <chr> "Married", "Single", "Married", "Unknown", "Mar…
#> $ Income_Category <chr> "$60K - $80K", "Less than $40K", "$80K - $120K"…
#> $ Months_Inactive_12_mon <int> 1, 1, 1, 4, 1, 1, 1, 2, 2, 3, 3, 2, 6, 1, 2, 1,…
#> $ Credit_Limit <dbl> 12691.0, 8256.0, 3418.0, 3313.0, 4716.0, 4010.0…
#> $ Total_Trans_Amt <int> 1144, 1291, 1887, 1171, 816, 1088, 1330, 1538, …
#> $ Total_Trans_Ct <int> 42, 33, 20, 20, 28, 24, 31, 36, 24, 32, 42, 26,…
CLIENTNUM -> menjadi nama kolom.Gender -> factorEducation_Level -> factorMarital_Status -> factorIncome_Category -> factorMonths_Inactive_12_mon -> factor# Menyesuaikan data
creditcard <-
creditcard %>%
column_to_rownames(var = "CLIENTNUM") %>% # menjadikan kolom ke rowname
mutate(Gender = as.factor(Gender), # mengubah ke factor
Education_Level = as.factor(Education_Level), # mengubah ke factor
Marital_Status = as.factor(Marital_Status), # mengubah ke factor
Income_Category = as.factor(Income_Category), # mengubah ke factor
Months_Inactive_12_mon = as.factor(Months_Inactive_12_mon)) # mengubah ke factor
# Menampilkan tipe data setelah disesuaikan
creditcard %>%
glimpse()
#> Rows: 10,127
#> Columns: 9
#> $ Customer_Age <int> 45, 49, 51, 40, 40, 44, 51, 32, 37, 48, 42, 65,…
#> $ Gender <fct> M, F, M, F, M, M, M, M, M, M, M, M, M, M, F, M,…
#> $ Education_Level <fct> High School, Graduate, Graduate, High School, U…
#> $ Marital_Status <fct> Married, Single, Married, Unknown, Married, Mar…
#> $ Income_Category <fct> $60K - $80K, Less than $40K, $80K - $120K, Less…
#> $ Months_Inactive_12_mon <fct> 1, 1, 1, 4, 1, 1, 1, 2, 2, 3, 3, 2, 6, 1, 2, 1,…
#> $ Credit_Limit <dbl> 12691.0, 8256.0, 3418.0, 3313.0, 4716.0, 4010.0…
#> $ Total_Trans_Amt <int> 1144, 1291, 1887, 1171, 816, 1088, 1330, 1538, …
#> $ Total_Trans_Ct <int> 42, 33, 20, 20, 28, 24, 31, 36, 24, 32, 42, 26,…
Kita dapat menggunakan fungsi summary() untuk melihat
ringkasan statistik. - Untuk data bertipe integer (int)
(bilangan bulat) dan double (dbl) (bilangan desimal)
terdapat lima ringkasan statistik deskriptif :
Minimum Value: nilai terkecil dari keseluruhan data
1st Qu : nilai kuartil pertama (berada di urutan 1/4 dari keseluruhan data)
2st Qu/Median : nilai tengah (berada di urutan 2/4 dari keseluruhan data)
Mean: rata-rata setiap nilai
3st Qu : nilai kuartil ketiga (berada di urutan 3/4 dari keseluruhan data)
Maximum Value: nilai terbesar dari keseluruhan data.
Untuk data bertipe factor menjumlah setiap jenis data.
creditcard %>%
summary()
#> Customer_Age Gender Education_Level Marital_Status
#> Min. :26.00 F:5358 College :1013 Divorced: 748
#> 1st Qu.:41.00 M:4769 Doctorate : 451 Married :4687
#> Median :46.00 Graduate :3128 Single :3943
#> Mean :46.33 High School :2013 Unknown : 749
#> 3rd Qu.:52.00 Post-Graduate: 516
#> Max. :73.00 Uneducated :1487
#> Unknown :1519
#> Income_Category Months_Inactive_12_mon Credit_Limit Total_Trans_Amt
#> $120K + : 727 0: 29 Min. : 1438 Min. : 510
#> $40K - $60K :1790 1:2233 1st Qu.: 2555 1st Qu.: 2156
#> $60K - $80K :1402 2:3282 Median : 4549 Median : 3899
#> $80K - $120K :1535 3:3846 Mean : 8632 Mean : 4404
#> Less than $40K:3561 4: 435 3rd Qu.:11068 3rd Qu.: 4741
#> Unknown :1112 5: 178 Max. :34516 Max. :18484
#> 6: 124
#> Total_Trans_Ct
#> Min. : 10.00
#> 1st Qu.: 45.00
#> Median : 67.00
#> Mean : 64.86
#> 3rd Qu.: 81.00
#> Max. :139.00
#>
Kalau kita lihat pada ringkasan ini ternyata ada nilai “Unknown” yang sebenarnya merupakan nilai kosong (missing value). Oleh karena itu, kita perlu menyelesaikan/memilih treatment untuk mengatasi missing value. Kolom yang memiliki nilai “Unknown” :
Education_Level
Marital_Status
Income_Category
Berhubung ketiga kolom yang memiliki missing value bertipe factor, sebaiknya menyelesaikan dengan menganti nilai “Unknown” dengan nilai modus (nilai yang paling sering muncul) karena kita tidak memungkinkan untuk menanyakan data nilai “Unknown” kepada pemiliki data. Kita tidak memilih treatment menghapus baris karena jumlah barisnya sangat banyak ribuan baris sedangkan data kita hanya berjumlah 10.000+. Kita tidak menghapus kolom yang memiliki nilai “Unknown” karena merupakan kolom yang sangat penting.
Nilai Modus Nilai modus dapat kita lihat langsung pada ringkasan data di atas : - Pada kolom “Education_Level” nilai “Graduate” memiliki jumlah paling banyak (Modus : “Graduate”) - Pada kolom “Marital_Status” nilai “Married” memiliki jumlah paling banyak (Modus : “Married”) - Pada kolom “Income_Category” nilai “Less than $40K” memiliki jumlah paling banyak (Modus : “Less than $40K”)
# Mengubah nilai "Unknown" menjadi modus masing-masing kolom
# Education_Level
creditcard$Education_Level <-
creditcard$Education_Level %>%
str_replace_all(pattern = "Unknown",
replacement = "Graduate")
# Marital_Status
creditcard$Marital_Status <-
creditcard$Marital_Status %>%
str_replace_all(pattern = "Unknown",
replacement = "Married")
# Income_Category
creditcard$Income_Category <-
creditcard$Income_Category %>%
str_replace_all(pattern = "Unknown",
replacement = "Less than $40K")
Ubah kembali tipe datanya karena kita menggunakan fungsi
str_replace_all sehingga otomatis terubah menjadi tipe
string (charachter) kembali.
creditcard <-
creditcard %>%
mutate(Gender = as.factor(Gender),
Education_Level = as.factor(Education_Level),
Marital_Status = as.factor(Marital_Status),
Income_Category = as.factor(Income_Category))
Kita cek setelah di ubah setiap nilai “Unknown” menjadi nilai modus masing-masing kolom.
summary(creditcard)
#> Customer_Age Gender Education_Level Marital_Status
#> Min. :26.00 F:5358 College :1013 Divorced: 748
#> 1st Qu.:41.00 M:4769 Doctorate : 451 Married :5436
#> Median :46.00 Graduate :4647 Single :3943
#> Mean :46.33 High School :2013
#> 3rd Qu.:52.00 Post-Graduate: 516
#> Max. :73.00 Uneducated :1487
#>
#> Income_Category Months_Inactive_12_mon Credit_Limit Total_Trans_Amt
#> $120K + : 727 0: 29 Min. : 1438 Min. : 510
#> $40K - $60K :1790 1:2233 1st Qu.: 2555 1st Qu.: 2156
#> $60K - $80K :1402 2:3282 Median : 4549 Median : 3899
#> $80K - $120K :1535 3:3846 Mean : 8632 Mean : 4404
#> Less than $40K:4673 4: 435 3rd Qu.:11068 3rd Qu.: 4741
#> 5: 178 Max. :34516 Max. :18484
#> 6: 124
#> Total_Trans_Ct
#> Min. : 10.00
#> 1st Qu.: 45.00
#> Median : 67.00
#> Mean : 64.86
#> 3rd Qu.: 81.00
#> Max. :139.00
#>
Sekarang di ketiga kolom tadi (Education_Level,
Marital_Status, Income_Category) sudah tidak
memiliki nilai “Unknown”.
Insight :
Kebanyakan customer kita memiliki gender Female.
Customer kita memiliki level pendidikan terbanyak adalah Graduated dan terkecil Doctorate.
Kebanyakan customer kita sudah menikah dan single.
Kebanyakan customer kita memiliki income sekitar Less than $40K.
Kalau kita lihat kolom “Credit_Limit” dan “Total_Trans_Amt” memiliki perbedaan nilai median dengan max sangat jauh alias kita dapat menduga kolom tersebut memiliki nilai ekstrim (outlier).
Kita ingin membuktikan dugaan pada insight no 5 dengan menggunakan boxplot
Credit_Limitboxplot_cr_Limit <- boxplot(creditcard$Credit_Limit)
Total_Trans_Amtboxplot_T_Trans_Amt <- boxplot(creditcard$Total_Trans_Amt)
Kalau kita lihat dari kedua boxplot dari kedua kolom menunjukan bahwa
memang terdapat banyak sekali nilai outlier pada data kita. Hal ini
menggambarkan karakteristik customer kita yang memang beragam, apabila
nilai outlier berjumlah sedikit, hal ini dapat mengindikasikan bahwa ada
kemungkinan data yang kita peroleh salah atau memang nilai sebenarnya
(namun perlu diverifikasi lebih lanjut.
# Please run the code down below
creditcard %>%
select_if(is.numeric) %>%
hist.data.frame()
Pada tabel distribusi di atas (Yang terdiri oleh kolom bertipe numeric),
kolom yang memiliki distribusi normal adalah
Customer_Age
dan yang mendekati, yaitu Total_Trans_Ct, sedangkan kolom
Credit_Limit dan Total_Trans_Amt memiliki
distribusi tidak normal.
Algoritma Partitioning Around Medoids(PAM) atau bisa disebut K-Medoids adalah sebuah metode pengelompokan non-hierarki yang masih menjadi keluarga dekat dari metode K-Means. Metode PAM atau K-Medoids ini akan mengelompokan sekumpulan n objek menjadi ke beberapa k cluster. Cara kerja metode K-Medoids akan diawali dengan penentuan Medoids (sebuah objek yang letaknya terpusat di dalam suatu cluster).
knitr::include_graphics("assets/K-Medoids_Clustering.gif")
Penentuan Medoids itu tidak dilakukan hanya sekali, melainkan berulang sampai Medoids itu tidak bisa bergerak lagi. Mengapa tidak hanya sekali, dikarenakan peletakan Medoids belum tentu posisi paling optimal. Untuk mendapatkan posisi yang paling optimal nantinya posisi Medoids awal akan dihitung ulang total simpangannya dengan menggunakan rumus berikut di bawah ini.
\[ S = b - a \] Dimana:
a adalah cost jarak terdekat antara objek ke
medoid awalb adalah cost jarak terdekat antara objek ke
medoid baruJika S < 0, maka tukar obyek dengan data untuk membentuk sekumpulan k baru sebagai Medoid
Langkah tersebut akan terus diulang sampai nantinya S > 0, yang berarti tidak adanya pergerakan lagi dari Medoid yang dipilih sebagai titik tengah. Dari titik Medoids yang paling optimum itu, akan dicari lagi objek yang menyerupai dari karakteristik Medoids tersebut. Berikut step proses yang dilakukan :
Step 1: Menentukan medoids secara random
Step 2: Menghitung jarak antara setiap observasi data terhadap
titik medoidsnya \[
Jarak = |Xi - Xm| + |Yi - Ym|
\] Dimana: - Xi, Yi: Titik observasi
data untuk titik X & Y - Xm, Ym: Titik
medoids yang ditentukan untuk titik X & Y
Step 2.1: Menentukan observasi data masuk ke kelompok berapa Setelah mendapatkan perhitungan jarak, setiap observasi data akan dimasukan ke sebuah kelompok berdasarkan jarak yang paling dekat. Penentuan jarak yang paling dekat, berdasarkan nilai perbandingan dari masing-masing kolom.
Dari penentuan setiap observasi data masuk ke kelompok berapa, kita dapat menghitung nilai costnya \[ Cost Awal: Kelompok 1 + Kelompok 2 \] Step 3: Memilih random medoids kembali Setelah mendapatkan hasil perhitungan jarak dengan medoids pertama, akan ditentukan medoids lainnya secara random untuk menjadi pembanding.
Step 4: Bandingkan hasil cost antara medoids yang sudah ditentukan Pada tahapan ini kita sudah memiliki 2 hasil perhitungan, untuk medoids yang pertama kali ditentukan dan medoids yang kedua.
\[ S = Cost Baru - Cost Lama \] Berdasarkan asumsi yang ada, jika S>0. Maka tidak ada perubahan medoids.
Setelah berkenalan dengan data yang kita gunakan, mari kita coba implementasikan metode PAM untuk membuat segmentasi kustomer. Secara garis besar akan ada 3 langkah yang nantinya akan dilakukan, yaitu:
Dari hasil eksplorasi data, kita mengetahui bahwa total observasi data kita adalah lebih dari 10.000 baris dan setiap observasi data pastinya memiliki nilai yang berbeda. Agar nantinya hasil dari setiap kelompok terdiri dari data-data yang identik, kita harus mengetahui jarak antara satu observasi dengan observasi lainnya berdekatan atau tidak
Pilihan paling populer untuk menghitung jarak adalah Euclidean, namun metode tersebut hanya berlaku untuk data numerik saja, oleh karena itu metode Euclidean tidak berlaku di sini.
Rumus Euclidean:
\[ Euclidean Distance = {\sqrt{(p - q)^2}} \]
Dimana:
p: titik observasi 1q: titik obervasi 2Ada satu metode yang dapat kita gunakan untuk kasus yang memiliki data campuran (data numerik dan data kategorikal), metode tersebut dinamakan Gower Distance.
Metode Gower Distance nantinya akan melakukan perbandingan pada setiap observasi data yang ada terhadap data-data yang lainnya, dengan cara melakukan perhitungan skala antara kedua observasi yang dibandingkan dengan rentan 0 sampai 1.
Rumus Gower Distance:
\[ Gower Distance = \frac{1}{p}\sum\limits^p_{i=1}(Xnumeric, Xcateogrical) \]
Dimana:
p = jumlah kolomXnumeric: kondisi ketika kolom yang dibandingkan adalah
numeric\[
Xnumeric = \frac{|X_i - {Xj}|}{r}
\] * Xi = Data observasi 1 * Xj = Data
observasi 2 * r = Range dari kolom observasi tersebut
Xcategorical: Nilai yang akan diberikan ketika kolom
yang dibandingkan adalah categorical
Setelah lebih memahami dari perhitungan manual, mari kita coba implementasikan ke data kita. Di R, metode Gower Distance tersimpan pada library(cluster) dan fungsi yang bisa digunakan adalah daisy(). Pada fungsi tersebut nantinya akan ada 2 parameter yang bisa diisi, yaitu:
x: Data frame yang ingin digunakanmetric: Metode apa yang ingin digunakan, karena kita
akan menggunakan metode Gower Distance, kita bisa isi dengan
“gower”.# Please type your code
creditcard_gd <- daisy(x = creditcard,
metric = "gower")
Sebagai pembuktian apakah metode Gower Distance memang bisa menempatkan data-data kita berdasarkan kemiripannya, kita bisa mencetak pasangan yang paling mirip dan berbeda dalam data kita dengan menggunakan fungsi di bawah ini.
# Please run the code down below
example <- as.matrix(creditcard_gd)
creditcard[which(example == min(example[example != min(example)]), arr.ind = TRUE)[1, ], ]
# Please run the code down below
creditcard[which(example == max(example[example != max(example)]),
arr.ind = TRUE)[1, ], ]
Seperti yang sudah disampaikan pada bagian pendahuluan, tujuan dari melakukan clustering adalah menempatkan setiap observasi data yang ada ke beberapa kelompok yang sesuai dengan karakteristiknya atau bedasarkan kedekatan jarak antar setiap observasi. Pada langkah pertama kita sudah memiliki informasi jarak antar setiap observasi, kita akan memanfaatkan informasi tersebut untuk menentukan berapakah kelompok yang paling optimal. Hasil dari jumlah kelompok nantinya akan digunakan untuk menentukan berapa banyak segmentasi kustomer yang bisa dibuat berdasarkan data historis pembelian kustomer.
Dalam menentukan jumlah kelompok yang paling optimum, kita data
memanfaatkan metode Elbow Method. Metode tersebut dapat kita
gunakan dengan fungsi fviz_nbclust() dari
library(factoextra). Pada fungsi tersebut nantinya akan ada
3 parameter yang bisa diisi
Dengan metode pertama ini kita akan memvariasikan jumlah kelompok dengan menghitung Within Cluster Sum of Square (WSS). WSS adalah akan menghasilkan jumlah kuadrat jarak antara setiap observasi terhadap titik Medoids untuk setiap kemungkinan jumlah kelompok.
\[ WCSS = \sum\limits^N_{i=1}d(X_i - Xc)^2 \]
Dimana:
N = clusterXi = Data observationXc = Titik medoidsd(Xi - Xc): Jarak antara setiap observasi data terhadap
titik medoidsFungsi fviz_nbclust() secara otomatis akan menghitung
WSS sampai dengan 10 kelompok (jumlah kelompok yang ingin dicoba hitung
bisa diatur secara manual sesuai dengan kebutuhan).
Dengan bertambahnya jumlah kelompok, nilai WCSS akan mulai berkurang (nilai WCSS terbesar ketika K = 1). Ketika kita menganalisis grafik kita dapat melihat bahwa grafik akan berubah dengan cepat pada suatu titik dan dengan demikian menciptakan bentuk siku. Dari titik ini, grafik mulai bergerak hampir sejajar dengan sumbu X. Nilai K yang sesuai dengan titik ini adalah nilai K optimal atau jumlah kelompok yang optimal.
Fungsi set.seed() digunakan untuk mengunci random number
generator sehingga hasil sampling tidak berubah setiap kali run code.
Nilai seed yang digunakan bebas, maksimal 10 digit.
Penentual Nilai K
# Please type your code
#set.seed(123)
#fviz_nbclust(x = as.matrix(creditcard_gd),
# FUNcluster = pam,
# method = "wss",
# k.max = 5)
Notes: Penentuan nilai K akan berdasarkan nilai WCSSnya. Harapannya kita bisa memilih jumlah kelompok yang nilai WCSSnya paling kecil, akan tetapi setiap penambahan kelompok nilai WCSSnya akan semakin mengecil. Maka dari itu kita bisa memilih nilai K yang penurunnya tidak terlalu signifikan.
Secara subjektik nilai K yang penurunannya tidak terlalu landai itu berada pada nilai K = 3.
Selain menggunakan metode Elbow, terdapat dua metode lagi yang dapat kita manfaatkan yaitu Metode Silhouette & Gap Statistic.
Metode kedua yang bisa dicoba untuk menentukan jumlah kelompok yang optimal adalah Silhouette Method. Metode ini akan menghitung seberapa mirip sebuah observasi dengan kelompoknya sendiri jika dibandingkan dengan nilai kelompok lainnya.
Hasil dari perhitungannya akan memiliki rentan koefisien dari -1 sampai 1. Jika nanti hasilnya makin mendekati 1 maka observasi tersebut cocok dengan kelompoknya dan kurang cocok dengan kelompok tetangga, begitu juga sebaliknya, jika hasilnya makin mendekati -1 maka observasi tersebut tidak cocok dengan kelompoknya akan tetapi lebih cocok dengan kelompok tetangganya.
Berbeda dengan elbow method, makin bertambahnya jumlah kelompok, nilai hasil perhitungan metode silhouette method tidak pasti akan berkurang. Penentuan nilai kelompok yang optimal akan ditentukan berdasarkan nilai koefisien paling tinggi pada saat membagi keseluruhan observasi ke berapa banyak kelompok.
#set.seed(123)
#fviz_nbclust(x = as.matrix(creditcard_gd),
# FUNcluster = pam,
# method = "silhouette",
# k.max = 5) +
# labs(subtitle = "Silhouette Method")
Metode terakhir yang bisa dicoba adalah Gap Statistic Method, metode ini akan menghitung seberapa berbeda total variansi antara setiap observasi pada sebuah kelompok terhadap observasi yang terdapat pada kelompok lainnya. Penentuannya akan berdasarkan nilai statistic yang didapatkan, nilai statistik yang dihasilkan akan memiliki rentan 0-1, semakin mendekat satu berarti bervariansi antara setiap observasi kelompok dengan yang lainnya.
#set.seed(123)
#fviz_nbclust(x = as.matrix(creditcard_gd),
# FUNcluster = pam,
# method = "gap_stat",
# k.max = 5,) +
# labs(subtitle = "Gap Statistic Method")
Dislaimer: Penentuan jumlah kelompok tidak wajib menggunakan 3 metode pengujian di atas, penentuan kelompok juga dapat ditentukan berdasarkan pertanyaan bisnis atau kesepakatan bersama.
Saya telah berusaha berjam-jam menjalankan salah satu method di atas untuk mendapatkan nilai K optimal, namun tetap saja belum bisa. Oleh karena itu, saya mengakalinya dengan mencoba opsi K dari 2 hingga 6. Berikut gambar visualisasi setiap K :
knitr::include_graphics("assets/K2.png")
knitr::include_graphics("assets/K3.png")
- K = 4
knitr::include_graphics("assets/K4.png")
knitr::include_graphics("assets/K5.png")
knitr::include_graphics("assets/K6.png")
Jadi, saya rasa K = 2 lebih baik karena ketika K = 3 cukup banyak datanya tercampur sehingga sulit melihat pola klasifikasi data, begitu pula dengan K > 3 yang semakin kurang jelas pola pengelompokannya.
Sekarang kita bisa memulai tahapan terakhir yaitu mengelompokan semua
data customer ke kelompok yang sudah ditentukan dengan menggunakan
fungsi pam(). Pada fungsi tersebut nantinya akan ada 2
parameter yang bisa diisi, yaitu:
x = Data frame yang ingin digunakank = Jumlah kelompok# Please type your code
pam_fit <- pam(x = creditcard_gd,
k = 2)
Fungsi di atas akan membantu kita untuk mengelompokan keseluruhan observasi data ke beberapa kelompok berdasarkan kemiripan setiap observasi terhadap titik pusat atau medoids. Supaya kita bisa mendapatkan intuisi awal bagaimana karakteristik customer untuk setiap kelompoknya, kita bisa melihat dari tabel di bawah ini.
# Please type your code
creditcard[pam_fit$medoids, ]
Seperti yang sudah disampaikan, dengan melihat tabel di atas kita hanya bisa mendapatkan intuisi awal bagaimana karakteristik dari masing-masing kelompok yang dibuat. Supaya kita dapat melakukan interpretasi lebih detail dan melihat apakah pengelompokan yang kita lakukan sudah dapat memisahkan setiap observasi data dengan baik, kita bisa memanfaatkan metode statistik deskriptif dan visualisasi.
Jika dengan menggunakan metode statistik deskriptif kita bisa memahami karakteristik dari masing-masing kelompok, metode visualisasi dapat membantu kita untuk menilai bagaimana hasil pengelompokan. Metode visualisasi yang akan digunakan adalah metode t-SNE, metode ini merupakan salah satu cara untuk memvisualisasikan data yang tidak hanya memiliki nilai numerik saja melainkan nilai kategorikal juga.
# Please type your code
set.seed(123)
tsnse_obj <- Rtsne(X = creditcard_gd,
is_distance = TRUE)
tsnse_dataframe <- tsnse_obj$Y %>%
data.frame() %>%
setNames(c("X", "Y")) %>%
mutate(cluster = factor(pam_fit$clustering))
tsnse_dataframe %>% head()
ggplot(data = tsnse_dataframe, mapping = aes(x = X, y = Y)) +
geom_point(mapping = aes(color = cluster)) +
theme(plot.title = element_text(hjust = 0.5)) +
labs(title = "Gambaran Pengelompokan Data Setelah Disesuaikan Dimensinya")
Tujuan melakukan statistik deskriptif adalah untuk memahami karakteristik masing-masing kelompok, dan dalam kasus ini untuk mengetahui karakteristik untuk setiap segmentasi kustomer.
# Please type your code
pam_result <-
creditcard %>%
mutate(cluster = pam_fit$clustering) %>%
group_by(cluster) %>%
do(the_summary = summary(.))
pam_result$the_summary[[1]]
#> Customer_Age Gender Education_Level Marital_Status
#> Min. :26.00 F: 0 College : 464 Divorced: 331
#> 1st Qu.:41.00 M:4539 Doctorate : 184 Married :2489
#> Median :46.00 Graduate :2046 Single :1719
#> Mean :46.15 High School : 939
#> 3rd Qu.:52.00 Post-Graduate: 244
#> Max. :73.00 Uneducated : 662
#>
#> Income_Category Months_Inactive_12_mon Credit_Limit Total_Trans_Amt
#> $120K + : 727 0: 9 Min. : 1438 Min. : 530
#> $40K - $60K : 776 1:1009 1st Qu.: 4188 1st Qu.: 1882
#> $60K - $80K :1402 2:1495 Median : 9502 Median : 3533
#> $80K - $120K :1535 3:1727 Mean :13166 Mean : 4527
#> Less than $40K: 99 4: 182 3rd Qu.:19773 3rd Qu.: 4745
#> 5: 67 Max. :34516 Max. :18484
#> 6: 50
#> Total_Trans_Ct cluster
#> Min. : 10.00 Min. :1
#> 1st Qu.: 42.00 1st Qu.:1
#> Median : 64.00 Median :1
#> Mean : 63.36 Mean :1
#> 3rd Qu.: 80.00 3rd Qu.:1
#> Max. :139.00 Max. :1
#>
pam_result$the_summary[[2]]
#> Customer_Age Gender Education_Level Marital_Status
#> Min. :26.00 F:5358 College : 549 Divorced: 417
#> 1st Qu.:41.00 M: 230 Doctorate : 267 Married :2947
#> Median :46.00 Graduate :2601 Single :2224
#> Mean :46.47 High School :1074
#> 3rd Qu.:52.00 Post-Graduate: 272
#> Max. :70.00 Uneducated : 825
#>
#> Income_Category Months_Inactive_12_mon Credit_Limit Total_Trans_Amt
#> $120K + : 0 0: 20 Min. : 1438 Min. : 510
#> $40K - $60K :1014 1:1224 1st Qu.: 2164 1st Qu.: 2400
#> $60K - $80K : 0 2:1787 Median : 3037 Median : 4109
#> $80K - $120K : 0 3:2119 Mean : 4949 Mean : 4305
#> Less than $40K:4574 4: 253 3rd Qu.: 5509 3rd Qu.: 4739
#> 5: 111 Max. :34516 Max. :17437
#> 6: 74
#> Total_Trans_Ct cluster
#> Min. : 12.00 Min. :2
#> 1st Qu.: 47.00 1st Qu.:2
#> Median : 69.00 Median :2
#> Mean : 66.08 Mean :2
#> 3rd Qu.: 81.00 3rd Qu.:2
#> Max. :138.00 Max. :2
#>