LBB: Spotify


1. Pendahuluan

library(dplyr)
library(tidyr)
library(GGally)
library(gridExtra)
library(factoextra)
library(FactoMineR)
library(plotly)

options(scipen = 100, max.print = 1e+06)

Pada LBB (Learning by Building) ini akan dilakukan analisis clustering dan principle component analysis dari dataset spotify (https://www.kaggle.com/datasets/bricevergnou/spotify-recommendation).

2. Mengimport Data

Hal paling pertama yang harus dilakukan adalah pastikan lokasi folder dataset yang ingin diinput sama dengan Rmd ini. Kemudian, lanjut dengan read dataset.

spotify <- read.csv("spotifyrecom.csv")

Dataset telah terbaca dan terinput dengan nama spotify. Untuk mengetahui isi dataset tersebut, lakukan ke tahap selanjutnya yaitu dengan cara menginspeksi data.

3. Menginspeksi Data

head(spotify,3)
dim (spotify)
#> [1] 195  14

Terlihat bahwa data terdiri dari 195 baris dan 14 kolom. Kemudian, cek missing value apakah ada atau tidak

anyNA(spotify)
#> [1] FALSE
colSums(is.na(spotify))
#>     danceability           energy              key         loudness 
#>                0                0                0                0 
#>             mode      speechiness     acousticness instrumentalness 
#>                0                0                0                0 
#>         liveness          valence            tempo      duration_ms 
#>                0                0                0                0 
#>   time_signature            liked 
#>                0                0

Terlihat bahwa tidak ada missing value, sehingga data siap diolah ke tahap selanjutnya.

4. Mengolah Data

glimpse(spotify)
#> Rows: 195
#> Columns: 14
#> $ danceability     <dbl> 0.803, 0.762, 0.261, 0.722, 0.787, 0.778, 0.666, 0.92~
#> $ energy           <dbl> 0.6240, 0.7030, 0.0149, 0.7360, 0.5720, 0.6320, 0.589~
#> $ key              <int> 7, 10, 1, 3, 1, 8, 0, 7, 7, 3, 9, 1, 1, 6, 8, 5, 8, 8~
#> $ loudness         <dbl> -6.764, -7.951, -27.528, -6.994, -7.516, -6.415, -8.4~
#> $ mode             <int> 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1,~
#> $ speechiness      <dbl> 0.0477, 0.3060, 0.0419, 0.0585, 0.2220, 0.1250, 0.324~
#> $ acousticness     <dbl> 0.4510000, 0.2060000, 0.9920000, 0.4310000, 0.1450000~
#> $ instrumentalness <dbl> 0.00073400, 0.00000000, 0.89700000, 0.00000118, 0.000~
#> $ liveness         <dbl> 0.1000, 0.0912, 0.1020, 0.1230, 0.0753, 0.0912, 0.114~
#> $ valence          <dbl> 0.6280, 0.5190, 0.0382, 0.5820, 0.6470, 0.8270, 0.776~
#> $ tempo            <dbl> 95.968, 151.329, 75.296, 89.860, 155.117, 140.951, 74~
#> $ duration_ms      <int> 304524, 247178, 286987, 208920, 179413, 224029, 14605~
#> $ time_signature   <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,~
#> $ liked            <int> 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0,~

Hapus kolom yang tidak diperlukan

spotify1 <- spotify %>%
  select(-c(key, mode, time_signature, liked, loudness, tempo, duration_ms))

Kemudian, cek isi data yang baru apakah sudah sesuai dengan yang diharapkan

head(spotify1,3)

5. Exploratory Data Analysis

Apakah antar variabel memiliki skala yang sama? Mari kita cek range untuk tiap kolom:

summary(spotify1)
#>   danceability        energy        speechiness      acousticness     
#>  Min.   :0.1300   Min.   :0.0024   Min.   :0.0278   Min.   :0.000003  
#>  1st Qu.:0.4625   1st Qu.:0.5335   1st Qu.:0.0568   1st Qu.:0.042200  
#>  Median :0.7050   Median :0.6590   Median :0.0962   Median :0.213000  
#>  Mean   :0.6367   Mean   :0.6384   Mean   :0.1490   Mean   :0.319093  
#>  3rd Qu.:0.7990   3rd Qu.:0.8375   3rd Qu.:0.2305   3rd Qu.:0.504000  
#>  Max.   :0.9460   Max.   :0.9960   Max.   :0.5400   Max.   :0.995000  
#>  instrumentalness       liveness         valence      
#>  Min.   :0.0000000   Min.   :0.0331   Min.   :0.0353  
#>  1st Qu.:0.0000000   1st Qu.:0.0840   1st Qu.:0.2690  
#>  Median :0.0000076   Median :0.1050   Median :0.5250  
#>  Mean   :0.1923373   Mean   :0.1485   Mean   :0.4936  
#>  3rd Qu.:0.0975000   3rd Qu.:0.1770   3rd Qu.:0.7175  
#>  Max.   :0.9690000   Max.   :0.6330   Max.   :0.9800

Lihat variance yang dirangkum tiap PC

plot(prcomp(spotify1))

Lakukan normalisasi/standarisasi skala dari variabel numerik dengan fungsi ‘scale()’

spotify1_scale <- scale(spotify1)
summary(spotify1_scale)
#>   danceability         energy          speechiness       acousticness    
#>  Min.   :-2.3390   Min.   :-2.44537   Min.   :-1.0062   Min.   :-0.9947  
#>  1st Qu.:-0.8040   1st Qu.:-0.40343   1st Qu.:-0.7653   1st Qu.:-0.8632  
#>  Median : 0.3155   Median : 0.07908   Median :-0.4381   Median :-0.3307  
#>  Mean   : 0.0000   Mean   : 0.00000   Mean   : 0.0000   Mean   : 0.0000  
#>  3rd Qu.: 0.7495   3rd Qu.: 0.76537   3rd Qu.: 0.6772   3rd Qu.: 0.5764  
#>  Max.   : 1.4281   Max.   : 1.37476   Max.   : 3.2475   Max.   : 2.1071  
#>  instrumentalness     liveness          valence       
#>  Min.   :-0.5555   Min.   :-1.0885   Min.   :-1.7121  
#>  1st Qu.:-0.5555   1st Qu.:-0.6082   1st Qu.:-0.8391  
#>  Median :-0.5555   Median :-0.4101   Median : 0.1172  
#>  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
#>  3rd Qu.:-0.2739   3rd Qu.: 0.2694   3rd Qu.: 0.8363  
#>  Max.   : 2.2432   Max.   : 4.5723   Max.   : 1.8169
plot(prcomp(spotify1_scale))

Cek hubungan antar variabel yang ada

library(GGally)
ggcorr(spotify1_scale, label = T)

Kesimpulan: Terdapat korelasi yang kuat antar variabel yaitu valence dan danceability.

Principal Component Analysis

spotify_pca <- prcomp(spotify1_scale, scale. = F)
summary(spotify_pca)
#> Importance of components:
#>                           PC1    PC2    PC3    PC4     PC5     PC6    PC7
#> Standard deviation     1.6986 1.2490 0.9606 0.8953 0.66258 0.47836 0.4030
#> Proportion of Variance 0.4122 0.2229 0.1318 0.1145 0.06272 0.03269 0.0232
#> Cumulative Proportion  0.4122 0.6351 0.7669 0.8814 0.94411 0.97680 1.0000

Ingin mempertahankan informasi pada data sebanyak ~80%, PC1 sampai 4 akan dipertahankan

Buat dataset baru hasil PC yang dipertahankan, simpanlah dalam object spotify_wbcd

spotify_wbcd <- as.data.frame(spotify_pca$x[, 1:4])
head(spotify_wbcd)

*Menggunakan PCA() dari library FactoMineR, dan jangan lupa untuk scaling hanya dilakukan sekali saja

# your code here
library(FactoMineR)
spotify_pca1 <- PCA(X = spotify1_scale,
              scale.unit = F,
              graph = F)

Visualize

Visualisasikan individual factor plot, dan identifikasi 5 outlier terluar

plot.PCA(x = spotify_pca1,
         choix = "ind",
         select="contrib 5")

Kesimpulan: Tidak ada outlier.

fviz_contrib(X = spotify_pca1,
             choice = "var",
             axes = 1)

Kesimpulan: 3 variabel yang paling berkontribusi pada PC 1 berdasarkan korelasi antara variabel dengan PC 1 adalah instrumentalness, danceability dan valence.

Choose Optimum K

# function
RNGkind(sample.kind = "Rounding")
kmeansTunning <- function(data, maxK) {
  withinall <- NULL
  total_k <- NULL
  for (i in 1:maxK) {
    set.seed(4)
    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")
}

# apply function
# kmeansTunning(your_data, maxK = 5)

kmeansTunning(spotify1_scale, maxK = 5)

Dipilih titik dimana penurunan total within sum of squares tidak lagi signifikan/melandai (titik elbow). Berdasarkan hasil elbow plot kita akan memilih nilai k = 2.

K-means Clustering

Lakukan k-means clustering berdasarkan elbow method sebelumnya dan simpan hasilnya pada objek ws_kmeans

RNGkind(sample.kind = "Rounding")
set.seed(333)

# your code here
ws_kmeans <- kmeans(x = spotify1_scale,
                    centers = 2)

Cluster Profiling

Kembalikan label cluster masing-masing observasi ke data awal sebelum di-scale, namun yang outliernya sudah di-remove

# your code here
spotify1$kelompok <- ws_kmeans$cluster

Lakukan profiling cluster dengan mencari nilai rata-rata untuk masing-masing produk

# your code here
spotify1 %>% 
  group_by(kelompok) %>% 
  summarise_all(mean)

Profiling:

  • Cluster 1: Paling rendah di speechiness, Paling tinggi di instrumentalness
  • Cluster 2: Paling rendah di instrumentalness, Paling tinggi di danceability
library(ggiraphExtra)
ggRadar(data=spotify1, aes(colour=kelompok), interactive=TRUE)

6. Kesimpulan

  1. Dengan menggunakan PCA diperoleh 3 variabel yang paling berkontribusi pada PC 1 berdasarkan korelasi antara variabel dengan PC 1 adalah instrumentalness, danceability dan valence.

  2. Dengan menggunakan K-means Clustering, diperoleh 2 cluster yaitu:

  • Cluster 1: Paling rendah di speechiness, Paling tinggi di instrumentalness
  • Cluster 2: Paling rendah di instrumentalness, Paling tinggi di danceability