library(dplyr)
library(FactoMineR)
library(factoextra)

1 Read and Inspect Data

Business Question:

Perusahaan memiliki data pembelian ragam tipe produk dari masing-masing customer, lalu ingin dilakukan segmentasi customer dari sebuah perusahaan wholesale berdasarkan karakteristik tiap customer dalam membeli produk.

wholesale <- read.csv("wholesale.csv")
head(wholesale)

Deskripsi kolom:

  • Channel: Horeca/Retail
  • Region: Lokasi branch perusahaan wholesale
  • Fresh, Milk, Grocery, Frozen, Detergents_Paper, Delicassen: jumlah pembelian untuk masing-masing tipe produk

2 Data Cleaning

Menghapus kolom yang tidak diperlukan

wholesale <- wholesale %>% 
  select(-c(Channel, Region))

3 EDA

Cek missing value

colSums(is.na(wholesale))
#>            Fresh             Milk          Grocery           Frozen 
#>                0                0                0                0 
#> Detergents_Paper       Delicassen 
#>                0                0

Cek summary

summary(wholesale)
#>      Fresh             Milk          Grocery          Frozen       
#>  Min.   :     3   Min.   :   55   Min.   :    3   Min.   :   25.0  
#>  1st Qu.:  3128   1st Qu.: 1533   1st Qu.: 2153   1st Qu.:  742.2  
#>  Median :  8504   Median : 3627   Median : 4756   Median : 1526.0  
#>  Mean   : 12000   Mean   : 5796   Mean   : 7951   Mean   : 3071.9  
#>  3rd Qu.: 16934   3rd Qu.: 7190   3rd Qu.:10656   3rd Qu.: 3554.2  
#>  Max.   :112151   Max.   :73498   Max.   :92780   Max.   :60869.0  
#>  Detergents_Paper    Delicassen     
#>  Min.   :    3.0   Min.   :    3.0  
#>  1st Qu.:  256.8   1st Qu.:  408.2  
#>  Median :  816.5   Median :  965.5  
#>  Mean   : 2881.5   Mean   : 1524.9  
#>  3rd Qu.: 3922.0   3rd Qu.: 1820.2  
#>  Max.   :40827.0   Max.   :47943.0

Insight: Perlu dilakukan scalling karena skala antar variable berbeda / range-nya terlalu kontras.

4 PCA

Sebelum melakukan clustering, mari lihat apakah terdapat outlier pada data. Outlier akan sangat mempengaruhi hasil clustering sehingga akan lebih baik bila kita menghilangkan terlebih dahulu outlier dari data. Outlier dapat divisualisasikan dengan biplot dari hasil PCA. Buat PCA dengan fungsi PCA() dan plot observasi dengan plot.PCA()!

Note: scaling hanya dilakukan 1 kali

wholesale_pca <- PCA(X = wholesale,
                     scale.unit = T)

Insight: Dari plot diketahui bahwa kelompok produk Milk, Grocery, dan Detergents_Paper memiliki kontribusi tinggi terhadap Dim 1 atau PC 1. Sedangkan kelompok produk Fresh, Frozen, dan Delicassen memiliki kontribusi tinggi terhadap Dim 2 atau PC 2. Kedua kelompok produk tersebut tidak saling berkorelasi.

Buat plot, visualisasikan 10 outlier terluar.

plot.PCA(x = wholesale_pca,
         choix = "ind",
         select = "contrib10")

Simpan indeks outlier dalam objek

outlier <- wholesale[-c(184,326,182,24,48,87,61,66,334,86),]

Sekarang kita dapat membuang observasi outlier dari data awal dan menyimpannya ke objek ws_normal untuk digunakan pada clustering.

Buang data outlier

ws_normal <- outlier

Cek variansi yang dirangkum tiap PC

wholesale_pca$eig
#>        eigenvalue percentage of variance cumulative percentage of variance
#> comp 1 2.64497357              44.082893                          44.08289
#> comp 2 1.70258397              28.376400                          72.45929
#> comp 3 0.74006477              12.334413                          84.79371
#> comp 4 0.56373023               9.395504                          94.18921
#> comp 5 0.28567634               4.761272                          98.95048
#> comp 6 0.06297111               1.049519                         100.00000

5 Clustering

