1 Pendahuluan

1.1 Clustering

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.

1.2 Stigma

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.

1.3 Machine Learning Pada Clustering

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.

1.4 Contoh Clustering Machine Learning

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.

2 Pembahasan

2.1 Library

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)

2.2 Dataset

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 Client
  • Customer_Age: Umur customer
  • Gender: gender customer
  • Education_Level: Tingkat pendidikan
  • Marital_Status: Status Pernikahan
  • Income_Category: Range pendapatan
  • Months_Inactive_12_mon: Selama 12 bulan terakhir sempat tidak menggunakan kartu kredit berapa lama
  • Credit_Limit: Limmit dari creditcard
  • Total_Trans_Amt: Jumlah amount transaksi yang dilakukan selama 12 bulan terakhir
  • Total_Trans_Ct: Total transaksi yang dilakukan selama 12 bulan terakhir

Role 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.

2.3 Data Wrangling

  1. Menyesuaikan tipe data
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,…
  1. Menyesuaikan tipe data
    • CLIENTNUM -> menjadi nama kolom.
    • Gender -> factor
    • Education_Level -> factor
    • Marital_Status -> factor
    • Income_Category -> factor
    • Months_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,…

2.4 Explorasi Data

2.4.1 Mengecek ringkasan Dataset

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

2.4.2 Menyelesaikan missing value

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 :

  1. Kebanyakan customer kita memiliki gender Female.

  2. Customer kita memiliki level pendidikan terbanyak adalah Graduated dan terkecil Doctorate.

  3. Kebanyakan customer kita sudah menikah dan single.

  4. Kebanyakan customer kita memiliki income sekitar Less than $40K.

  5. 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).

2.4.3 Further EDA

Kita ingin membuktikan dugaan pada insight no 5 dengan menggunakan boxplot

  • Kolom Credit_Limit
boxplot_cr_Limit <- boxplot(creditcard$Credit_Limit)

  • Kolom Total_Trans_Amt
boxplot_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.

2.4.4 Melihat Tabel Distribusi

# 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.

2.5 Clustering

2.5.1 Partitioning Around Medoids(PAM)

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).

  • Intuisi penentuan medoids pada PAM/K-Medoids:
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 awal
  • b adalah cost jarak terdekat antara objek ke medoid baru

Jika 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.

2.5.2 Implementasi Partisioning Around 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:

  • Perhitungan jarak antar observasi data
  • Penentuan jumlah cluster
  • Pembuatan cluster

2.5.2.1 Perhitungan Jarak

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 1
  • q: titik obervasi 2

Ada 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.

  • Jika hasil dari perbandingannya mendekati 0 maka bisa dibilang kedua data tersebut identik atau jarak antara kedua observasi tersebut berdekatan.
  • Jika rentan perbandingannya mendekati 1 bisa dibilang kedua data tersebut tidak identik atau jarak antara kedua observasi tersebut berjauhan.

Rumus Gower Distance:

\[ Gower Distance = \frac{1}{p}\sum\limits^p_{i=1}(Xnumeric, Xcateogrical) \]

Dimana:

  • p = jumlah kolom
  • Xnumeric: 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
    • Jika pada kolom kategorikal yang dibandingkan berbeda maka akan diberikan 1
    • Jika pada kolom kategorikal yang dibandingkan *tidak berbeda (sama) maka akan diberikan 0

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 digunakan
  • metric: 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.

  • Contoh pasangan data yang paling identik
# Please run the code down below
example <- as.matrix(creditcard_gd)

creditcard[which(example == min(example[example != min(example)]), arr.ind = TRUE)[1, ], ]
  • Contoh pasangan data yang paling tidak identik
# Please run the code down below
creditcard[which(example == max(example[example != max(example)]),
        arr.ind = TRUE)[1, ], ]

2.5.2.2 Penentuan Jumlah Cluster

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

  • Elbow Method

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 = cluster
  • Xi = Data observation
  • Xc = Titik medoids
  • d(Xi - Xc): Jarak antara setiap observasi data terhadap titik medoids

Fungsi 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 Silhoutte

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 Gap Statistic

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.

2.5.2.2.1 Penjelasan Menentukan K

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 :

  • K = 2
knitr::include_graphics("assets/K2.png")

  • K = 3
knitr::include_graphics("assets/K3.png")

- K = 4

knitr::include_graphics("assets/K4.png")

  • K = 5
knitr::include_graphics("assets/K5.png")

  • K = 6
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.

2.5.2.3 Pembuatan Cluster

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 digunakan
  • k = 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.

2.5.3 Interpretasi

2.5.3.1 Metode 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")

2.5.3.2 Metode Deskriptif

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(.))

3 Penutup

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  
#> 

3.1 Insight Pertama

  • Semua data pada cluster 1 memiliki gender laki-laki.
  • Level pendidikan pada cluster 1 didominasi oleh Graduate dan paling sedikit adalah Doctorate.
  • 64.70 % customer kita pada cluster 1 memiliki pendapatan $60K - $120K (1402+1535)/4539 = 0.6470
  • 93.21 % customer kita pernah Inactivate sekitar 1 - 3 bulan selama 12 bulan.
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  
#> 

3.2 Insight Kedua

  • Pada cluster 2 memiliki dominasi gender wanita.
  • Level pendidikan pada cluster 1 didominasi oleh Graduate dan paling sedikit adalah Doctorate.
  • 81.85 % customer kita memiliki pendapatan kurang dari $40K dan 18.15 % memiliki pendapatan $40K - $60K.
  • 91.80 % customer kita pernah Inactivate sekitar 1 - 3 bulan selama 12 bulan.