library(dplyr)
library(GGally)
library(gridExtra)
library(factoextra)
library(FactoMineR)
library(plotly)
Spotify adalah salah satu layanan streaming musik digital yang memberikan akses ke jutaan lagu di sekuruh dunia, pada penelitian ini bertujuan untuk melakukan klustering dan mengetahui fitur audio dominan di setiap klusternya dan melakukan reduksi dimensi data (PCA) dengan menganalisa pola untuk mendapatkan informasi dengan menggunakan 150 sample data lagu spotify
spotify <- read.csv("SpotifyFeatures.csv")
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 Willi~
#> $ 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~
Deskripsi Data :
genre : Genre Musik
artist_name : Nama artis
track_name : Judul lagu
track_id : Id lagu
popularity : Kepopuleran lagu
acousticness : Tingkat keakustikan lagu
danceability : Tingkat ideal lagu untuk membuat pendengar menari
duration_ms : Durasi lagu dalam (milliseconds)
energy : Tingkat energi lagu
instrumentalness : Ragam instrumen yang dipakai dalam sebuah lagu
key : chord awal lagu dimulai
liveness : produksi musik dengan perandaian ketika lagu ditampilkan secara langsung
loudness : Tingkat kenyaringan lagu
mode : menggunakan nada yang sama dengan major standar namun dengan cara baru
speechiness ; Kerapatan kata dalm lagu
tempo : Tingkat cepat atau lambat sebuah lagu
time_signature : Birama
valence : Emosi yang dimunculkan sebuah lagu
spotify <- spotify %>%
mutate_at(vars(ï..genre,key,mode,time_signature),as.factor)
head(spotify)
names(spotify)[names(spotify) == "ï..genre"] <- "genre"
#check missing value
anyNA(spotify)
#> [1] FALSE
spotify <- spotify[1:150,]
#Mengambil data variabel numerik untuk melakukan scaling data
spotify_clean <- spotify%>%
select_if(is.numeric)
head(spotify_clean)
summary(spotify_clean)
#> popularity acousticness danceability duration_ms
#> Min. : 0.000 Min. :0.00104 Min. :0.1080 Min. : 22413
#> 1st Qu.: 0.000 1st Qu.:0.38900 1st Qu.:0.4440 1st Qu.: 144090
#> Median : 0.000 Median :0.66400 Median :0.5860 Median : 190034
#> Mean : 7.767 Mean :0.60700 Mean :0.5647 Mean : 253618
#> 3rd Qu.: 3.000 3rd Qu.:0.85075 3rd Qu.:0.6837 3rd Qu.: 238110
#> Max. :76.000 Max. :0.98900 Max. :0.9140 Max. :3435625
#> energy instrumentalness liveness loudness
#> Min. :0.00154 Min. :0.000000 Min. :0.0320 Min. :-25.274
#> 1st Qu.:0.25350 1st Qu.:0.000000 1st Qu.:0.1090 1st Qu.:-14.343
#> Median :0.43800 Median :0.000000 Median :0.1460 Median :-10.709
#> Mean :0.44017 Mean :0.077886 Mean :0.2026 Mean :-11.158
#> 3rd Qu.:0.63150 3rd Qu.:0.000202 3rd Qu.:0.2487 3rd Qu.: -7.503
#> Max. :0.95300 Max. :0.976000 Max. :0.9000 Max. : -1.828
#> speechiness tempo valence
#> Min. :0.0258 Min. : 32.24 Min. :0.0378
#> 1st Qu.:0.0370 1st Qu.: 90.24 1st Qu.:0.3615
#> Median :0.0557 Median :111.03 Median :0.5700
#> Mean :0.1643 Mean :113.94 Mean :0.5468
#> 3rd Qu.:0.1258 3rd Qu.:130.01 3rd Qu.:0.7478
#> Max. :0.9610 Max. :205.46 Max. :0.9730
cov(spotify_clean[1:4])
#> popularity acousticness danceability duration_ms
#> popularity 379.9250559 -1.54426447 0.45769351 -240084.730
#> acousticness -1.5442645 0.08364705 -0.01681911 2209.618
#> danceability 0.4576935 -0.01681911 0.02834559 4115.406
#> duration_ms -240084.7299776 2209.61750683 4115.40572036 145437758318.691
Dari hasil diatas variance dari masing-masing variabel berbeda jauh karena range/skala dari tiap variabel berbeda, begitupun covariance. Nilai variance dan covariance dipengaruhi oleh skala dari data. Semakin tinggi skala, nilai variance atau covariance akan semakin tinggi.
Scaling data
spotify_scale <- scale(spotify_clean) %>%
as.data.frame()
spotify_scale
ggcorr(spotify_scale,low = 'green', high = 'darkblue',
label = TRUE, label_size = 2.5, hjust = 1, layout.exp = 3)
Analisa dari grafik korelasi diatas memberikan informasi bahwa ada beberapa variabel yang memiliki korelasi cukup kuat yaitu pada variabel
energy dengan loudness, danceablility dengan valence dan energy dengan valence hal tersebut dapat diatasi dengan melakukan (PCA) agar menghilangkan sifat multikolinearitas pada data, dan mengunragi dimensi data tetapi dapat merangkum informasi sebanyak mungkin. Hasil dari analisis tersebut dapat dimanfaatkan untuk melakukan klasifikasi
fviz_nbclust(spotify_scale, kmeans, method = "wss") + labs(subtitle = "wss method")
fviz_nbclust(spotify_scale, kmeans, "silhouette", k.max = 10) + labs(subtitle = "Silhouette method")
Berdasarkan dari analisis silhouette method dan wss K optimum berada di nilai 7, Maka cluster akan dibuat menjadi 7 kelas
set.seed(100)
spotify_means <- kmeans(spotify_scale,7)
#memasukan label cluster ke data scale
spotify_scale$cluster <- as.factor(spotify_means$cluster)
head(spotify_scale)
spotify_scale %>%
group_by(cluster) %>%
summarise_all(mean)
Dengan mengambil nilai rata - rata dari setiap kluster, sekarang kita dapat mengetahui karakteristik dari setiap kluster :
kluster 1 : lagu bersifat akustik, memiliki danceability untuk pendengar, durasi lagu rendah dan memiliki valence
kluster 2 : lagu memiliki popularity yang tinggi, tidak bersifat akustik, bersifat nyaring/loudness dan tempo cepat
kluster 3 : lagu bersifat akustik, memiliki dancebility yang rendah, bersifat instrumentalness
kluster 4 : lagu bersifat danceability serta memiliki durasi yang cukup lama serta bersifat speechiness
kluster 5 : lagu memiliki durasi yang rendah dan berenergy, dan memiliki liveness
kluster 6 : lagu tidak bersifat akustik, memiliki energy, loudness dan memiliki valence
kluster 7 : lagu bersifat akustik, dan memiliki tingkat valence yang rendah
#Visualisasi CLustering
fviz_cluster(object = spotify_means,
data = spotify_scale[,-12])
pca <- spotify %>%
select_if(is.numeric)
pca$genre <- spotify$genre
PCA tidak hanya berguna untuk dimensionality reduction namun baik untuk visualisasi high-dimensional data. Visualisasi dapat menggunakan biplot yang menampilkan:
#Melakukan PCA dengan FactomineR
spotify_pca <- PCA(spotify_scale, quali.sup =12)
Dari grafik PCA diatas terbagi menjadi 2 PC, karena dari hasil reduksi dimensi tersebut PC 1 dan PC 2 akan merangkum informasi paling banyak, sehingga jika diaplikasikan kedalam biplot PC1 = sumbu x, sedangkan PC2 = sumbu y.
Insight :
- PC1 paling banyak merangkum variabel : acousticness,instrumentalness,danceability,valence,energy,loudness
- PC2 paling banyak merangkum variabel : speechiness,duration_ms,liveness,popularity,tempo
fviz_eig(spotify_pca, ncp = 10, addlabels = T, main = "Variance explained by each dimensions")
Jika dibuat kedalam grafik, dapat dibuktikan bahwa informasi paling tinggi berada di dimensi 1 dan 2 atau PC1 dan PC2
spotify_pca$eig
#> eigenvalue percentage of variance cumulative percentage of variance
#> comp 1 3.2911084 29.919167 29.91917
#> comp 2 1.8506667 16.824243 46.74341
#> comp 3 1.1782375 10.711250 57.45466
#> comp 4 1.0308187 9.371079 66.82574
#> comp 5 0.8274323 7.522111 74.34785
#> comp 6 0.7916284 7.196621 81.54447
#> comp 7 0.7229491 6.572265 88.11674
#> comp 8 0.5262140 4.783763 92.90050
#> comp 9 0.3632822 3.302566 96.20307
#> comp 10 0.2722207 2.474734 98.67780
#> comp 11 0.1454421 1.322201 100.00000
#Membuat data frame baru dari hasil PCA
spotify_keep <- PCA(spotify_scale, graph = F, ncp = 6, quali.sup = 12)$ind$coord %>% as.data.frame()
spotify_x <- spotify_keep %>%
bind_cols(cluster = as.factor(spotify_means$cluster))
head(spotify_x)
Dari hasil dimension reduction diatas mengambil 6 dimensi karena untuk mendaptkan informasi sebanyak 80%, yang didapatkan dari cummulative of percentage variance.
fviz_pca_ind(spotify_pca, habillage = 12, addEllipses = T)
Data outlier
spotify[c(16,55,97,115),]
Dari hasil diatas didapetkan bahwa data outlier dari genre movie, berada di cluster 4, sesuai dengan profiling kluster diatas, lagu outlier tersebut bersifat danceability serta memiliki durasi yang cukup lama serta bersifat speechiness yang tinggi.
spotify_viz <- spotify_keep %>%
bind_cols(cluster = as.factor(spotify_means$cluster))
head(spotify_viz)
Menggunakan plotly untuk melihat visual data PCA dengan 3 Dimensi
plot_ly(spotify_viz, x = ~Dim.1, y = ~Dim.2, z = ~Dim.3, color = ~cluster, colors = c('black','blue',"yellow","green","red","magenta","brown")) %>%
add_markers() %>%
layout(scene = list(xaxis = list(title = 'Dim.1'),
yaxis = list(title = 'Dim.2'),
zaxis = list(title = 'Dim.3')))
Dari hasil analisis klustering didapatkan bahwa terdapat 7 kluster dengan karakteristiknya masing - masing, jika dilihat dari segi bisnis industri musik, lagu - lagu dengan tingkat populer yang tinggi berada di kluster 2 dengan karakter lagu tidak bersifat akustik dan memiliki tingkat kenyaringan yang tinggi dan memiliki tempo yang cepat
Dalam melakukan reduksi dimensi kita dapat memilih semua PC, pada pemilihan nilai variabel PC diatas mengambil 6 variabel PC dengan mempertahankan 80% informasi dari data aslinya, yang dimana data tersebut dapat dilanjutkan dengan model supervised machine learning.