# chunk options
knitr::opts_chunk$set(
  message = FALSE,
  warning = FALSE
)

1 Introduction

Machine learning bertujuan untuk membuat mesin yang belajar berdasarkan data.

LBB ini akan menganalisa pengelompokan berdasarkan karakteristik fitur-fitur audio dalam lagu yang diputar di Spotify, menggunakan data dari link berikut: https://www.kaggle.com/zaheenhamidani/ultimate-spotify-tracks-db

he spotify API allows us to create a simple server-side application that accesses user related data from the Spotify app. It also gives you access to information that is not available on the app, such as artist popularity, song metrics, album cover images, etc. It allows you to create, delete and modify existing playlists in a user’s account.

The goal of this project is to use a clustering algorithm to break down a large playlist into smaller ones. For this, song metrics such as ‘danceability’, ‘valence’, ‘tempo’, ‘liveness’, ‘speechiness’ are used.

In this project, we employ two main techniques to analyze and categorize songs based on their audio characteristics in the Spotify dataset. The first technique is k-means clustering, which groups songs with similar audio features into clusters. This step allows us to identify natural groupings of songs with comparable musical traits.

The second technique we utilize is Principal Component Analysis (PCA). PCA helps us reduce the high-dimensional audio feature space into a lower-dimensional space represented by principal components. These principal components capture the most significant variations in the data, making it easier to visualize and comprehend.

By integrating PCA with k-means clustering, we gain a comprehensive understanding of the relationships between songs and their audio characteristics. The reduced dimensionality through PCA allows us to create visual representations that reveal the underlying structure of the song data in a more interpretable manner. Furthermore, the principal components give us valuable insights into the key audio features that heavily influence the clustering of songs, thereby providing valuable information about the main traits that define each group of songs.

Kita menggunakan pendekatan Unsupervised Learning yang mempunyai ciri:

  • Tidak memiliki target variable.

  • Tujuannya untuk mencari pola dalam data, yang berguna untuk menghasilkan informasi.

  • Tidak ada ground truth sehingga tidak ada evaluasi model

1.1 Data Understanding

Before diving into the project, we’ll need to import the required libraries to facilitate our analysis.

library(tidyverse) # For data processing and visualization
library(tidyr)
library(ggplot2) # ggplot visualization
library(ggthemes) # ggplot theme
library(GGally) # ggplot2 for correlation matrix and survival plots
library(FactoMineR) # PCA exploratory multivariate data analysis
library(corrplot) # correlation plot
library(factoextra) # plot fviz contribution, elbow method of PCA
library(caret) # Confusion Matrix # pre-process and scale the data
library(ggiraphExtra) # Make advance visualize : Radar
options(scipen=999)

And then import our data

spotify <- read.csv("datasets/SpotifyFeatures.csv")
dim(spotify)
## [1] 232725     18
head(spotify)
glimpse(spotify)
## Rows: 232,725
## Columns: 18
## $ genre            <chr> "Movie", "Movie", "Movie", "Movie", "Movie", "Movie",…
## $ artist_name      <chr> "Henri Salvador", "Martin & les fées", "Joseph Willia…
## $ track_name       <chr> "C'est beau de faire un Show", "Perdu d'avance (par G…
## $ track_id         <chr> "0BRjO6ga9RKCKjfDqeFgWV", "0BjC1NfoEOOusryehmNudP", "…
## $ popularity       <int> 0, 1, 3, 0, 4, 0, 2, 15, 0, 10, 0, 2, 4, 3, 0, 0, 0, …
## $ acousticness     <dbl> 0.61100, 0.24600, 0.95200, 0.70300, 0.95000, 0.74900,…
## $ danceability     <dbl> 0.389, 0.590, 0.663, 0.240, 0.331, 0.578, 0.703, 0.41…
## $ duration_ms      <int> 99373, 137373, 170267, 152427, 82625, 160627, 212293,…
## $ energy           <dbl> 0.9100, 0.7370, 0.1310, 0.3260, 0.2250, 0.0948, 0.270…
## $ instrumentalness <dbl> 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.123…
## $ key              <chr> "C#", "F#", "C", "C#", "F", "C#", "C#", "F#", "C", "G…
## $ liveness         <dbl> 0.3460, 0.1510, 0.1030, 0.0985, 0.2020, 0.1070, 0.105…
## $ loudness         <dbl> -1.828, -5.559, -13.879, -12.178, -21.150, -14.970, -…
## $ mode             <chr> "Major", "Minor", "Minor", "Major", "Major", "Major",…
## $ speechiness      <dbl> 0.0525, 0.0868, 0.0362, 0.0395, 0.0456, 0.1430, 0.953…
## $ tempo            <dbl> 166.969, 174.003, 99.488, 171.758, 140.576, 87.479, 8…
## $ time_signature   <chr> "4/4", "4/4", "5/4", "4/4", "4/4", "4/4", "4/4", "4/4…
## $ valence          <dbl> 0.8140, 0.8160, 0.3680, 0.2270, 0.3900, 0.3580, 0.533…

Metadata:

Data ini berisi lagu yang ada di streaming platform spotify yang diberikan fitur audio yang penjelasannya dapat dilihat pada link berikut : https://developer.spotify.com/documentation/web-api/reference/tracks/get-audio-features/

  • acousticness: A confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.

  • danceability: Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.

  • energy: Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.

  • instrumentalness: Predicts whether a track contains no vocals. “Ooh” and “aah” sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly “vocal”. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.

  • key: The key the track is in. Integers map to pitches using standard Pitch Class notation. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on. If no key was detected, the value is -1.

  • liveness: Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.

  • loudness: The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typically range between -60 and 0 db.

  • mode: Mode indicates the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0.

  • speechiness: Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.

  • tempo: The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.

  • time_signature: An estimated time signature. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure). The time signature ranges from 3 to 7 indicating time signatures of “3/4”, to “7/4”.

  • valence: A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).

Summary :

Data Spotify terdiri dari 232725 baris dan 18 kolom dengan deskripsi masing-masing kolom sebagai berikut:

  1. genre: Genre dari lagu dalam bentuk teks (chr).

  2. artist_name: Nama artis yang membuat lagu dalam bentuk teks (chr).

  3. track_name: Nama lagu dalam bentuk teks (chr).

  4. track_id: ID unik yang mengidentifikasi lagu dalam bentuk teks (chr).

  5. popularity: Tingkat popularitas lagu dalam bentuk angka (int).

  6. acousticness: Ukuran tingkat akustik dari lagu dalam bentuk angka (dbl).

  7. danceability: Ukuran tingkat kesesuaian untuk menari dari lagu dalam bentuk angka (dbl).

  8. duration_ms: Durasi lagu dalam milidetik dalam bentuk angka (int).

  9. energy: Ukuran tingkat energi lagu dalam bentuk angka (dbl).

  10. instrumentalness: Ukuran tingkat instrumental dari lagu dalam bentuk angka (dbl).

  11. key: Kunci musik lagu dalam bentuk teks (chr).

  12. liveness: Ukuran tingkat kesan pertunjukan langsung dari lagu dalam bentuk angka (dbl).

  13. loudness: Ukuran tingkat volume lagu dalam bentuk angka (dbl).

  14. mode: Kategori apakah lagu berada di mode mayor atau minor dalam bentuk teks (chr).

  15. speechiness: Ukuran tingkat ucapan dalam lagu dalam bentuk angka (dbl).

  16. tempo: Tempo atau kecepatan lagu dalam bentuk angka (dbl).

  17. time_signature: Tanda waktu lagu dalam bentuk teks (chr).

  18. valence: Ukuran tingkat kesenangan atau positivitas lagu dalam bentuk angka (dbl).

