Dalam industri digital streaming musik global seperti Spotify, kesuksesan sebuah karya musik tidak lagi dipandang sebagai sebuah misteri intuitif semata. Industri modern mentransformasikan karya seni suara menjadi komponen data terstruktur yang dapat diukur. Dataset yang kami gunakan dalam penelitian tugas akhir ini adalah Spotify Tracks Dataset yang diperoleh dari platform repositori data publik Kaggle. Dataset ini merekam karakteristik internal audio, performa popularitas, serta identitas struktural dari ribuan lagu lintas genre secara global.
Untuk memenuhi batas minimum tuntutan tugas akademik (minimal 500
observasi), kami sepakat menetapkan ukuran sampel sebanyak 600
observasi. Pengambilan sampel dilakukan menggunakan teknik
Random Sampling via fungsi slice_sample() dengan
penguncian acak set.seed(123). Langkah pengacakan ini
sangat krusial (vital) agar data yang terambil tidak bias atau menumpuk
pada genre tertentu saja (seperti baris-baris awal dataset asli yang
didominasi genre akustik), melainkan tersebar secara adil
(unbiased) dari seluruh populasi trek lagu Spotify.
Analisis multivariat ini berfokus penuh pada 11 variabel numerik kontinu utama yang merepresentasikan kualitas sinyal audio fisik maupun persepsi psikologis pendengar:
popularity: Tingkat popularitas lagu (skala 0–100)
berbasis algoritma jumlah pemutaran terbaru.duration_ms: Durasi total lagu dalam satuan
milidetik.danceability: Tingkat kelayakan lagu untuk digunakan
berdansa berdasarkan ritme dan keteraturan ketukan.energy: Ukuran persepsi intensitas, kecepatan, dan
kenyaringan dinamika lagu.loudness: Volume suara total lagu dalam satuan Desibel
(dB).speechiness: Keberadaan kata-kata terucap (vokal
manusia) di dalam lagu.acousticness: Tingkat probabilitas bahwa lagu dibuat
menggunakan instrumen non-elektronik (akustik).instrumentalness: Tingkat probabilitas bahwa lagu tidak
mengandung vokal manusia (murni instrumen).liveness: Deteksi keberadaan audiens secara langsung
(efek panggung live/konser).valence: Ukuran positivitas emosional yang dihantarkan
oleh lagu (nada ceria vs nada sedih).tempo: Kecepatan ketukan lagu secara keseluruhan dalam
satuan Beats Per Minute (BPM).Tujuan Utama Analisis:
track_id) dan baris kosong (missing values) agar
proses pemodelan kelompok terbebas dari bias komputasi.Sesuai dengan kaidah Data Wrangling modern, data mentah
divalidasi struktur dan tipe datanya terlebih dahulu. Format data diubah
menjadi bentuk modern tibble yang bersifat strict
dan efisien dalam memori, mengecek keberadaan data ganda, serta membuang
variabel indeks bawaan sistem yang bersifat redundant (tidak
memiliki arti substantif).
library(tidyverse)
library(psych)
# 1. Membaca data
spotify_raw <-read.csv("C:/Users/MyBook Hype AMD/OneDrive/Desktop/SEMESTER 4/eksplorasi dan visualisasi data/Spotify_Tracks.csv")
# 2. Melakukan penarikan sampel acak terkunci untuk pengujian representatif
set.seed(123)
df_600 <- spotify_raw %>%
slice_sample(n = 600)
# 3. Transformasi ke format Tibble dan pembersihan kolom indeks tidak relevan
df_clean <- as_tibble(df_600) %>%
select(-matches("...1|Unnamed|X"))
# 4. Validasi dan eliminasi data duplikat berdasarkan ID Unik Trek Lagu
jumlah_duplikat <- sum(duplicated(df_clean$track_id))
df_clean <- df_clean %>%
distinct(track_id, .keep_all = TRUE)
# 5. Penanganan Nilai Hilang (Missing Values / NA)
missing_summary <- colSums(is.na(df_clean))
df_clean <- df_clean %>%
drop_na(artists, track_name)
# 6. Menampilkan output dimensi final dari data cleaning awal
dim(df_clean)#> [1] 600 19
Unnamed: 0 atau X hanyalah penanda nomor baris
otomatis saat file diekspor ke format CSV. Memasukkan variabel ini ke
dalam analisis multivariat adalah kesalahan fatal karena komputer akan
menganggap angka urut tersebut sebagai fitur numerik bermakna, yang
dapat merusak akurasi matriks korelasi dan PCA.colSums(is.na(df_clean)) memastikan akurasi data. Pada
penarikan sampel acak ini, tidak ditemukan nilai kosong yang signifikan
pada variabel numerik inti, sehingga baris data yang dipertahankan tetap
utuh dan solid di angka 600 observasi.Metrik statistik deskriptif berikut dihitung untuk mengamati karakteristik pemusatan (mean, median), penyebaran (standard deviation, range), serta bentuk keasimetrisan kurva data (skewness, kurtosis).
# Mengisolasi 11 variabel numerik inti untuk analisis multivariat
df_numerik <- df_clean %>%
select(popularity, duration_ms, danceability, energy,
loudness, speechiness, acousticness, instrumentalness,
liveness, valence, tempo)
# Menghasilkan matriks ringkasan statistik deskriptif mendalam
tabel_deskriptif <- describe(df_numerik)
print(tabel_deskriptif[, c("mean", "sd", "median", "min", "max", "skew", "kurtosis")])#> mean sd median min max skew kurtosis
#> popularity 33.77 22.26 36.00 0.00 92.00 -0.01 -0.92
#> duration_ms 227342.29 90022.37 211786.50 39775.00 702629.00 1.47 3.89
#> danceability 0.55 0.18 0.58 0.00 0.94 -0.45 -0.21
#> energy 0.64 0.26 0.69 0.00 1.00 -0.60 -0.58
#> loudness -8.21 5.60 -6.67 -41.74 -0.25 -2.66 9.47
#> speechiness 0.08 0.10 0.05 0.00 0.95 5.07 33.35
#> acousticness 0.32 0.34 0.17 0.00 1.00 0.71 -1.00
#> instrumentalness 0.15 0.30 0.00 0.00 1.00 1.84 1.67
#> liveness 0.22 0.19 0.14 0.02 0.99 2.06 4.21
#> valence 0.48 0.27 0.47 0.00 0.97 0.09 -1.06
#> tempo 121.73 29.92 122.79 0.00 208.28 0.21 0.14
popularity & tempo): Rata-rata
popularitas lagu berada pada angka \(33.77\) dengan standar deviasi cukup besar
(\(22.66\)), membuktikan data kita
sangat bervariasi antara lagu tidak terkenal hingga lagu hits global
berskala \(92\). Rata-rata tempo lagu
berada di angka \(121.73\) BPM, yang
merupakan detak ritme standar pergerakan musik populer
(mid-to-upbeat).Untuk mendukung interpretasi hasil matematis secara visual, data terlebih dahulu ditransformasikan ke format memanjang menggunakan fungsi pivot_longer(). Selanjutnya, visualisasi multi-panel dibangun dengan bantuan fungsi facet_wrap() pada ggplot2, sehingga pola dan karakteristik masing-masing variabel dapat diamati secara lebih jelas.
Histogram mencerminkan sebaran frekuensi kemunculan nilai pada setiap variabel fitur audio.
df_long <- df_numerik %>%
pivot_longer(cols = everything(), names_to = "Variabel", values_to = "Nilai")
ggplot(df_long, aes(x = Nilai, fill = Variabel)) +
geom_histogram(bins = 30, color = "white", alpha = 0.8) +
facet_wrap(~Variabel, scales = "free") +
theme_minimal() +
labs(title = "Histogram Distribusi Fitur Kuantitatif Komponen Audio Spotify",
x = "Skala Nilai Variabel", y = "Frekuensi Munculan") +
theme(legend.position = "none",
strip.text = element_text(face = "bold", size = 10))Boxplot dirancang untuk mendeteksi keberadaan outlier secara visual, yang ditandai dengan sebaran titik merah di luar garis batas whiskers.
ggplot(df_long, aes(y = Nilai, fill = Variabel)) +
geom_boxplot(color = "black", alpha = 0.7, outlier.color = "red", outlier.shape = 16) +
facet_wrap(~Variabel, scales = "free") +
theme_minimal() +
labs(title = "Boxplot Multi-Variabel Audio Spotify untuk Identifikasi Outliers Visual",
y = "Rentang Nilai Kuantitatif") +
theme(legend.position = "none",
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
strip.text = element_text(face = "bold", size = 10))Meskipun secara visual outlier telah terpetakan pada boxplot, kami melakukan perhitungan matematis yang presisi menggunakan aturan Interquartile Range (IQR) untuk menghitung jumlah mutlak outlier pada masing-masing variabel.
# Fungsi kalkulasi mendeteksi amatan di luar [Q1 - 1.5*IQR] atau [Q3 + 1.5*IQR]
hitung_outlier <- function(x) {
q1 <- quantile(x, 0.25, na.rm = TRUE)
q3 <- quantile(x, 0.75, na.rm = TRUE)
iqr <- q3 - q1
lower_bound <- q1 - 1.5 * iqr
upper_bound <- q3 + 1.5 * iqr
sum(x < lower_bound | x > upper_bound, na.rm = TRUE)
}
outlier_summary <- df_numerik %>%
summarise(across(everything(), hitung_outlier))
print(outlier_summary)#> # A tibble: 1 × 11
#> popularity duration_ms danceability energy loudness speechiness acousticness
#> <int> <int> <int> <int> <int> <int> <int>
#> 1 0 30 1 0 40 72 0
#> # ℹ 4 more variables: instrumentalness <int>, liveness <int>, valence <int>,
#> # tempo <int>
Berdasarkan teori reduksi data dan manipulasi variabel, kami
merekayasa data dengan melahirkan 3 fitur baru yang
diturunkan dari variabel asli menggunakan kombinasi fungsi
mutate(). Fitur baru ini dibangun berlandaskan teori
struktur musik nyata (applied music theory) agar memiliki daya
penjelas yang tinggi.
df_engineered <- df_clean %>%
mutate(
# 1. Fitur Bentuk Rasio: Perbandingan Energi Terhadap Akustik
Energy_Acoustic_Ratio = energy / (acousticness + 0.001),
# 2. Fitur Bentuk Akumulasi: Estimasi Total Ketukan Sepanjang Lagu
Total_Estimated_Beats = (duration_ms / 1000 / 60) * tempo,
# 3. Fitur Bentuk Skor Gabungan: Indeks Suasana Positif Lagu
Audio_Positive_Vibe_Index = (danceability + energy + valence) / 3
)
# Menampilkan 5 baris teratas hasil ekstraksi fitur baru
df_engineered %>%
select(track_name, artists, Energy_Acoustic_Ratio, Total_Estimated_Beats, Audio_Positive_Vibe_Index) %>%
head(5)#> # A tibble: 5 × 5
#> track_name artists Energy_Acoustic_Ratio Total_Estimated_Beats
#> <chr> <chr> <dbl> <dbl>
#> 1 Aankhon Aankhon Yo Yo Honey… 3.40 531.
#> 2 Ailesa Shakti Siva… 2.92 555.
#> 3 El Maestro - En Vivo Babasónicos 2.05 319.
#> 4 No Chill Control Fre… 671. 416.
#> 5 Nunca Voy A Olvidarte LA INDIA 1.00 868.
#> # ℹ 1 more variable: Audio_Positive_Vibe_Index <dbl>
Energy_Acoustic_Ratio (Rasio Energi terhadap
Akustik)Alasan Pembuatan
Fitur ini dibentuk dari perbandingan antara variabel
energy dan acousticness. Kedua variabel
tersebut umumnya menunjukkan karakteristik yang berlawanan, di mana lagu
dengan tingkat energi tinggi cenderung memiliki unsur akustik yang
rendah, dan sebaliknya. Penambahan konstanta sebesar 0,001 pada penyebut
dilakukan untuk menghindari kemungkinan terjadinya pembagian dengan nol
sehingga proses perhitungan dapat berjalan dengan aman.
Interpretasi
Nilai rasio yang lebih besar dari 1 menunjukkan bahwa lagu lebih didominasi oleh karakter suara yang energik dan penggunaan instrumen elektrik modern, seperti pada genre Rock, EDM, atau Techno. Sebaliknya, nilai rasio yang mendekati 0 menunjukkan karakter lagu yang lebih tenang, lembut, dan banyak memanfaatkan instrumen akustik, seperti pada genre Folk, Akustik, atau Klasik.
Total_Estimated_Beats (Estimasi Total Ketukan)Alasan Pembuatan
Variabel tempo menggambarkan jumlah ketukan per menit
(BPM), sedangkan duration_ms menunjukkan durasi lagu dalam
milidetik. Dengan mengonversi durasi lagu ke satuan menit dan
mengalikannya dengan nilai tempo, diperoleh estimasi jumlah total
ketukan yang terjadi selama lagu diputar dari awal hingga akhir.
Interpretasi
Fitur ini merepresentasikan banyaknya ketukan irama yang terdapat dalam sebuah lagu. Nilai yang tinggi menunjukkan bahwa lagu memiliki durasi yang relatif panjang, tempo yang cepat, atau kombinasi keduanya. Sebaliknya, nilai yang rendah menunjukkan jumlah ketukan yang lebih sedikit selama lagu diputar.
Audio_Positive_Vibe_Index (Indeks Nuansa Positif
Audio)Alasan Pembuatan
Fitur ini dirancang untuk menggambarkan tingkat keceriaan sebuah lagu
secara lebih menyeluruh. Pembentukannya didasarkan pada rata-rata tiga
variabel utama, yaitu danceability, energy,
dan valence. Ketiga variabel tersebut dipilih karena
masing-masing mewakili aspek penting yang berkaitan dengan ritme,
intensitas energi, dan suasana emosional lagu.
Interpretasi
Nilai indeks berada pada rentang 0 hingga 1. Semakin mendekati 1, semakin tinggi tingkat keceriaan dan energi positif yang dimiliki lagu tersebut. Lagu dengan nilai indeks yang tinggi umumnya memiliki ritme yang mudah diikuti, energi yang kuat, serta nuansa emosional yang positif, sehingga cocok digunakan untuk aktivitas seperti olahraga, pesta, atau suasana yang membutuhkan peningkatan mood. Sebaliknya, nilai yang lebih rendah menunjukkan karakter lagu yang cenderung lebih tenang atau reflektif.
Data hasil rekayasa akhir ini diekspor secara resmi menjadi file CSV baru:
library(tidyverse)
library(corrplot)
library(ggcorrplot)
library(car) # Untuk VIF
library(glmnet) # Untuk LASSO
library(caret)
numeric_vars <- c("popularity", "duration_ms", "danceability", "energy", "loudness", "speechiness", "acousticness", "instrumentalness", "liveness", "valence", "tempo", "Energy_Acoustic_Ratio", "Total_Estimated_Beats", "Audio_Positive_Vibe_Index")
# Filter dataframe untuk variabel numerik saja
df_num <- df_engineered[, numeric_vars]
# Menghitung matriks korelasi
cor_matrix <- cor(df_num, use = "complete.obs")
# Visualisasi Heatmap Korelasi Interaktif
ggcorrplot(cor_matrix,
hc.order = TRUE,
type = "lower",
lab = TRUE,
lab_size = 2.5,
method = "circle",
colors = c("#6D9EC1", "white", "#E46726"),
title = "Matriks Korelasi Variabel Musik Spotify",
ggtheme = theme_minimal()) +
theme(
axis.text.x = element_text(size = 7, angle = 45, hjust = 1),
axis.text.y = element_text(size = 7),
plot.margin = margin(10, 10, 10, 10)
)Berdasarkan heatmap di atas, terdapat beberapa pola hubungan penting:
Korelasi Positif Paling Kuat: Variabel duration_ms dan Total_Estimated_Beats menunjukkan korelasi positif tertinggi di seluruh heatmap (r = 0.84). Hal ini terjadi karena Total_Estimated_Beats merupakan hasil perkalian langsung dari duration_ms dan tempo, sehingga keduanya membawa informasi yang hampir identik — menjadi justifikasi kuat untuk eliminasi pada tahap Feature Selection.
Korelasi Negatif Kuat: Hubungan antara energy dan acousticness menunjukkan korelasi negatif yang signifikan (r = −0.75). Lagu-lagu akustik murni cenderung memiliki karakteristik energi elektronik yang rendah.
Untuk membuktikan adanya gejala multikolinearitas secara objektif, dilakukan pengujian nilai VIF menggunakan model regresi linear global dengan target variabel popularity.
# Membuat model regresi global
df_vif <- df_num %>%
select(-Energy_Acoustic_Ratio,
-Audio_Positive_Vibe_Index)
vif_model <- lm(popularity ~ ., data = df_vif)
# Menghitung nilai VIF
vif_values <- vif(vif_model)
vif_table <- data.frame(Variable = names(vif_values), VIF = vif_values)
# Menampilkan tabel VIF
knitr::kable(vif_table, caption = "Nilai Variance Inflation Factor (VIF) Antar Variabel", digits = 3, align = "c")| Variable | VIF | |
|---|---|---|
| duration_ms | duration_ms | 16.513 |
| danceability | danceability | 1.571 |
| energy | energy | 4.209 |
| loudness | loudness | 3.177 |
| speechiness | speechiness | 1.098 |
| acousticness | acousticness | 2.516 |
| instrumentalness | instrumentalness | 1.466 |
| liveness | liveness | 1.128 |
| valence | valence | 1.693 |
| tempo | tempo | 6.858 |
| Total_Estimated_Beats | Total_Estimated_Beats | 22.519 |
Berdasarkan ambang batas statistik, suatu variabel dikatakan mengalami multikolinearitas serius jika nilai \(\text{VIF} > 5\) atau \(> 10\). Dari tabel di atas:
Guna mereduksi dimensi data tanpa menghilangkan sinyal informasi yang penting, diterapkan kombinasi dua pendekatan seleksi fitur yang berbeda: pendekatan berbasis korelasi target (bivariate filtering) dan pendekatan regularisasi berbasis penalti (multivariate regularisation).
Metode ini menyaring fitur berdasarkan kekuatan hubungannya langsung dengan variabel target (popularity) dengan batas ambang \(|r| \ge 0.10\).
# Korelasi seluruh variabel terhadap popularity
cor_with_target <- cor_matrix[, "popularity"]
cor_target_df <- data.frame(
Variabel = names(cor_with_target),
Korelasi_Popularity = cor_with_target
) %>% filter(Variabel != "popularity")
# Menentukan threshold 0.10
threshold <- 0.10
fitur_lolos_korelasi <- cor_target_df %>%
filter(abs(Korelasi_Popularity) >= threshold) %>%
pull(Variabel)
cat("=== Fitur yang Lolos Seleksi Korelasi (|r| >= 0.10): ===\n")#> === Fitur yang Lolos Seleksi Korelasi (|r| >= 0.10): ===
#> [1] "speechiness"
#>
#> === Fitur yang Dieliminasi: ===
print(setdiff(names(cor_with_target)[names(cor_with_target) != "popularity"], fitur_lolos_korelasi))#> [1] "duration_ms" "danceability"
#> [3] "energy" "loudness"
#> [5] "acousticness" "instrumentalness"
#> [7] "liveness" "valence"
#> [9] "tempo" "Energy_Acoustic_Ratio"
#> [11] "Total_Estimated_Beats" "Audio_Positive_Vibe_Index"
Hasil seleksi menunjukkan hanya variabel speechiness
yang melampaui ambang batas |r| ≥ 0.10 terhadap popularity. Hal ini
bukan berarti variabel lain tidak penting, melainkan mencerminkan bahwa
variabel popularity pada dataset Spotify bersifat noisy —
dipengaruhi oleh faktor eksternal seperti algoritma rekomendasi platform
dan tren sosial yang tidak tertangkap oleh fitur audio murni. Oleh
karena itu, metode Correlation Threshold digunakan sebagai evaluasi awal
hubungan linear, sementara keputusan seleksi final diserahkan kepada
metode LASSO yang mampu menangkap kontribusi multivariat secara lebih
komprehensif.
Metode kedua menggunakan algoritma penalti L1 (LASSO Regression). Metode ini bekerja secara objektif di tingkat multivariat dengan menyusutkan koefisien variansi dari fitur-fitur yang tidak berkontribusi signifikan atau bersifat redundan tepat menjadi nol.
# Menyiapkan matriks untuk LASSO
X <- as.matrix(df_num %>% select(-popularity))
y <- df_num$popularity
# Menggunakan Cross-Validation untuk mencari lambda optimal
set.seed(123)
cv_lasso <- cv.glmnet(X, y, alpha = 1)
# Plot koefisien LASSO berdasarkan nilai Lambda
plot(cv_lasso)
title("Optimasi Penalti Lambda pada Regulasi LASSO music Spotify", line = 2.5)# Mengambil koefisien pada lambda minimum terbaik
best_lambda <- cv_lasso$lambda.min
lasso_model <- glmnet(X, y, alpha = 1, lambda = best_lambda)
lasso_coefs <- coef(lasso_model)
# Mengubah ke dataframe untuk visualisasi teks
coef_df <- data.frame(
Fitur = rownames(lasso_coefs),
Koefisien = as.vector(lasso_coefs)
) %>% filter(Fitur != "(Intercept)")
cat("=== Koefisien Fitur dari Model LASSO: ===\n")#> === Koefisien Fitur dari Model LASSO: ===
#> Fitur Koefisien
#> 1 duration_ms 0.000000000
#> 2 danceability 9.034718687
#> 3 energy 3.799232227
#> 4 loudness 0.000000000
#> 5 speechiness -22.417632072
#> 6 acousticness -1.306073535
#> 7 instrumentalness -1.247208137
#> 8 liveness -4.680567179
#> 9 valence -11.544422728
#> 10 tempo 0.000000000
#> 11 Energy_Acoustic_Ratio -0.005527578
#> 12 Total_Estimated_Beats 0.003139165
#> 13 Audio_Positive_Vibe_Index 0.000000000
Sebagai konklusi dari fase pengujian variabel, fitur final ditentukan berdasarkan hasil LASSO Regression sebagai metode seleksi utama, dikombinasikan dengan eliminasi variabel yang memiliki nilai VIF ekstrem (>10). Pendekatan ini memastikan subset fitur yang diserahkan ke Orang Ketiga bebas dari redundansi dan memiliki dimensi yang cukup untuk analisis PCA yang bermakna.
# Fitur final berdasarkan LASSO (koefisien non-zero)
fitur_terpilih_lasso <- coef_df %>%
filter(Koefisien != 0) %>%
pull(Fitur)
# Buang variabel dengan VIF ekstrem (>10)
variabel_vif_ekstrem <- c("Total_Estimated_Beats", "duration_ms")
# Fitur final = hasil LASSO minus variabel VIF ekstrem
fitur_final_pca <- setdiff(fitur_terpilih_lasso, variabel_vif_ekstrem)
cat("=== Fitur Final untuk PCA (Orang 3): ===\n")#> === Fitur Final untuk PCA (Orang 3): ===
#> [1] "danceability" "energy" "speechiness"
#> [4] "acousticness" "instrumentalness" "liveness"
#> [7] "valence" "Energy_Acoustic_Ratio"
# Tabel ringkasan
ringkasan_fitur <- data.frame(
Variabel = names(cor_with_target)[names(cor_with_target) != "popularity"]
) %>%
mutate(
Lolos_LASSO = if_else(Variabel %in% fitur_terpilih_lasso, "Ya", "Tidak"),
VIF_Ekstrem = if_else(Variabel %in% variabel_vif_ekstrem, "Ya", "Tidak"),
Keputusan_Final = if_else(
Variabel %in% fitur_final_pca, "DIPERTAHANKAN", "DIELIMINASI"
)
)
knitr::kable(
ringkasan_fitur,
caption = "Matriks Keputusan Final Penyaringan Fitur Audio Spotify",
align = "c"
)| Variabel | Lolos_LASSO | VIF_Ekstrem | Keputusan_Final |
|---|---|---|---|
| duration_ms | Tidak | Ya | DIELIMINASI |
| danceability | Ya | Tidak | DIPERTAHANKAN |
| energy | Ya | Tidak | DIPERTAHANKAN |
| loudness | Tidak | Tidak | DIELIMINASI |
| speechiness | Ya | Tidak | DIPERTAHANKAN |
| acousticness | Ya | Tidak | DIPERTAHANKAN |
| instrumentalness | Ya | Tidak | DIPERTAHANKAN |
| liveness | Ya | Tidak | DIPERTAHANKAN |
| valence | Ya | Tidak | DIPERTAHANKAN |
| tempo | Tidak | Tidak | DIELIMINASI |
| Energy_Acoustic_Ratio | Ya | Tidak | DIPERTAHANKAN |
| Total_Estimated_Beats | Ya | Ya | DIELIMINASI |
| Audio_Positive_Vibe_Index | Tidak | Tidak | DIELIMINASI |
# Export subset final
df_final_pca <- df_engineered %>% select(all_of(fitur_final_pca))
setwd("C:/Users/MyBook Hype AMD/OneDrive/Desktop/SEMESTER 4/eksplorasi dan visualisasi data")
write_csv(df_final_pca, "Spotify_Final_PCA.csv")Metode Utama — LASSO Regression: LASSO digunakan sebagai penentu utama seleksi fitur karena mampu menangani data multivariat dan secara otomatis menyusutkan koefisien variabel yang redundan menjadi nol.
Eliminasi Berdasarkan VIF Ekstrem: Variabel
Total_Estimated_Beats (VIF = 22.519) dan
duration_ms (VIF = 16.513) dieliminasi karena redundansi
ekstrem — Total_Estimated_Beats merupakan turunan langsung dari
duration_ms × tempo sehingga informasinya tumpang tindih.
Subset Final untuk PCA: Variabel yang dioper ke Orang 3 adalah: danceability, energy, speechiness, acousticness, instrumentalness, liveness, valence, dan Energy_Acoustic_Ratio (jika koefisien LASSO-nya non-zero). Subset ini cukup untuk PCA yang bermakna karena memiliki lebih dari 5 variabel dengan informasi yang beragam.
Setelah melalui tahapan feature engineering serta feature selection, data yang tersisa masih mengandung hubungan linear antar variabel audio. Kondisi ini menyebabkan informasi antar fitur saling tumpang tindih (redundant information), sehingga diperlukan proses feature extraction untuk merangkum informasi tersebut ke dimensi yang lebih ringkas.
Metode yang digunakan pada penelitian ini adalah Principal Component Analysis (PCA), yaitu teknik reduksi dimensi yang mentransformasikan sekumpulan variabel asli menjadi sejumlah komponen baru (principal components) yang bersifat:
Sesuai teori pada materi reduksi data, PCA sangat penting digunakan ketika data mengalami gejala multikolinearitas dan memiliki jumlah fitur yang cukup banyak.
Sebelum dilakukan Principal Component Analysis (PCA), seluruh
variabel terlebih dahulu distandardisasi menggunakan fungsi
scale(). Tahap ini bersifat sangat penting karena setiap
variabel memiliki skala dan penyebaran nilai yang berbeda.
library(tidyverse)
library(factoextra)
# Membaca data final hasil feature selection
df_final_pca <- read_csv("C:/Users/MyBook Hype AMD/OneDrive/Desktop/SEMESTER 4/eksplorasi dan visualisasi data/Spotify_Final_PCA.csv")Sebagai contoh:
Apabila standardisasi tidak dilakukan, maka variabel dengan skala terbesar akan mendominasi pembentukan principal component dan menyebabkan hasil PCA menjadi bias secara matematis.
Transformasi Z-score dilakukan menggunakan rumus:
\[ Z = \frac{x - \mu}{\sigma} \]
dengan:
#> spc_tbl_ [600 × 8] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
#> $ danceability : num [1:600] 0.746 0.628 0.65 0.593 0.546 0.676 0.787 0.603 0.49 0.791 ...
#> $ energy : num [1:600] 0.988 0.79 0.915 0.937 0.628 0.338 0.872 0.525 0.0614 0.808 ...
#> $ speechiness : num [1:600] 0.0637 0.0655 0.0368 0.0566 0.0441 0.0284 0.143 0.0412 0.0397 0.0334 ...
#> $ acousticness : num [1:600] 0.29 0.27 0.446 0.000397 0.625 0.372 0.0067 0.135 0.979 0.347 ...
#> $ instrumentalness : num [1:600] 2.18e-03 6.83e-04 0.00 6.28e-01 1.10e-02 5.57e-06 1.93e-04 0.00 8.48e-01 2.14e-02 ...
#> $ liveness : num [1:600] 0.131 0.606 0.91 0.302 0.0801 0.468 0.136 0.0714 0.111 0.0877 ...
#> $ valence : num [1:600] 0.61 0.47 0.885 0.0333 0.708 0.321 0.696 0.273 0.232 0.745 ...
#> $ Energy_Acoustic_Ratio: num [1:600] 3.4 2.92 2.05 670.72 1 ...
#> - attr(*, "spec")=
#> .. cols(
#> .. danceability = col_double(),
#> .. energy = col_double(),
#> .. speechiness = col_double(),
#> .. acousticness = col_double(),
#> .. instrumentalness = col_double(),
#> .. liveness = col_double(),
#> .. valence = col_double(),
#> .. Energy_Acoustic_Ratio = col_double()
#> .. )
#> - attr(*, "problems")=<externalptr>
Melalui standardisasi Z-Score, seluruh variabel diubah ke skala yang seragam dengan:
Dengan demikian, setiap variabel memperoleh kontribusi yang lebih adil dalam proses ekstraksi komponen utama.
Berdasarkan output:
#> [1] 600 8
Artinya, data akhir yang digunakan pada tahap PCA terdiri atas:
Dataset ini telah memenuhi syarat untuk dilakukan analisis multivariat berbasis reduksi dimensi menggunakan Principal Component Analysis (PCA).
Tahap Principal Component Analysis (PCA) dilakukan untuk mereduksi dimensi data dari variabel audio Spotify yang telah melalui proses feature selection sebelumnya. Sebelum dilakukan PCA, seluruh variabel numerik telah distandarisasi menggunakan metode Z-score untuk memastikan setiap variabel memiliki skala yang sama dan tidak saling mendominasi dalam perhitungan komponen utama.
# PCA tanpa standardisasi ulang
pca_model <- prcomp(data_scaled)
# Ringkasan hasil PCA
summary(pca_model)#> Importance of components:
#> PC1 PC2 PC3 PC4 PC5 PC6 PC7
#> Standard deviation 1.5408 1.3008 1.1002 0.9374 0.8338 0.74701 0.62230
#> Proportion of Variance 0.2968 0.2115 0.1513 0.1098 0.0869 0.06975 0.04841
#> Cumulative Proportion 0.2968 0.5083 0.6595 0.7694 0.8563 0.92605 0.97446
#> PC8
#> Standard deviation 0.45202
#> Proportion of Variance 0.02554
#> Cumulative Proportion 1.00000
PCA menghasilkan 8 principal components (PC1 hingga PC8) yang masing-masing menjelaskan proporsi variasi data sebagai berikut:
Dari hasil tersebut terlihat bahwa:
Hal ini menunjukkan bahwa karakteristik audio musik Spotify bersifat multidimensional, di mana tidak ada satu faktor tunggal yang mendominasi seluruh variasi data.
Model PCA berhasil mereduksi kompleksitas data dari 8 variabel menjadi beberapa komponen utama yang lebih ringkas. Berdasarkan cumulative variance, penggunaan 4 principal components sudah cukup optimal karena mampu mempertahankan lebih dari 70% informasi dari data asli.
Berdasarkan hasil PCA, diperoleh eigenvalue serta proporsi variansi dari masing-masing principal component sebagai berikut:
# Mengambil eigenvalue
eigenvalues <- pca_model$sdev^2
# Proporsi variasi
prop_variance <- eigenvalues / sum(eigenvalues)
# Variasi kumulatif
cum_variance <- cumsum(prop_variance)
# Membuat tabel ringkasan
tabel_pca <- data.frame(
Komponen = paste0("PC", 1:length(eigenvalues)),
Eigenvalue = eigenvalues,
Proporsi_Variansi = prop_variance,
Kumulatif_Variansi = cum_variance
)
# Menampilkan tabel
knitr::kable(
tabel_pca,
digits = 4,
caption = "Ringkasan Variansi Principal Component"
)| Komponen | Eigenvalue | Proporsi_Variansi | Kumulatif_Variansi |
|---|---|---|---|
| PC1 | 2.3740 | 0.2967 | 0.2967 |
| PC2 | 1.6921 | 0.2115 | 0.5083 |
| PC3 | 1.2104 | 0.1513 | 0.6596 |
| PC4 | 0.8788 | 0.1098 | 0.7694 |
| PC5 | 0.6952 | 0.0869 | 0.8563 |
| PC6 | 0.5580 | 0.0698 | 0.9261 |
| PC7 | 0.3873 | 0.0484 | 0.9745 |
| PC8 | 0.2043 | 0.0255 | 1.0000 |
Interpretasi PCA dilakukan menggunakan dua pendekatan utama:
Menurut kriteria Kaiser, komponen dipertahankan jika memiliki:
\[ \text{Eigenvalue} > 1 \]
Karena komponen dengan eigenvalue besar mampu menjelaskan variasi data lebih baik dibanding satu variabel asli. Jadi, PC1, PC2, dan PC3 layak dipertahankan karena memiliki \(\text{Eigenvalue} > 1\)
Komponen dipilih hingga total variasi kumulatif mencapai minimal:
Apabila dua atau tiga komponen pertama sudah mampu menjelaskan mayoritas variasi data, maka reduksi dimensi dianggap berhasil.
Scree plot digunakan untuk memvisualisasikan penurunan eigenvalue antar komponen utama.
fviz_eig(pca_model,
addlabels = TRUE,
ylim = c(0, 60),
main = "Scree Plot Principal Component Spotify")Visualisasi scree plot di atas memberikan konfirmasi visual yang konsisten dengan analisis matematis sebelumnya melalui beberapa poin penting:
Jika dilihat dari bentuk grafiknya, penurunan persentase varians dari PC1 hingga PC8 cenderung landai dan tidak memiliki tekukan tajam (elbow) yang ekstrem.
Menggabungkan analisis kriteria Kaiser, proporsi kumulatif, dan konfirmasi visual dari scree plot, maka diputuskan untuk mempertahankan 4 Principal Components pertama (PC1, PC2, PC3, dan PC4).
Pilihan ini diambil sebagai jalan tengah terbaik: kita berhasil mereduksi dimensi data hingga 50% (dari 8 variabel menjadi 4 komponen), namun tetap berhasil mempertahankan sebagian besar informasi penting dari dataset Spotify, yaitu sebesar 76,94%. Komponen sisanya (PC5 hingga PC8) dapat diabaikan karena grafik scree plot menunjukkan kontribusinya yang sudah tidak signifikan.
Loading factor menunjukkan kontribusi masing-masing variabel terhadap principal component.
# Loading factor
loading_factor <- pca_model$rotation
# Menampilkan loading
print(round(loading_factor, 4))#> PC1 PC2 PC3 PC4 PC5 PC6 PC7
#> danceability -0.3610 -0.4425 -0.1309 0.3240 -0.2970 -0.2109 -0.6387
#> energy -0.5546 0.2667 0.0354 -0.0058 -0.0890 -0.0564 0.2976
#> speechiness -0.0814 0.0039 0.6432 0.6898 0.2891 0.0689 0.0901
#> acousticness 0.5125 -0.2949 0.1241 -0.0244 0.0726 0.4467 -0.2014
#> instrumentalness 0.2907 0.3584 -0.1335 0.4302 -0.7360 0.1691 0.1154
#> liveness -0.0940 0.0669 0.7126 -0.4822 -0.4360 0.0419 -0.2113
#> valence -0.4045 -0.3859 -0.1077 -0.0307 -0.1279 0.7213 0.2842
#> Energy_Acoustic_Ratio -0.1895 0.6035 -0.1237 0.0020 0.2588 0.4443 -0.5622
#> PC8
#> danceability 0.1055
#> energy 0.7213
#> speechiness -0.0862
#> acousticness 0.6238
#> instrumentalness -0.0242
#> liveness -0.0992
#> valence -0.2398
#> Energy_Acoustic_Ratio -0.0641
Visualisasi loading digunakan untuk melihat variabel mana yang paling dominan membentuk principal component.
fviz_pca_var(pca_model,
col.var = "contrib",
repel = TRUE,
gradient.cols = c("skyblue", "orange", "red"),
title = "Visualisasi Loading Factor PCA Spotify")Grafik ini memvisualisasikan bagaimana variabel-variabel audio Spotify tersebar dan berkorelasi di dalam ruang dua dimensi utama (Dim1 dan Dim2). Interpretasi grafik ini dapat dibagi menjadi tiga poin utama:
energy, acousticness,
danceability, valence, dan
Energy_Acoustic_Ratio memiliki panah yang panjang dan
mendekati lingkaran luar. Hal ini menandakan bahwa variabel-variabel
tersebut memiliki kontribusi yang sangat besar dan esensial dalam
membentuk struktur Dim1 dan Dim2.liveness dan speechiness memiliki panah yang
sangat pendek dan berada di dekat pusat lingkaran. Hal ini menunjukkan
bahwa kedua variabel tersebut tidak berkontribusi kuat pada Dim1 maupun
Dim2 (kedua variabel ini baru akan terlihat dominan pada dimensi
berikutnya, yaitu Dim3 dan Dim4).Sumbu horizontal melambangkan Dim1 (29.7% varians):
acousticness
berdiri sendiri secara dominan.energy, valence, dan
danceability.acousticness berlawanan arah
(membentuk sudut hampir 180 derajat) dengan energy. Ini
membuktikan adanya korelasi negatif yang kuat secara visual: semakin
akustik sebuah lagu Spotify, maka energinya akan semakin rendah, dan
begitu pula sebaliknya.Sumbu vertikal melambangkan Dim2 (21.2% varians):
Energy_Acoustic_Ratio dan
instrumentalness.danceability dan valence.Energy_Acoustic_Ratio
membentuk sudut hampir tegak lurus (90 derajat) dengan
acousticness atau energy. Artinya, variasi
rasio energi-akustik ini bergerak secara independen (tidak terikat) dari
nilai absolut akustik dasar lagunya.# Membuat dataframe score PCA
score_pca <- as.data.frame(pca_model$x)
# Visualisasi Score Plot
ggplot(score_pca, aes(x = PC1, y = PC2)) +
geom_point(alpha = 0.7, color = "steelblue") +
theme_minimal() +
labs(
title = "Score Plot PCA Lagu Spotify",
x = "Principal Component 1 (PC1)",
y = "Principal Component 2 (PC2)"
)Grafik ini sebenarnya sedang menunjukkan “peta wilayah” dari lagu-lagu Spotify setelah dimensinya diringkas oleh PCA. Jika kita gabungkan dengan arah panah dari grafik loading factor sebelumnya, kita bisa membagi peta ini menjadi beberapa wilayah karakter:
Wilayah Kiri (Karakter Musik Energik) Jika dilihat, gerombolan
titik yang paling ramai dan menumpuk berada di sebelah kiri (PC1 minus).
Karena area kiri ini memiliki nilai energy dan
danceability yang tinggi, artinya mayoritas lagu dalam
dataset ini merupakan tipe musik modern yang bertempo cepat, ceria, dan
ritmis (seperti genre Pop komersial, EDM, atau Hip-Hop).
Wilayah Kanan (Karakter Musik Akustik) Semakin ke kanan arah
titik-titiknya (PC1 positif), sebarannya terlihat semakin renggang. Area
kanan ini adalah wilayah kekuasaan acousticness. Jadi,
lagu-lagu yang berada di sebelah kanan ini adalah lagu-lagu akustik yang
tenang, kalem, dan minim instrumen listrik (seperti genre indie folk,
acoustic ballad, atau piano klasik).
Wilayah Atas (Karakter Musik Instrumental) Perhatikan beberapa
titik yang mencuat sendirian ke arah atas (PC2 positif tinggi). Area
atas ini diisi oleh variabel instrumentalness dan
Energy_Acoustic_Ratio. Artinya, lagu-lagu di posisi atas
ini merupakan musik instrumen yang fokus pada aransemen tanpa vokal,
contohnya seperti musik Lofi atau lagu latar instrumental.
Wilayah Bawah (Karakter Vokal Dominan) Sementara untuk titik-titik yang mengarah ke bawah (PC2 minus), ini menandakan lagu-lagu pop mainstream yang aransemen musiknya lebih sederhana, namun karakter vokal penyanyi utamanya dibuat sangat menonjol dan dominan.
Biplot digunakan untuk menampilkan hubungan simultan antara observasi dan variabel dalam ruang principal component.
jangan hanya gini saja rcodenya, nanti output plotnya terlihat menupuk dan panahnya tidak terlihat
fviz_pca_biplot(pca_model,
repel = TRUE,
col.var = "red",
col.ind = "gray40",
title = "Biplot PCA Karakteristik Audio Spotify")
lebih baik seperti ini:
fviz_pca_biplot(pca_model,
repel = TRUE,
geom.ind = "point", # Mengubah observasi menjadi titik saja, tanpa teks angka
col.var = "red",
col.ind = "gray60", # Titik data dibuat abu-abu transparan/lembut
alpha.ind = 0.6, # Mengatur transparansi titik agar sebaran terlihat
title = "Biplot PCA Karakteristik Audio Spotify")Biplot di atas menggabungkan sebaran posisi seluruh lagu (titik abu-abu) dengan arah kontribusi variabel (panah oranye). Dari grafik tersebut, kita bisa memetakan karakteristik lagu ke dalam 4 kuadran utama:
Area ini merupakan tempat berkumpulnya lagu-lagu dengan nilai
energy tinggi dan nilai Energy_Acoustic_Ratio
yang dominan. Lagu-lagu di kuadran ini memiliki karakteristik musik yang
keras, cepat, berisik, dan kental dengan nuansa aransemen
modern/digital.
Area ini didominasi oleh pergerakan panah danceability
dan valence. Lagu-lagu yang jatuh di kuadran ini memiliki
ritme yang sangat asyik untuk dipakai berdansa, memiliki groove yang
kuat, serta membawa suasana hati (mood) yang positif, ceria, atau
bahagia.
Sesuai dengan arah panah acousticness, wilayah kanan
bawah ini mengelompokkan lagu-lagu Spotify yang didominasi oleh
instrumen musik alami (gitar akustik, piano, vokal murni). Karakteristik
lagunya cenderung tenang, syahdu, minim distorsi elektronik, dan
memiliki tingkat energi yang rendah.
Kuadran ini mengarah pada variabel instrumentalness. Di
sinilah lagu-lagu yang minim vokal (atau tanpa lirik sama sekali)
berkumpul, seperti musik-musik lofi, instrumental klasik, atau lagu
pengantar tidur/belajar.
Dari hasil analisis PCA, ternyata ada beberapa karakteristik audio yang paling kuat dalam menentukan “warna” dari lagu-lagu Spotify di dataset ini, yaitu:
energy dan acousticness (yang dominan
banget di PC1)Energy_Acoustic_Ratio (yang memegang kendali di
PC2)danceability dan valence (aspek keceriaan
dan irama lagu)Bisa dibilang, variabel-variabel inilah yang paling sensitif dalam membedakan identitas antar-lagu.
Jelas berhasil sekali. Ada tiga alasan utamanya:
Setelah dibedah isi bobotnya, ternyata 4 komponen yang kita simpan ini punya “tugas” unik masing-masing dalam mengenali lagu:
energy, valence, dan
danceability). Sementara di sisi positifnya, dikuasai penuh
oleh lagu-lagu organik yang tenang, syahdu, dan minim distorsi
(acousticness).Energy_Acoustic_Ratio
dan instrumentalness). Kebalikannya, di sisi negatif diisi
oleh lagu-lagu pop komersial yang mengutamakan vokal dominan serta irama
yang asyik untuk dinikmati santai (danceability dan
valence).liveness)
atau lagu yang didominasi oleh suara orang berbicara intens
(speechiness).speechiness positif) serta didukung aransemen
instrumen latar yang kuat (instrumentalness positif), namun
diproduksi secara bersih di dalam studio, bukan di panggung konser
(liveness bernilai negatif). Contoh gampangnya seperti
karakteristik pada musik hip-hop atau rap studio.Analisis PCA ini membuktikan kalau musik di Spotify itu tidak sesederhana “lagu cepat atau lambat”. Karakter musik itu bersifat multidimensional.
Secara keseluruhan, lagu-lagu di Spotify bisa dipetakan lewat dua kombinasi besar: pertama, seberapa kuat energinya dibanding sisi akustiknya (PC1 & PC2), dan kedua, bagaimana suasana panggung serta kepadatan vokalnya (PC3 & PC4).
Struktur berlapis inilah yang bikin kita tahu kalau algoritma rekomendasi Spotify gak bisa cuma pakai satu fitur doang, tapi harus mengkombinasikan keempat dimensi ini biar bisa menebak selera lagu kita dengan pas.