Sebelum melakukan clustering, pastikan data kita hanya terdiri dari kolom numerik yang akan digunakan untuk clustering dan sudah bebas dari outlier yang dapat mengganggu.

summary(ws_normal)
#>      Fresh            Milk          Grocery          Frozen     
#>  Min.   :    3   Min.   :   55   Min.   :    3   Min.   :   25  
#>  1st Qu.: 3098   1st Qu.: 1497   1st Qu.: 2132   1st Qu.:  744  
#>  Median : 8224   Median : 3596   Median : 4630   Median : 1526  
#>  Mean   :11561   Mean   : 5164   Mean   : 7263   Mean   : 2843  
#>  3rd Qu.:16641   3rd Qu.: 7011   3rd Qu.:10066   3rd Qu.: 3491  
#>  Max.   :76237   Max.   :38369   Max.   :59598   Max.   :35009  
#>  Detergents_Paper   Delicassen     
#>  Min.   :    3    Min.   :    3.0  
#>  1st Qu.:  256    1st Qu.:  405.2  
#>  Median :  788    Median :  946.5  
#>  Mean   : 2571    Mean   : 1346.8  
#>  3rd Qu.: 3806    3rd Qu.: 1779.0  
#>  Max.   :26701    Max.   :14472.0

Scaling

Sebelum melakukan clustering, perlu dilakukan scalling untuk menyeragamkan skala antar variable. Scalling pada saat PCA dilakukan hanya untuk observasi data dan tidak di-assign sebagai data processing, sedangkan scalling yang dilakukan disini akan di-assign pada data sebagai tahap processing untuk Clustering.

ws_scale <- scale(ws_normal)

5.0.1 Pilih k Optimum

# fungsi tuning k berdasarkan wss
RNGkind(sample.kind = "Rounding")
kmeansTunning <- function(data, maxK) {
  withinall <- NULL
  total_k <- NULL
  for (i in 2:maxK) {
    set.seed(101)
    temp <- kmeans(data,i)$tot.withinss
    withinall <- append(withinall, temp)
    total_k <- append(total_k,i)
  }
  plot(x = total_k, y = withinall, type = "o", xlab = "Number of Cluster", ylab = "Total within")
}

# kmeansTunning(your_data, maxK = 10)
kmeansTunning(ws_scale, maxK = 10)

Insight: Dalam pemilihan k dapat dilakukan berdasarkan elbow method, yaitu kita ambil nilai k ketika penurunan total within sum of squares tidak lagi signifikan. Atau jika dilihat dalam plot, nilai k dipilih saat grafik mulai melandai. Dari plot diatas, berdasarkan elbow method kita pilih nilai k = 6.

Buat clustering dan simpan hasil clustering pada objek ws_kmeans

RNGkind(sample.kind = "Rounding")
set.seed(101)
ws_kmeans <- kmeans(ws_scale, centers = 6)

5.1 Cluster Profiling

Kembalikan hasil cluster ke data awal

ws_normal$cluster <- ws_kmeans$cluster

Profiling

ws_normal %>% 
  group_by(cluster) %>% # kelompokan berdasarkan cluster
  summarise_all(mean)

Insight:

  • Cluster 1: Customer yang banyak membeli produk Detergent Paper, Milk, dan Grocery
  • Cluster 2: Customer yang banyak membeli produk Delicassen
  • Cluster 3: Customer yang banyak membeli produk Fresh
  • Cluster 4: Customer tanpa preferensi tipe produk tertentu
  • Cluster 5: Customer yang banyak membeli produk Frozen
  • Cluster 6: Customer tanpa preferensi tipe produk tertentu

6 Conclusion

Visualisasi Cluster

fviz_cluster(ws_kmeans, data = ws_normal)

Data Tabular

ws_normal %>% 
  group_by(cluster) %>% 
  summarise(sum_of_customer = length(cluster))

Kesimpulan:

  • Setelah diproses, perilaku dan segmentasi customer dalam data wholesale dapat dibagi menjadi 6 cluster / kelompok.
  • Perilaku tiap kelompok customer berbeda antara cluster satu dengan yang lain.
  • Meskipun telah dibagi menjadi beberapa kelompok dengan behavior pembelian yang spesifik, namun mayoritas customer tergolong dalam cluster 4, dimana pada kelompok ini tidak ada behavior khusus terhadap pembelian suatu tipe produk tertentu.