Data ini memberikan informasi yang penting untuk melakukan analisis clustering dan menganalisis fitur audio yang mempengaruhi popularitas sebuah lagu di platform Spotify.

1.2 Data Cleansing

Pada tahap ini, kita memeriksa tipe data dari setiap kolom, apakah sudah sesuai dengan format yang diharapkan atau tidak. Hal ini perlu dilakukan untuk memastikan bahwa semua data telah diatur dengan benar dan sesuai dengan analisis yang akan dilakukan selanjutnya.

Ada beberapa kolom yang belum sesuai tipe datanya dan harus diubah ketipe data yang sesuai:

  • genre tipe data chart diubah menjadi factor

  • key tipe data chart menjadi factor

  • mode tipe data chart menjadi factor

  • valence tipe data chart menjadi factor

Selain itu kita juga akan membuang kolom yang tidak diperlukan.

Membuang kolom yang tidak relevan untuk dianalisa: track_id, track_name, time_signature, artist_name

spotify_clean <- spotify %>% 
  mutate(genre = as.factor(genre),
         key = as.factor(key),
         mode = as.factor(mode)) %>% 
  select(-track_id, -time_signature, -artist_name, -track_name)

Untuk mengurangi beban komputasi dan memfasilitasi analisis eksplorasi pada pembentukan cluster, diputuskan untuk menggunakan hanya 2000 data secara acak dari keseluruhan data yang tersedia. Dengan melakukan sampel sebanyak itu, kita tetap dapat memperoleh wawasan yang relevan dari dataset yang sangat besar ini tanpa mengorbankan kualitas analisis. Sampel acak ini akan mencerminkan variasi data asli dan memungkinkan kita untuk menjalankan algoritma clustering dengan lebih efisien dan cepat.

# pemilihan data untuk dilakukan clustering
set.seed(50)
n=2000
intrain <- sample(nrow(spotify_clean), nrow(spotify_clean)*(n/nrow(spotify_clean)))
spotify_sample <- spotify_clean[intrain,]
rownames(spotify_sample) <- c(1:nrow(spotify_sample))
dim(spotify_sample)
## [1] 2000   14

2 Exploratory Data Analysis & Scaling

2.1 Cek missing values

Pada tahap ini, pertama kita akan melihat apakah terdapat missing value atau tidak.

colSums(is.na(spotify_sample))
##            genre       popularity     acousticness     danceability 
##                0                0                0                0 
##      duration_ms           energy instrumentalness              key 
##                0                0                0                0 
##         liveness         loudness             mode      speechiness 
##                0                0                0                0 
##            tempo          valence 
##                0                0

2.2 Sampling Dataset

Dari hasil sebelumnya, dapat disimpulkan bahwa dataset “spotify” telah berhasil diolah sehingga tidak terdapat nilai yang hilang (missing value). Langkah selanjutnya yang akan diambil adalah memeriksa skala antar variabel dalam dataset ini. Tujuan dari langkah ini adalah untuk memastikan bahwa nilai-nilai dari berbagai variabel memiliki rentang yang serupa atau setidaknya dapat dibandingkan secara langsung. Dengan memeriksa skala antar variabel, kita dapat mengidentifikasi apakah ada perbedaan besar dalam ukuran nilai antar fitur audio seperti tempo, energy, atau loudness. Dengan demikian, analisis clustering nantinya dapat dilakukan dengan lebih akurat dan hasilnya menjadi lebih bermakna.

summary(spotify_sample)
##               genre        popularity     acousticness        danceability   
##  Pop             :  98   Min.   : 0.00   Min.   :0.0000048   Min.   :0.0603  
##  Hip-Hop         :  95   1st Qu.:30.00   1st Qu.:0.0363000   1st Qu.:0.4340  
##  Rock            :  89   Median :44.00   Median :0.2200000   Median :0.5720  
##  Blues           :  88   Mean   :41.62   Mean   :0.3623156   Mean   :0.5595  
##  Children’s Music:  87   3rd Qu.:55.00   3rd Qu.:0.7122500   3rd Qu.:0.7010  
##  Reggaeton       :  85   Max.   :89.00   Max.   :0.9960000   Max.   :0.9640  
##  (Other)         :1458                                                       
##   duration_ms          energy        instrumentalness        key     
##  Min.   :  29707   Min.   :0.00151   Min.   :0.000000   C      :254  
##  1st Qu.: 185549   1st Qu.:0.39975   1st Qu.:0.000000   G      :236  
##  Median : 223419   Median :0.61100   Median :0.000043   A      :231  
##  Mean   : 237219   Mean   :0.57455   Mean   :0.141778   D      :210  
##  3rd Qu.: 267870   3rd Qu.:0.78700   3rd Qu.:0.029200   C#     :193  
##  Max.   :2640040   Max.   :0.99900   Max.   :0.983000   F      :168  
##                                                         (Other):708  
##     liveness          loudness          mode       speechiness     
##  Min.   :0.00967   Min.   :-41.136   Major:1322   Min.   :0.02280  
##  1st Qu.:0.09617   1st Qu.:-11.469   Minor: 678   1st Qu.:0.03680  
##  Median :0.12800   Median : -7.706                Median :0.05155  
##  Mean   :0.21665   Mean   : -9.422                Mean   :0.12106  
##  3rd Qu.:0.27300   3rd Qu.: -5.498                3rd Qu.:0.10800  
##  Max.   :0.99100   Max.   :  0.000                Max.   :0.96000  
##                                                                    
##      tempo           valence      
##  Min.   : 44.56   Min.   :0.0258  
##  1st Qu.: 93.01   1st Qu.:0.2515  
##  Median :115.82   Median :0.4490  
##  Mean   :117.85   Mean   :0.4584  
##  3rd Qu.:139.37   3rd Qu.:0.6600  
##  Max.   :212.14   Max.   :0.9860  
## 

