Dokumen ini bertujuan untuk melakukan analisis data pada dataset Ultimate Spotify Tracks DB. Proses analisisnya mencakup: - Preprocessing data - Pemilihan parameter - Visualisasi data
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)
library(ggplot2)
library(cluster) # Untuk clustering
library(factoextra) # Untuk visualisasi clustering dan PCA
## Warning: package 'factoextra' was built under R version 4.4.3
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(readr)
library(corrplot) # Untuk visualisasi korelasi
## corrplot 0.95 loaded
library(purrr)
spotify <- read.csv("SpotifyFeatures.csv")
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.00e+00, 0.00e+00, 0.00e+00, 0.00e+00, 1.23e-01, 0.0…
## $ 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…
summary(spotify)
## genre artist_name track_name track_id
## Length:232725 Length:232725 Length:232725 Length:232725
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## popularity acousticness danceability duration_ms
## Min. : 0.00 Min. :0.0000 Min. :0.0569 Min. : 15387
## 1st Qu.: 29.00 1st Qu.:0.0376 1st Qu.:0.4350 1st Qu.: 182857
## Median : 43.00 Median :0.2320 Median :0.5710 Median : 220427
## Mean : 41.13 Mean :0.3686 Mean :0.5544 Mean : 235122
## 3rd Qu.: 55.00 3rd Qu.:0.7220 3rd Qu.:0.6920 3rd Qu.: 265768
## Max. :100.00 Max. :0.9960 Max. :0.9890 Max. :5552917
## energy instrumentalness key liveness
## Min. :2.03e-05 Min. :0.0000000 Length:232725 Min. :0.00967
## 1st Qu.:3.85e-01 1st Qu.:0.0000000 Class :character 1st Qu.:0.09740
## Median :6.05e-01 Median :0.0000443 Mode :character Median :0.12800
## Mean :5.71e-01 Mean :0.1483012 Mean :0.21501
## 3rd Qu.:7.87e-01 3rd Qu.:0.0358000 3rd Qu.:0.26400
## Max. :9.99e-01 Max. :0.9990000 Max. :1.00000
## loudness mode speechiness tempo
## Min. :-52.457 Length:232725 Min. :0.0222 Min. : 30.38
## 1st Qu.:-11.771 Class :character 1st Qu.:0.0367 1st Qu.: 92.96
## Median : -7.762 Mode :character Median :0.0501 Median :115.78
## Mean : -9.570 Mean :0.1208 Mean :117.67
## 3rd Qu.: -5.501 3rd Qu.:0.1050 3rd Qu.:139.05
## Max. : 3.744 Max. :0.9670 Max. :242.90
## time_signature valence
## Length:232725 Min. :0.0000
## Class :character 1st Qu.:0.2370
## Mode :character Median :0.4440
## Mean :0.4549
## 3rd Qu.:0.6600
## Max. :1.0000
# cek data NA
colSums(is.na(spotify))
## genre artist_name track_name track_id
## 0 0 0 0
## popularity acousticness danceability duration_ms
## 0 0 0 0
## energy instrumentalness key liveness
## 0 0 0 0
## loudness mode speechiness tempo
## 0 0 0 0
## time_signature valence
## 0 0
# cek data duplicated
sum(duplicated(spotify))
## [1] 0
ggplot(spotify, aes(x = popularity)) +
geom_histogram(binwidth = 5, fill = "steelblue", color = "white") +
theme_minimal() +
labs(title = "Distribusi Popularitas", x = "Popularity", y = "Frekuensi")
Insight: - Distribusi menunjukkan bahwa sebagian besar
data cenderung pada nilai rendah ke tengah-tengah. - Kemungkinan
terdapat outlier, terlihat dari adanya ekor pada sisi nilai yang lebih
tinggi.
# Seleksi variabel numerik
numeric_vars <- spotify %>%
select(popularity, acousticness, danceability, duration_ms, energy, instrumentalness,
liveness, loudness, speechiness, tempo, valence)
# Visualisasi korelasi
corrplot(cor(numeric_vars), method = "color", addCoef.col = "black", tl.cex = 0.8)
Insight: - Hubungan kuat antara energy dan loudness.
-> ini berarti lagu yang memiliki tingkat energi tinggi cenderung
memiliki kekerasan (volume) yang tinggi juga. - Korelasi negatif antara
accousticness dan energy. -> ini berarti lagu akustik memiliki
tingkat energi rendah - Korelasi moderat antara danceability dan energy.
-> ini berarti lagu yang ritme-nya cocok untuk dijadikan lagu tari,
memiliki tingkat energi yang lebih tinggi.
spotify_scaled <- scale(spotify %>% select(popularity, danceability, energy, valence))
# Menentukan jumlah cluster dengan metode elbow
wss <- function(k) {
kmeans(spotify_scaled, centers = k, nstart = 10)$tot.withinss
}
# Hitung wss untuk k dari 1 sampai 10
k_values <- 1:10
wss_values <- map_dbl(k_values, wss)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: did not converge in 10 iterations
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
# Plot metode elbow
plot(k_values, wss_values, type = "b", pch = 19, frame = FALSE,
xlab = "Jumlah cluster (k)", ylab = "Total within Sum of Squares",
main = "Metode Elbow untuk Menentukan k")
Insight: Berdasarkan bentuk grafik metode elbow
tersebut, terlihat bawa “elbow point” atau “tekukan” terjadi saat k = 3.
Setelah titik ini, penurunan Total within Sum of Squares mulai melambat,
yang menunjukkan bahwa penambahan jumlah cluster setelah k = 3 tidak
memberikan peningkatan yang signifikan dalam mengurangi varians
internal.
set.seed(123)
final_cluster <- kmeans(spotify_scaled, centers = 3, nstart = 25)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 11636250)
spotify$cluster <- as.factor(final_cluster$cluster)
# Visualisasi hasil clustering
fviz_cluster(final_cluster, data = spotify_scaled,
geom = "point", ellipse.type = "convex",
ggtheme = theme_minimal(),
main = "Visualisasi Hasil Clustering K-Means")
Insight: - ketiga cluster terlihat cukup terpisah
secara visual, walaupun ada sedikit overlapping di titik pertemuan
antara cluster 1, 2, dan 3.
pca <- prcomp(spotify_scaled, center = TRUE, scale. = TRUE)
summary(pca)
## Importance of components:
## PC1 PC2 PC3 PC4
## Standard deviation 1.4085 0.9773 0.8249 0.61700
## Proportion of Variance 0.4959 0.2388 0.1701 0.09517
## Cumulative Proportion 0.4959 0.7347 0.9048 1.00000
# visualisasi hasil PCA
pca_data <- as.data.frame(pca$x)
pca_data$cluster <- spotify$cluster
ggplot(pca_data, aes(x = PC1, y = PC2, color = cluster)) +
geom_point(alpha = 0.6) +
theme_minimal() +
labs(title = "PCA Scatter Plot Berdasarkan Cluster",
x = "Principal Component 1",
y = "Principal Component 2")
Visualisasi PCA scatter plot menunjukkan bahwa lagu-lagu dalam dataset Spotify dapat dikelompokkkan ke dalam 3 cluster utama yang mempresentasikan karakteristik musik yang berbeda. Masing-masing cluster menunjukkan distribusi data lagu berdasarkan dua komponen utama hasil reduksi dimensi menggunakan PCA. 1. Cluster 1 (🟥) : lagu akustik / mellow - lagu-lagu dalam cluster ini cenderung memiliki tingkat energi dan kekerasan yang rendah, tapi akustiknya tinggi. - cluster ini kemungkinan berisi lagu-lagu ballad, singer-songwriter, atau folk acoustic yang lebih tenang dan tidak terlalu ritmis. 2. Cluster 2 (🟩) : lagu pop / mid-energy - lagu dalam cluster ini cenderung memiliki tingkat energi sedang dengan danceability yang tinggi. tapi tidak sekeras cluster 3. - cluster ini kemungkinan berisi lagu-lagu pop, R&B, chill, dan indie-pop. 3. Cluster 3 (🟦) : lagu energic / party - lagu-lagu dalam cluster ini cenderng memiliki tingkat energi dan kekerasan yang tinggi. - cluster ini kemungkinan terdiri dari EDM, hip-hop, trap, atau party music.