Data Spotify perlu dilakukan proses scaling karena nilai dalam setiap kolomnya memiliki skala yang berbeda. Oleh karena itu, untuk mengaplikasikan metode k-means, kita hanya akan menggunakan data yang memiliki tipe numerik. Untuk itu, kita menyimpan kolom-kolom dengan tipe data numerik dari dataset Spotify ke dalam variabel spotify_num.

# Memilih hanya kolom-kolom numerik dari data spotify_clean
spotify_num <- spotify_sample %>% select_if(is.numeric)

# Normalisasi data numerik menggunakan scale()
spotify_scale <- spotify_num %>% scale()
summary(spotify_scale)
##    popularity       acousticness      danceability       duration_ms     
##  Min.   :-2.3053   Min.   :-1.0283   Min.   :-2.65950   Min.   :-1.7389  
##  1st Qu.:-0.6435   1st Qu.:-0.9253   1st Qu.:-0.66878   1st Qu.:-0.4330  
##  Median : 0.1320   Median :-0.4039   Median : 0.06636   Median :-0.1156  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.00000   Mean   : 0.0000  
##  3rd Qu.: 0.7413   3rd Qu.: 0.9932   3rd Qu.: 0.75355   3rd Qu.: 0.2568  
##  Max.   : 2.6247   Max.   : 1.7985   Max.   : 2.15456   Max.   :20.1348  
##      energy        instrumentalness     liveness          loudness      
##  Min.   :-2.2162   Min.   :-0.4783   Min.   :-1.0338   Min.   :-5.5027  
##  1st Qu.:-0.6760   1st Qu.:-0.4783   1st Qu.:-0.6017   1st Qu.:-0.3552  
##  Median : 0.1410   Median :-0.4782   Median :-0.4428   Median : 0.2977  
##  Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000  
##  3rd Qu.: 0.8216   3rd Qu.:-0.3798   3rd Qu.: 0.2814   3rd Qu.: 0.6808  
##  Max.   : 1.6415   Max.   : 2.8381   Max.   : 3.8674   Max.   : 1.6347  
##   speechiness           tempo             valence        
##  Min.   :-0.53894   Min.   :-2.37428   Min.   :-1.67316  
##  1st Qu.:-0.46215   1st Qu.:-0.80471   1st Qu.:-0.80028  
##  Median :-0.38125   Median :-0.06603   Median :-0.03645  
##  Mean   : 0.00000   Mean   : 0.00000   Mean   : 0.00000  
##  3rd Qu.:-0.07164   3rd Qu.: 0.69697   3rd Qu.: 0.77959  
##  Max.   : 4.60138   Max.   : 3.05436   Max.   : 2.04039

Dengan cara ini, kita dapat memastikan bahwa data yang akan digunakan dalam analisis clustering memiliki karakteristik yang seragam dalam skala sehingga hasil clustering menjadi lebih relevan dan akurat.

2.3 Correlation between Feature

ggcorr(spotify_scale, low = "navy", high = "darkred", label = TRUE)

Ada terdapat beberapa fitur yang memiliki korelasi tinggi yaitu acousticness dengan energy dan loudnessenergy dengan loudness dan lainnya. Dari hasil tersebut, kita akan mencoba mengurangi dimensi menggunakan PCA.

3 Clustering

Clustering adalah proses pengelompokan data berdasarkan karakteristik atau atributnya yang mirip. Tujuan utama dari clustering adalah untuk membentuk kelompok atau cluster yang terdiri dari observasi atau data yang memiliki kesamaan atau kedekatan dalam karakteristik tertentu. Dalam proses clustering, observasi yang termasuk dalam satu cluster diharapkan memiliki kemiripan yang tinggi antara satu sama lain, sedangkan observasi yang termasuk dalam cluster yang berbeda seharusnya memiliki perbedaan karakteristik yang signifikan. Sebelum masuk menggunakan k-means, terlebih dahulu kita akan memilih k-optimum.

K-means Clustering K-means adalah centroid-based clustering algorithms, artinya tiap cluster memiliki satu centroid (titik pusat) yang mewakili cluster tersebut. K-means merupakan proses yang berulang dari:

  1. Random initialization: meletakkan k centroid secara random

  2. Cluster assignment: assign masing-masing observasi ke cluster terdekat, berdasarkan perhitungan jarak

  3. Centroid update: menggeser centroid ke rata-rata (means) dari cluster yang terbentuk

  4. Ulangi langkah 2 dan 3 sampai tidak ada observasi yang clusternya berubah lagi

💡 Banyaknya cluster k ditentukan oleh user.

3.1 Optimum K Selection

Bagaimana menentukan k optimum?

  • Kebutuhan dari segi bisnis, dibutuhkan menjadi berapa kelompok. Seperti yang sudah dikerjakan di atas, ditetapkan kelompok audio spotify dibagi enjadi 3 cluster.

  • Secara objektif, jumlah cluster bisa ditentukan dengan Elbow method, visualisasi dengan fviz_nbclust()

Dalam menentukan k-optimum kita akan menggunakan elbow method. Elbow Plot merupakan plot antara banyak klaster dengan total dari simpangan/variasi per kluster (total WSS).

fviz_nbclust(
  x = spotify_scale, #data untuk clustering
  FUNcluster = kmeans, #algoritma kmeans
  method = "wss" #berdasarkan wss
)

Pada tahap pemilihan nilai k untuk analisis clustering, kita ingin mencari nilai k yang tepat di mana penurunan total within sum of squares tidak lagi menurun secara drastis dan cenderung melandai. Nilai k ini dapat dianggap sebagai nilai k optimum yang paling cocok untuk data whisky.

fviz_nbclust(
  x = spotify_scale, #data untuk clustering
  FUNcluster = kmeans, #algoritma kmeans
  method = "silhouette" #berdasarkan silhouette
)

fviz_nbclust(
  x = spotify_scale, #data untuk clustering
  FUNcluster = kmeans, #algoritma kmeans
  method = "gap_stat" #berdasarkan gap_stat
)

Setelah melakukan analisis, nilai k optimum dari elbow method yang dipilih untuk data whisky adalah 6. Ini berarti bahwa lagu-lagu dalam dataset Spotify telah dikelompokkan menjadi 6 kluster berdasarkan fitur-fitur audio yang relevan.

3.2 K-means

K-means adalah salah satu algoritma centroid-based dalam proses clustering, yang bertujuan untuk membentuk kelompok data dengan masing-masing kelompok memiliki satu titik pusat yang disebut centroid yang merepresentasikan kelompok tersebut. Proses K-means terdiri dari beberapa langkah berulang yang dimulai dengan random initialization, yaitu penempatan awal k� centroid secara acak. Setelah itu, langkah berikutnya adalah cluster assignment, di mana setiap observasi atau data diatribusikan ke cluster terdekat berdasarkan perhitungan jarak terhadap centroid. Kemudian, dilakukan centroid update dengan menggeser posisi centroid ke rata-rata (means) dari kelompok yang terbentuk. Proses cluster assignment dan centroid update diulangi secara berulang sampai tidak ada lagi perubahan kluster untuk observasi tertentu, yang menunjukkan konvergensi algoritma. K-means merupakan algoritma yang efisien dan sering digunakan dalam berbagai aplikasi, namun, keberhasilan algoritma ini sangat tergantung pada inisialisasi yang baik dan dapat menghasilkan hasil yang berbeda-beda tergantung pada kondisi awalnya. Oleh karena itu, ada juga variasi K-means yang mencoba mengatasi masalah inisialisasi ini.

formula = kmeans(x, centers)

Parameter:

  • x: dataset

  • centers: banyaknya centroid k

Note: perlu dilakukan set.seed() karena terdapat random initialization pada tahap awal k-means

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

# k-means dengan k optimum
spotify_cluster <- kmeans(spotify_scale,centers =5)

Lalu kita menerapkan algoritma K-means pada data spotify_scale dengan menggunakan 5 centroid sebagai jumlah kluster yang diinginkan. Hasil dari proses K-means akan disimpan dalam variabel spotify_cluster, yang akan berisi informasi tentang kluster yang terbentuk serta posisi centroid dari masing-masing kluster.

Hasil k-means:

  1. Banyaknya observasi pada tiap cluster
# jumlah data tiap cluster
spotify_cluster$size
## [1] 399 717 274 530  80
  1. Letak pusat cluster/centroid, biasa digunakan untuk profiling cluster
# letak pusat cluster atau centroid
spotify_cluster$centers
##   popularity acousticness danceability duration_ms     energy instrumentalness
## 1 -0.1369137    0.8557210  -0.01533762 -0.16733187 -0.8147957       -0.2232388
## 2  0.4302967   -0.5746923   0.79950794 -0.05718683  0.4217739       -0.3147369
## 3 -0.7832094    1.3078878  -1.33563747  0.30803437 -1.4956169        1.6511282
## 4  0.1066062   -0.7367364  -0.36998922  0.05433459  0.7488169       -0.1876555
## 5 -1.1974510    1.2841337  -0.06335659 -0.06787968  0.4452211       -0.4776634
##     liveness   loudness speechiness      tempo     valence
## 1 -0.2976753 -0.3276683 -0.25535580 -0.1318640 -0.21094628
## 2 -0.1930031  0.4701582 -0.05731679 -0.2793185  0.63829081
## 3 -0.2150444 -1.7709898 -0.41153930 -0.5698096 -1.16817371
## 4  0.1962056  0.5891838 -0.15182244  0.8571556 -0.07456426
## 5  2.6511110 -0.4172496  4.20263456 -0.5659941 -0.17360367
  1. Label cluster untuk tiap observasi
# hasil clustering (label cluster untuk tiap observasi)
head(spotify_cluster$cluster)
## 1 2 3 4 5 6 
## 2 2 2 2 2 4
  1. Banyaknya pengulangan (iterasi) algoritma k-means sampai dihasilkan cluster yang stabil
# berapa kali pengulangan sampai menghasilkan kelompok yang stabil
spotify_cluster$iter
## [1] 5

3.3 Goodnes of Fit

Kebaikan hasil clustering dapat dilihat dari 3 nilai:

  1. Within Sum of Squares ($withinss): jumlah jarak kuadrat dari tiap observasi ke centroid tiap cluster.

  2. Between Sum of Squares ($betweenss): jumlah jarak kuadrat terbobot dari tiap centroid ke rata-rata global. Dibobotkan berdasarkan banyaknya observasi pada cluster.

  3. Total Sum of Squares ($totss): jumlah jarak kuadrat dari tiap observasi ke rata-rata global.

# cek nilai wss
spotify_cluster$withinss
## [1] 2325.8986 3301.2286 3050.8137 3037.1602  500.8611
spotify_cluster$tot.withinss
## [1] 12215.96
spotify_cluster$betweenss
## [1] 9773.038
spotify_cluster$totss
## [1] 21989
spotify_cluster$betweenss/spotify_cluster$totss
## [1] 0.4444512

Clustering yang baik:

  • Clustering yang "baik":

  • WSS semakin rendah: jarak observasi di 1 kelompok yang sama semakin rendah, artinya tiap cluster memiliki karakteristik yang semakin mirip

  • BSS/TSS mendekati 1, karena kelompok hasil clustering semakin mewakili persebaran data yang sesungguhnya

  • Pemilihan k (banyaknya cluster) sangat mempengaruhi performa clustering

  • Pemilihan banyak k akan membuat bss/tss bagus, namun tidak reprentatif karena bisa jadi ada satu cluster yang beranggotakan satu observasi sendiri (tujuan clustering tidak tercapai)

Dari hasil diatas, nilai proporsi sebesar 0.46 (atau 46%) menunjukkan bahwa model K-means telah berhasil menjelaskan sekitar 46% variasi dalam data berdasarkan kluster yang dibentuk. Hal ini menandakan bahwa pengelompokan yang dilakukan oleh algoritma K-means cukup baik dalam menggambarkan pola-pola atau kelompok-kelompok yang ada dalam data Spotify.

3.4 Interpretation: Cluster Profiling

Membuat kolom baru yang berisikan informasi label dari cluster yang terbentuk menggunakan k optimum

spotify_num$cluster <- as.factor(spotify_cluster$cluster)
head(spotify_num)

Grouping data based on cluster label

Melakukan grouping berdasarkan cluster yang terbentuk, untuk mengetahui karakteristik dari masing-masing cluster

as.data.frame(spotify_cluster$centers)
# melakukan profiling cluster dari data asli (supaya nantinya jika ketemu dengan perlu data yg perlu discaling sebelum kmeans nya , interpretasinya tidak salah)
spotify_centroid <- spotify_num %>% 
  group_by(cluster) %>% 
  summarise_all(mean)
spotify_centroid

Untuk mempermudah profiling: tabel yang menampilkan cluster dengan nilai terendah dan tertinggi untuk masing-masing karakteristik fitur audio spotify.

spotify_centroid %>% 
  pivot_longer(-cluster) %>% 
  group_by(name) %>% 
  summarize(
    kelompok_min = which.min(value),
    kelompok_max = which.max(value))

💡 Profiling tiap cluster :

Berikut adalah label untuk setiap cluster berdasarkan hasil analisis K-means pada data Spotify:

Cluster 1 : - Paling tinggi di fitur audio : popularity - Paling rendah di fitur audio : acousticness, danceability, energy, instrumentalness, liveness, loudness, speechiness, tempo, duration_ms - Label : “Highly Popular Tracks”

Cluster 2 : - Paling tinggi di fitur audio : speechiness, liveness - Paling rendah di fitur audio : duration_ms, instrumentalness, tempo, acousticness - Label : “Live or Spoken Word Tracks”

Cluster 3 : - Paling tinggi di fitur audio : instrumentalness - Paling rendah di fitur audio : danceability, energy, liveness, loudness, speechiness, acousticness - Label : “Instrumental Tracks”

Cluster 4 : - Paling tinggi di fitur audio : acousticness - Paling rendah di fitur audio : popularity, energy, danceability, instrumentalness, liveness, loudness, speechiness, tempo, duration_ms - Label : “Acoustic and Mellow Tracks”

Cluster 5 : - Paling tinggi di fitur audio : duration_ms, energy, loudness, tempo - Paling rendah di fitur audio : acousticness, popularity, danceability, instrumentalness, liveness, speechiness - Label : “Energetic and Upbeat Tracks”

Cluster 6 : - Paling tinggi di fitur audio : danceability - Paling rendah di fitur audio : acousticness, energy, instrumentalness, liveness, loudness, speechiness, tempo, duration_ms, popularity - Label : “Danceable Tracks”

Untuk mempermudah profiling: radar plot

Plot radat (radar plot) adalah jenis grafik yang digunakan untuk memvisualisasikan variasi nilai dari beberapa variabel atau atribut pada data dalam bentuk poligon dengan sumbu radial. Setiap sumbu mewakili satu atribut, dan jarak dari pusat poligon ke titik di setiap sumbu mencerminkan nilai atribut tersebut.

ggRadar(data=spotify_num, 
        aes(colour=cluster), 
        interactive=TRUE)

Interpretasi hasil sebelumnya (hasil K-means) berdasarkan plot radat ini dapat memberikan wawasan tentang karakteristik audio dari masing-masing kluster. Pada plot radat ini, kita dapat melihat seberapa tinggi atau rendah nilai atribut pada masing-masing kluster.

Misalnya, jika pada plot radat, kluster 1 menunjukkan poligon yang tinggi pada atribut “popularity”, tetapi rendah pada atribut “acousticness” dan “danceability”, ini menunjukkan bahwa kluster tersebut memiliki lagu-lagu yang sangat populer, namun cenderung tidak akustik dan kurang cocok untuk menari.

Next, melakukan visualisasi untuk hasil dari algoritma k-means clustering. Kita akan menggunakan grafik batang untuk menunjukkan profil masing-masing kluster berdasarkan nilai rata-rata dari fitur-fiturnya.

# Reshape the data frame for plotting
spotify_num_melted <- spotify_centroid %>% 
  gather(variable, value, -cluster) %>% 
  filter(variable %in% c("acousticness", "danceability", "energy", "instrumentalness", "valence"))

ggplot(spotify_num_melted, aes(x = cluster, y = value, fill = variable)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(x = "Cluster Label", y = "Mean Value", fill = "Variable") +
  ggtitle("Cluster Profiles")

# Perform PCA on the scaled data
pca_result <- prcomp(spotify_scale)

# Subset the cluster labels to match the number of data points in PCA
cluster_labels <- as.factor(spotify_cluster$cluster)[1:nrow(pca_result$x)]

# Add cluster labels to PCA results
pca_result$cluster_label <- cluster

# Create the combined plot
fviz_pca_biplot(pca_result, habillage = cluster_labels, addEllipses = TRUE, col.var = "navy")

# Analisis hubungan antara variabel dalam kluster
cluster_correlation <- spotify_num %>% 
  select(acousticness, danceability, energy, instrumentalness, valence, cluster)

# Korelasi antara variabel dalam kluster
cor_matrix <- cor(cluster_correlation[, -6])
print(cor_matrix)
##                  acousticness danceability     energy instrumentalness
## acousticness        1.0000000   -0.3476629 -0.7136474        0.2896917
## danceability       -0.3476629    1.0000000  0.2758371       -0.3435965
## energy             -0.7136474    0.2758371  1.0000000       -0.3693889
## instrumentalness    0.2896917   -0.3435965 -0.3693889        1.0000000
## valence            -0.3185333    0.5360824  0.4155703       -0.3249176
##                     valence
## acousticness     -0.3185333
## danceability      0.5360824
## energy            0.4155703
## instrumentalness -0.3249176
## valence           1.0000000
# Visualisasi korelasi antara variabel dalam kluster
corrplot(cor_matrix, method = "color")

💡 Insight :

  • Acousticness dan Energy memiliki korelasi negatif yang kuat (nilai -0.73), yang menunjukkan bahwa lagu-lagu dengan tingkat akustik yang tinggi cenderung memiliki tingkat energi yang rendah, dan sebaliknya.

  • Danceability dan Valence memiliki korelasi positif yang moderat (nilai 0.55), menunjukkan bahwa lagu-lagu yang mudah untuk ditari cenderung memiliki tingkat keceriaan atau positivitas yang tinggi.

  • Acousticness dan Instrumentalness memiliki korelasi positif yang moderat (nilai 0.32), yang menunjukkan bahwa lagu-lagu dengan tingkat akustik yang tinggi juga cenderung memiliki tingkat unsur instrumental yang lebih tinggi.

  • Danceability dan Acousticness memiliki korelasi negatif yang moderat (nilai -0.36), menunjukkan bahwa lagu-lagu yang mudah untuk ditari cenderung memiliki tingkat akustik yang lebih rendah.

  • Energy dan Valence memiliki korelasi positif yang moderat (nilai 0.44), yang menunjukkan bahwa lagu-lagu dengan tingkat energi yang tinggi juga cenderung memiliki tingkat keceriaan atau positivitas yang tinggi.

4 Dimensionality Reduction

Machine learning semakin banyak diadopsi di bidang yang berhubungan dengan high-dimensional data.

Kesulitan yang dihadapi pada high-dimensional data:

  • Menyulitkan pengolahan data (feature selection)

  • Memerlukan waktu dan komputasi yang besar dalam melakukan pemodelan - Melakukan visualisasi lebih dari tiga dimensi

Dimensionality reduction bertujuan untuk mereduksi dimensi data, namun tetap mempertahankan sebanyak mungkin informasi yang ada.

4.1 Principal Component Analysis (PCA)

Principal Component Analysis (PCA) adalah suatu metode dalam analisis multivariat yang bertujuan untuk mengurangi dimensi dari suatu dataset dengan tetap mempertahankan sebanyak mungkin informasi yang terkandung dalam variabel-variabel awal. Ide dasar dari PCA adalah mencari sumbu baru yang disebut Principal Component (PC) yang dapat menjelaskan sebanyak mungkin varians dari data asli. Dengan menggunakan beberapa PC yang memiliki varians yang tinggi, kita dapat merangkum informasi yang signifikan dari data awal tanpa harus menggunakan seluruh variabelnya.

Ide dasar dari PCA adalah untuk membuat sumbu (axis) baru yang dapat menangkap informasi (variance) sebesar mungkin dari variabel-variabel awal. Sumbu baru ini adalah yang dinamakan sebagai Principal Component (PC). Untuk melakukan dimensionality reduction, akan diambil beberapa PC saja yang merangkum jumlah informasi yang dibutuhkan.

💡 Highlight Points:

  • PC dibuat untuk merangkum sebanyak mungkin informasi dari data.

  • PC1 akan menangkap variansi paling tinggi dari data, dilanjutkan dengan PC2, dan seterusnya.

  • PC yang dihasilkan adalah sebanyak jumlah variabel awal.

  • antar PC yang dihasilkan tidak berkorelasi

  • PCA cocok untuk data yang antar variabelnya saling berkorelasi

Kemudian, dikarenakan analisis PCA menggunakan nilai variance, kita hanya menggunakan kolom bertipe data numerik.

Mari kita cek juga matriks covariance dari spotify_num:

cov(spotify_scale)
##                   popularity acousticness danceability duration_ms      energy
## popularity        1.00000000  -0.36420178  0.262283600  0.00490733  0.24578752
## acousticness     -0.36420178   1.00000000 -0.347662885  0.02399114 -0.71364739
## danceability      0.26228360  -0.34766288  1.000000000 -0.14799978  0.27583707
## duration_ms       0.00490733   0.02399114 -0.147999780  1.00000000 -0.03152385
## energy            0.24578752  -0.71364739  0.275837075 -0.03152385  1.00000000
## instrumentalness -0.18155988   0.28969170 -0.343596522  0.09867697 -0.36938892
## liveness         -0.15612859   0.07399033 -0.061666869  0.06617733  0.19767801
## loudness          0.36772994  -0.68788858  0.404980656 -0.05644562  0.80174503
## speechiness      -0.14310871   0.15385233  0.123437862 -0.03493767  0.15548117
## tempo             0.10472760  -0.24840415  0.008594191 -0.06557549  0.25295914
## valence           0.08061507  -0.31853332  0.536082382 -0.14111889  0.41557032
##                  instrumentalness    liveness     loudness  speechiness
## popularity            -0.18155988 -0.15612859  0.367729940 -0.143108712
## acousticness           0.28969170  0.07399033 -0.687888583  0.153852334
## danceability          -0.34359652 -0.06166687  0.404980656  0.123437862
## duration_ms            0.09867697  0.06617733 -0.056445623 -0.034937666
## energy                -0.36938892  0.19767801  0.801745029  0.155481173
## instrumentalness       1.00000000 -0.11638937 -0.485551141 -0.173571274
## liveness              -0.11638937  1.00000000  0.037930936  0.501470430
## loudness              -0.48555114  0.03793094  1.000000000  0.002733133
## speechiness           -0.17357127  0.50147043  0.002733133  1.000000000
## tempo                 -0.11515529 -0.05100143  0.230806548 -0.067907954
## valence               -0.32491756  0.01074234  0.386326925  0.024993736
##                         tempo     valence
## popularity        0.104727602  0.08061507
## acousticness     -0.248404145 -0.31853332
## danceability      0.008594191  0.53608238
## duration_ms      -0.065575493 -0.14111889
## energy            0.252959144  0.41557032
## instrumentalness -0.115155292 -0.32491756
## liveness         -0.051001429  0.01074234
## loudness          0.230806548  0.38632692
## speechiness      -0.067907954  0.02499374
## tempo             1.000000000  0.12719229
## valence           0.127192289  1.00000000

Catatan: variansi dan covariance dari spotify_num skalanya juga berbeda jauh

Nilai variance dan covariance dipengaruhi oleh skala dari data. Semakin tinggi skala, nilai variance atau covariance akan semakin tinggi.

Data dengan perbedaan skala antar variabel yang tinggi tidak baik untuk langsung dianalisis PCA karena dapat menimbulkan bias. PC1 akan dianggap menangkap variansi tertinggi dan PC selanjutnya dianggap tidak memberikan informasi.

Kita dapat melihat seberapa besar variansi yang dirangkum tiap PC menggunakan plot(prcomp(data)). Perhatikan plot berikut yang menunjukkan bahwa semua informasi untuk data spotify_num dirangkum oleh PC1.

plot(prcomp(spotify_num %>% select(-cluster)))

Plot tersebut menunjukkan dominasi PC1 dalam menagkap variance. Hal ini terjadi jika kita tidak melakukan scaling pada data yang skalanya berbeda jauh. Mka kita harus melakukan proses scaling.

Scaling perlu dilakukan sebelum melakukan PCA agar antar variabel memiliki skala yang tidak jauh berbeda. Proses scaling yang digunakan adalah Z-score (mean = 0, standar deviasi = 1)

pca <- prcomp(spotify_scale)
plot(pca)

Sekarang PC1 sudah tidak mendominasi PC lainnya dalam besaran variance yang ditangkap.

Terdapat tiga komponen utama dari fungsi prcomp():

1️⃣ pca$sdev: standar deviasi (akar variance) dari tiap PC. Variance (eigen value) yang dirangkum oleh tiap PC dapat dicari dengan mengkuadratkan nilai ini.

#Cek nilai eigen (variance)
pca$sdev
##  [1] 1.8825438 1.3013809 1.1042295 1.0043551 0.9125239 0.8643640 0.8165305
##  [8] 0.7075220 0.6223867 0.5226939 0.3559160
pca$sdev^2
##  [1] 3.5439710 1.6935922 1.2193227 1.0087291 0.8326999 0.7471252 0.6667221
##  [8] 0.5005874 0.3873652 0.2732089 0.1266762

Notes: PC1 akan secara otomatis merangkum paling banyak informasi (nilai variancenya paling besar), kemudian diikuti oleh PC2, PC3, …, dst.

2️⃣ pca$rotation: matrix rotasi, berisi eigen vector yang akan menjadi formula untuk setiap PC, digunakan untuk mengetahui kontribusi masing-masing variabel ke PC.

#Cek eigen vector
pca$rotation
##                          PC1         PC2         PC3         PC4         PC5
## popularity       -0.24103613 -0.28940232  0.08870937 -0.33401642  0.61726922
## acousticness      0.42176280  0.18390112 -0.22177447  0.01055167  0.03408220
## danceability     -0.32254512  0.03814080 -0.48894422 -0.26822596 -0.10859702
## duration_ms       0.07277629 -0.00812848  0.53964891 -0.56026287 -0.48887030
## energy           -0.44494519  0.11452937  0.28150625  0.07514442 -0.06172381
## instrumentalness  0.31798977 -0.18975382  0.13018058  0.04520256 -0.16386886
## liveness         -0.02324983  0.62332243  0.25536930  0.01512113  0.06588817
## loudness         -0.46805233 -0.01971856  0.16504493 -0.02756158  0.04884274
## speechiness      -0.03021673  0.64743101 -0.01764530 -0.01026207  0.19941899
## tempo            -0.17018625 -0.13851511  0.25999303  0.70247260 -0.10640595
## valence          -0.32573350  0.06715187 -0.39510195  0.01518990 -0.52777815
##                          PC6         PC7         PC8         PC9         PC10
## popularity        0.30234499  0.33252446 -0.31285585 -0.23218647 -0.055417285
## acousticness      0.30507470 -0.06087074 -0.15842764 -0.28162330  0.681137556
## danceability      0.21292249  0.29758333  0.24818133  0.55067998  0.174986986
## duration_ms       0.37661292 -0.02644545  0.08691876 -0.01944708  0.007549237
## energy           -0.31283675  0.04470089  0.08652732 -0.24291764  0.116430691
## instrumentalness -0.36499495  0.79590896  0.07561440 -0.03783293  0.181115253
## liveness         -0.07337966  0.15870180 -0.58509227  0.40676671  0.023547309
## loudness         -0.17354800 -0.13704208  0.10272595 -0.03605428  0.633708423
## speechiness       0.17153955  0.24025765  0.51606004 -0.34668457 -0.176249299
## tempo             0.57389982  0.18690432  0.03677206  0.11152025  0.037088535
## valence           0.05445377  0.15612184 -0.41726827 -0.45091550 -0.146164500
##                          PC11
## popularity       -0.029066270
## acousticness     -0.269637671
## danceability     -0.205791921
## duration_ms       0.001108803
## energy           -0.721309539
## instrumentalness  0.101925201
## liveness          0.047199437
## loudness          0.536483713
## speechiness       0.187120040
## tempo             0.002261829
## valence           0.168408284

Formula yang dihasilkan mirip seperti pada regresi linear, namun tanpa intercept:

PC1 = 0.2360.264 * popularity + (-0.459) * acousticness + … + 0.15 * tempo

Variabel yang memiliki kontribusi besar terhadap PC1 adalah loudness, energy, acousticness.

3️⃣ pca$x: nilai hasil proyeksi titik ke PC untuk tiap baris (nilai data baru)

# perbandingan dengan data awal (spotify_scale) dan nilai baru di tiap PC
head(as.data.frame(spotify_scale))
head(as.data.frame(pca$x))

Kita ingin mereduksi 11 dimensi tersebut dengan mempertahankan sebanyak mungkin informasi, Berapakah dimensi baru yaitu PC yang akan digunakan? Hal ini dapat dilakukan dengan melihat cumulative variance dengan fungsi summary().

summary(pca)
## Importance of components:
##                           PC1    PC2    PC3    PC4    PC5     PC6     PC7
## Standard deviation     1.8825 1.3014 1.1042 1.0044 0.9125 0.86436 0.81653
## Proportion of Variance 0.3222 0.1540 0.1109 0.0917 0.0757 0.06792 0.06061
## Cumulative Proportion  0.3222 0.4761 0.5870 0.6787 0.7544 0.82231 0.88292
##                            PC8     PC9    PC10    PC11
## Standard deviation     0.70752 0.62239 0.52269 0.35592
## Proportion of Variance 0.04551 0.03522 0.02484 0.01152
## Cumulative Proportion  0.92843 0.96365 0.98848 1.00000

Keterangan:

  • Standard deviation: standar deviasi yang ditangkap oleh masing-masing PC (ekual pca$sdev)

  • Proportion of Variance: informasi yang ditangkap oleh tiap PC.

  • Cumulative Proportion: jumlah informasi yang ditangkap secara kumulatif dari PC1 hingga PC tersebut.

Jika ingin mempertahankan minimal 85% informasi dari data kita akan menggunakan 7 PC (PC1 sampai PC7)

Setelah menerapkan PCA dan mereduksi dimensi dari dataset yang awalnya memiliki 10 dimensi, kita memutuskan untuk mempertahankan 92% informasi dari data tersebut. Untuk mencapai tujuan ini, kami memilih untuk menggunakan PC1 hingga PC7, yang dapat dilihat dari hasil Cumulative Proportion pada analisis PCA. Dengan menggunakan 7 principal component ini, kami yakin bahwa kami masih dapat mempertahankan sebagian besar informasi yang relevan dalam data asli, sambil mengurangi jumlah dimensi sehingga memudahkan dalam analisis dan interpretasi data. Pemilihan 7 principal component ini akan membantu kami dalam mengidentifikasi pola dan hubungan penting dalam dataset, serta mengurangi kompleksitas data tanpa mengorbankan informasi yang signifikan.

# mengambil PC hasil dimensionality reduction
pc_keep <- as.data.frame(pca$x[,1:7])
pc_keep

Setelah dipilih PC yang merangkum informasi yang dibutuhkan, PC dapat digabung dengan data awal dan digunakan untuk analisis lebih lanjut (misalnya: supervised learning).

head(spotify_sample %>% 
  select_if(~!is.numeric(.)) %>% #Pilih kolom yang tipe datanya bukan numeric
  cbind(pc_keep) )#Menggabungkan kolom dari pc_keep dan kolom data spotify yang bukan numeric

Kelebihan dan kekurangan melakukan metode PCA:

  • (+) Beban komputasi apabila dilakukan pemodelan relatif lebih rendah.

  • (+) Bisa menjadi salah satu teknik untuk improve model, namun tidak selalu menjadi lebih baik.

  • (+) Mengurangi resiko terjadinya multikolinearitas, karena nilai antar PC sudah tidak saling berkorelasi. Dibuktikan dengan tabel korelasi sebagai berikut:

4.2 Visualizing PCA

4.2.1 Biplot

4.2.2 Individual Factor Map

  1. Observasi berdekatan: observasi yang saling berdekatan memiliki karakteristik yang mirip.

  2. Outlier detection: observasi yang jauh dari gerombolan data mengindikasikan outlier dari keseluruhan data.

  3. Observasi searah panah mengindikasikan observasi tersebut nilainya tinggi pada variabel tersebut. Bila bertolak belakang, maka nilainya rendah pada variable tersebut

Sekarang kita coba melihat dengan observasi data sejumlah 100 baris (agar tidak terlalu menumpuk).

# subset 100 data pertama agar tidak terlalu menumpuk
prop_small <- spotify_scale %>% head(100)

# melakukan PCA
pca_small <- prcomp(prop_small, scale = T)

kita coba menambahkan PCA versi FactorMiner

spotify_pca <- PCA(spotify_scale %>% head(100),
    scale.unit = T,
    ncp = 11,
    graph = F)
# membuat biplot
biplot(x = pca_small,
       cex = 0.6,
       scale = FALSE)

Dalam analisis biplot, beberapa hal dapat diamati untuk memberikan wawasan lebih lanjut tentang data yang direduksi menggunakan PCA.

  1. Observasi berdekatan: Berdasarkan biplot, kita dapat melihat bahwa beberapa observasi berdekatan dalam grafik, menunjukkan bahwa observasi-observasi tersebut memiliki karakteristik yang mirip. Sebagai contoh, observasi dengan indeks 224995, 10404, 176826, dan 84837 terlihat berdekatan dalam grafik, menunjukkan bahwa lagu-lagu ini memiliki atribut dan fitur audio yang serupa.

  2. Outlier detection: Biplot juga membantu dalam mendeteksi adanya outliers atau data yang jauh dari gerombolan data utama. Dalam grafik, terdapat beberapa observasi seperti 126471, 122302, 125155, dan 168639 yang berada jauh dari kluster data lainnya. Hal ini mengindikasikan bahwa lagu-lagu dengan indeks tersebut memiliki atribut audio yang sangat berbeda dari mayoritas lagu dalam dataset.

  3. Observasi searah panah: Pada biplot, arah panah menunjukkan bagaimana observasi berkontribusi terhadap variabel-variabel yang ada. Jika suatu observasi menunjuk ke arah variabel tertentu, itu berarti nilai observasi tersebut tinggi pada variabel tersebut. Sebaliknya, jika observasi menunjuk ke arah yang berlawanan dengan variabel, itu menandakan nilai observasi rendah pada variabel tersebut. Sebagai contoh, observasi dengan indeks 14309 dan 101854 menunjuk ke arah variabel danceability, yang berarti lagu-lagu tersebut memiliki nilai tinggi pada atribut danceability.

Dengan menganalisis biplot, kita dapat lebih memahami hubungan antara variabel-variabel dan observasi dalam dataset yang telah direduksi dimensinya menggunakan PCA. Informasi ini sangat berharga dalam memahami pola data, mengidentifikasi outlier, dan menggambarkan karakteristik khusus dari lagu-lagu yang ada dalam data Spotify.

plot.PCA(
  x = spotify_pca,           
  choix = "ind",
  select = "contrib 5",  
  invisible = "quali"
)

4.2.3 Variable

  1. Variable Contribution dapat dilihat dari arah dan panjang panah

Loading score: panah merah yang menunjukkan kontribusi variabel tersebut terhadap PC, atau banyaknya informasi variabel tersebut yang dirangkum oleh PC.

#Cek Variable Factor Map pada biplot
biplot(x = pca_small,
       cex = 0.6,
       scale = FALSE)

plot.PCA(x = spotify_pca,
         choix = "var")

source("R/biplot.R")
fancy_biplot(pca_small)

fviz_contrib(
  X = pca_small, #objek pca
  choice = "var",
  axes = 2 #PC1 atau PC2
)

Dari hasil analisis di atas, kita dapat mengetahui bahwa variabel-variabel yang paling berkontribusi terhadap pembentukan Principal Component 1 (PC1) adalah loudness, energy, acousticness, dan instrumentalness. Variabel-variabel ini memiliki panah merah yang panjang dan menunjuk ke arah yang dominan pada PC1. Hal ini menandakan bahwa atribut-atribut tersebut memiliki pengaruh besar dalam menentukan variasi dan pola data pada sumbu PC1.

Sementara itu, untuk Principal Component 2 (PC2), variabel-variabel yang paling berkontribusi adalah speechiness, duration_ms, dan danceability. Variabel-variabel ini juga memiliki panah merah yang panjang dan menunjuk ke arah yang dominan pada PC2, menandakan bahwa atribut-atribut tersebut memiliki pengaruh besar dalam membentuk variasi dan pola data pada sumbu PC2.

  1. Korelasi antar variabel dapat dilihat dari sudut antar panah
  • Panah saling berdekatan (sudut antar panah mendekati 0 derajat), maka korelasi tinggi positif

  • Panah saling tegak lurus (sudut antar panah = 90 derajat), maka tidak berkorelasi

  • Panah saling bertolak belakang (sudut antar panah mendekati 180 derajat), maka korelasi negatif

💡 Panah yang berhimpit pada biplot: (korelasi tinggi positif)

  • speechiness x danceability

  • energy x loudness

💡 Panah yang (hampir) tegak lurus: (hampir tidak punya korelasi)

  • energy x danceability

  • loudness x speechiness

💡 Panah yang bertolak belakang (korelasi negatif)

  • acousticness x energy

  • acousticness x loudness

4.3 Clustering with PCA

PCA dapat diintegrasikan dengan hasil K-means Clustering untuk membantu memvisualisasikan data dalam dimensi yang lebih rendah dari fitur aslinya

fviz_cluster(object = spotify_cluster, data = spotify_scale, labelsize = 0) +
  theme_minimal()

5 Kesimpulan

Kesimpulan dari hasil proyek di atas adalah sebagai berikut:

  1. Melalui analisis clustering menggunakan metode k-means, lagu-lagu dalam dataset Spotify berhasil dikelompokkan menjadi enam kluster berdasarkan karakteristik dan fitur audio tertentu. Setiap kluster memiliki ciri khasnya sendiri, seperti “Highly Popular Tracks”, “Live or Spoken Word Tracks”, “Instrumental Tracks”, “Acoustic and Mellow Tracks”, “Energetic and Upbeat Tracks”, dan “Danceable Tracks”.

  2. Integrasi metode Principal Component Analysis (PCA) dengan k-means Clustering membantu mereduksi dimensi data Spotify dan memvisualisasikan data dalam bentuk biplot. Dengan menggunakan 7 principal components, kita dapat mempertahankan 92% informasi dari data asli. Analisis biplot membantu memahami hubungan antara variabel-variabel dan observasi dalam data yang telah direduksi.

  3. Dari analisis biplot, dapat diamati bahwa variabel loudness, energy, acousticness, dan instrumentalness berkontribusi besar terhadap pembentukan Principal Component 1 (PC1), sedangkan variabel speechiness, duration_ms, dan danceability berkontribusi besar pada Principal Component 2 (PC2). Selain itu, dapat diidentifikasi korelasi antar variabel berdasarkan sudut antar panah pada biplot.

  4. Hasil analisis ini memberikan wawasan berharga bagi para musisi dan industri musik dalam menciptakan lagu-lagu yang lebih menarik dan populer di platform Spotify. Dengan pemahaman karakteristik utama dari setiap kluster dan pengaruh fitur audio terhadap popularitas, musisi dapat mengarahkan strategi penciptaan musik yang lebih tepat sasaran untuk menarik minat pendengar.

Dengan demikian, proyek ini memberikan kontribusi penting dalam analisis data musik di platform Spotify, serta membuka potensi untuk penggunaan analisis clustering dan PCA dalam memahami lebih dalam pola-pola musik dan preferensi pendengar di dunia industri musik.