EKSPLORASI DAN REDUKSI DATA PADA DATASET SPOTIFY
Menggunakan Feature Engineering, Feature Selection,
dan Principal Component Analysis (PCA)
Tugas ini disusun untuk memenuhi tugas mata
kuliah
Eksplorasi dan Visualisasi Data
Dosen Pengampu:
Agung Satrio Wicaksono, S.Mat., M.Si.
Disusun oleh:
| Nazwa Khoirina | 3338240005 |
| Tadzkiah Fayrooz Ridwan | 3338240029 |
| Delvira Damayanti | 3338240042 |
PROGRAM STUDI STATISTIKA
FAKULTAS TEKNIK
UNIVERSITAS SULTAN AGENG TIRTAYASA
2026
Dataset Spotify
library(readr)
library(tidyverse)
# =====================================================
# 1. IMPORT DATA
# =====================================================
spotify <- read_csv("spotify tracks dataset.csv")
# =====================================================
# 2. MENGAMBIL 1000 DATA SECARA ACAK
# =====================================================
set.seed(123)
spotify <- spotify[sample(nrow(spotify), 1000), ]Dalam analisis ini digunakan sebanyak 1000 observasi yang dipilih secara acak dari total 114.000 observasi pada dataset Spotify Tracks. Pemilihan 1000 observasi dilakukan agar proses pengolahan data menjadi lebih efisien, namun tetap mampu merepresentasikan karakteristik data secara keseluruhan untuk keperluan analisis multivariat dan Principal Component Analysis (PCA).
# =====================================================
# 3. MELIHAT DATA AWAL
# =====================================================
head(spotify)## # A tibble: 6 × 22
## ...1 `Unnamed: 0` track_id artists album_name track_name popularity
## <dbl> <dbl> <chr> <chr> <chr> <chr> <dbl>
## 1 51662 51662 78PDj0uocOvtSJCd… Yo Yo … Bhaag Joh… Aankhon A… 59
## 2 57869 57869 1hP0hDL5VREpThmM… Shakti… Ailesa Ailesa 42
## 3 2985 2985 5EL8He4J2hrTWl9r… Babasó… Desde Ade… El Maestr… 44
## 4 29924 29924 46VgwcEKnjPCcSEs… Contro… Sable Val… No Chill 39
## 5 95245 95245 0WjreSYeix5YZRbw… LA IND… The Great… Nunca Voy… 34
## 6 103064 103064 07U6dNp0xM9htc4A… Omar A… All That … Archetype 4
## # ℹ 15 more variables: duration_ms <dbl>, explicit <lgl>, danceability <dbl>,
## # energy <dbl>, key <dbl>, loudness <dbl>, mode <dbl>, speechiness <dbl>,
## # acousticness <dbl>, instrumentalness <dbl>, liveness <dbl>, valence <dbl>,
## # tempo <dbl>, time_signature <dbl>, track_genre <chr>
## tibble [1,000 × 22] (S3: tbl_df/tbl/data.frame)
## $ ...1 : num [1:1000] 51662 57869 2985 29924 95245 ...
## $ Unnamed: 0 : num [1:1000] 51662 57869 2985 29924 95245 ...
## $ track_id : chr [1:1000] "78PDj0uocOvtSJCdOt65qy" "1hP0hDL5VREpThmMOa1pta" "5EL8He4J2hrTWl9rxbE3DY" "46VgwcEKnjPCcSEsJ5fWY2" ...
## $ artists : chr [1:1000] "Yo Yo Honey Singh" "Shakti Sivamani" "Babasónicos" "Control Freak" ...
## $ album_name : chr [1:1000] "Bhaag Johnny" "Ailesa" "Desde Adentro - Impuesto de Fe (En Vivo)" "Sable Valley Summer Vol. 2" ...
## $ track_name : chr [1:1000] "Aankhon Aankhon" "Ailesa" "El Maestro - En Vivo" "No Chill" ...
## $ popularity : num [1:1000] 59 42 44 39 34 4 0 55 35 57 ...
## $ duration_ms : num [1:1000] 244831 250601 170866 178285 299613 ...
## $ explicit : logi [1:1000] FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ danceability : num [1:1000] 0.746 0.628 0.65 0.593 0.546 0.676 0.787 0.603 0.49 0.791 ...
## $ energy : num [1:1000] 0.988 0.79 0.915 0.937 0.628 0.338 0.872 0.525 0.0614 0.808 ...
## $ key : num [1:1000] 10 5 4 1 6 9 9 2 0 7 ...
## $ loudness : num [1:1000] -4.57 -7.16 -5.76 -6.7 -10.29 ...
## $ mode : num [1:1000] 0 0 0 0 1 1 1 1 1 1 ...
## $ speechiness : num [1:1000] 0.0637 0.0655 0.0368 0.0566 0.0441 0.0284 0.143 0.0412 0.0397 0.0334 ...
## $ acousticness : num [1:1000] 0.29 0.27 0.446 0.000397 0.625 0.372 0.0067 0.135 0.979 0.347 ...
## $ instrumentalness: num [1:1000] 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:1000] 0.131 0.606 0.91 0.302 0.0801 0.468 0.136 0.0714 0.111 0.0877 ...
## $ valence : num [1:1000] 0.61 0.47 0.885 0.0333 0.708 0.321 0.696 0.273 0.232 0.745 ...
## $ tempo : num [1:1000] 130 133 112 140 174 ...
## $ time_signature : num [1:1000] 4 4 4 4 4 4 4 4 4 4 ...
## $ track_genre : chr [1:1000] "hip-hop" "indie" "alt-rock" "dubstep" ...
## [1] 1000 22
## [1] "...1" "Unnamed: 0" "track_id" "artists"
## [5] "album_name" "track_name" "popularity" "duration_ms"
## [9] "explicit" "danceability" "energy" "key"
## [13] "loudness" "mode" "speechiness" "acousticness"
## [17] "instrumentalness" "liveness" "valence" "tempo"
## [21] "time_signature" "track_genre"
## ...1 Unnamed: 0 track_id artists
## Min. : 30 Min. : 30 Length:1000 Length:1000
## 1st Qu.: 28046 1st Qu.: 28046 Class :character Class :character
## Median : 56187 Median : 56187 Mode :character Mode :character
## Mean : 56077 Mean : 56077
## 3rd Qu.: 83659 3rd Qu.: 83659
## Max. :113841 Max. :113841
## album_name track_name popularity duration_ms
## Length:1000 Length:1000 Min. : 0.00 Min. : 39775
## Class :character Class :character 1st Qu.:17.00 1st Qu.:173465
## Mode :character Mode :character Median :35.00 Median :214433
## Mean :33.72 Mean :228868
## 3rd Qu.:51.00 3rd Qu.:264231
## Max. :93.00 Max. :716079
## explicit danceability energy key
## Mode :logical Min. :0.0000 Min. :0.00189 Min. : 0.000
## FALSE:911 1st Qu.:0.4540 1st Qu.:0.46775 1st Qu.: 2.000
## TRUE :89 Median :0.5780 Median :0.68400 Median : 5.000
## Mean :0.5647 Mean :0.64169 Mean : 5.211
## 3rd Qu.:0.6930 3rd Qu.:0.85800 3rd Qu.: 8.000
## Max. :0.9450 Max. :0.99900 Max. :11.000
## loudness mode speechiness acousticness
## Min. :-41.739 Min. :0.000 Min. :0.00000 Min. :0.00000
## 1st Qu.: -9.896 1st Qu.:0.000 1st Qu.:0.03530 1st Qu.:0.02368
## Median : -6.756 Median :1.000 Median :0.04875 Median :0.17000
## Mean : -8.093 Mean :0.648 Mean :0.08537 Mean :0.32469
## 3rd Qu.: -4.911 3rd Qu.:1.000 3rd Qu.:0.08123 3rd Qu.:0.61675
## Max. : -0.250 Max. :1.000 Max. :0.94800 Max. :0.99500
## instrumentalness liveness valence tempo
## Min. :0.0000000 Min. :0.0212 Min. :0.0000 Min. : 0.00
## 1st Qu.:0.0000000 1st Qu.:0.0974 1st Qu.:0.2552 1st Qu.: 99.49
## Median :0.0000174 Median :0.1345 Median :0.4585 Median :122.01
## Mean :0.1462549 Mean :0.2194 Mean :0.4743 Mean :121.26
## 3rd Qu.:0.0269250 3rd Qu.:0.2850 3rd Qu.:0.6870 3rd Qu.:139.68
## Max. :0.9990000 Max. :0.9910 Max. :0.9830 Max. :208.28
## time_signature track_genre
## Min. :0.000 Length:1000
## 1st Qu.:4.000 Class :character
## Median :4.000 Mode :character
## Mean :3.909
## 3rd Qu.:4.000
## Max. :5.000
# =====================================================
# 4. MEMILIH VARIABEL NUMERIK
# =====================================================
spotify_num <- spotify[, c("popularity",
"duration_ms",
"danceability",
"energy",
"loudness",
"speechiness",
"acousticness",
"instrumentalness",
"liveness",
"valence",
"tempo")]
head(spotify_num)## # A tibble: 6 × 11
## popularity duration_ms danceability energy loudness speechiness acousticness
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 59 244831 0.746 0.988 -4.57 0.0637 0.29
## 2 42 250601 0.628 0.79 -7.16 0.0655 0.27
## 3 44 170866 0.65 0.915 -5.76 0.0368 0.446
## 4 39 178285 0.593 0.937 -6.70 0.0566 0.000397
## 5 34 299613 0.546 0.628 -10.3 0.0441 0.625
## 6 4 168828 0.676 0.338 -7.96 0.0284 0.372
## # ℹ 4 more variables: instrumentalness <dbl>, liveness <dbl>, valence <dbl>,
## # tempo <dbl>
## tibble [1,000 × 11] (S3: tbl_df/tbl/data.frame)
## $ popularity : num [1:1000] 59 42 44 39 34 4 0 55 35 57 ...
## $ duration_ms : num [1:1000] 244831 250601 170866 178285 299613 ...
## $ danceability : num [1:1000] 0.746 0.628 0.65 0.593 0.546 0.676 0.787 0.603 0.49 0.791 ...
## $ energy : num [1:1000] 0.988 0.79 0.915 0.937 0.628 0.338 0.872 0.525 0.0614 0.808 ...
## $ loudness : num [1:1000] -4.57 -7.16 -5.76 -6.7 -10.29 ...
## $ speechiness : num [1:1000] 0.0637 0.0655 0.0368 0.0566 0.0441 0.0284 0.143 0.0412 0.0397 0.0334 ...
## $ acousticness : num [1:1000] 0.29 0.27 0.446 0.000397 0.625 0.372 0.0067 0.135 0.979 0.347 ...
## $ instrumentalness: num [1:1000] 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:1000] 0.131 0.606 0.91 0.302 0.0801 0.468 0.136 0.0714 0.111 0.0877 ...
## $ valence : num [1:1000] 0.61 0.47 0.885 0.0333 0.708 0.321 0.696 0.273 0.232 0.745 ...
## $ tempo : num [1:1000] 130 133 112 140 174 ...
## popularity duration_ms danceability energy
## Min. : 0.00 Min. : 39775 Min. :0.0000 Min. :0.00189
## 1st Qu.:17.00 1st Qu.:173465 1st Qu.:0.4540 1st Qu.:0.46775
## Median :35.00 Median :214433 Median :0.5780 Median :0.68400
## Mean :33.72 Mean :228868 Mean :0.5647 Mean :0.64169
## 3rd Qu.:51.00 3rd Qu.:264231 3rd Qu.:0.6930 3rd Qu.:0.85800
## Max. :93.00 Max. :716079 Max. :0.9450 Max. :0.99900
## loudness speechiness acousticness instrumentalness
## Min. :-41.739 Min. :0.00000 Min. :0.00000 Min. :0.0000000
## 1st Qu.: -9.896 1st Qu.:0.03530 1st Qu.:0.02368 1st Qu.:0.0000000
## Median : -6.756 Median :0.04875 Median :0.17000 Median :0.0000174
## Mean : -8.093 Mean :0.08537 Mean :0.32469 Mean :0.1462549
## 3rd Qu.: -4.911 3rd Qu.:0.08123 3rd Qu.:0.61675 3rd Qu.:0.0269250
## Max. : -0.250 Max. :0.94800 Max. :0.99500 Max. :0.9990000
## liveness valence tempo
## Min. :0.0212 Min. :0.0000 Min. : 0.00
## 1st Qu.:0.0974 1st Qu.:0.2552 1st Qu.: 99.49
## Median :0.1345 Median :0.4585 Median :122.01
## Mean :0.2194 Mean :0.4743 Mean :121.26
## 3rd Qu.:0.2850 3rd Qu.:0.6870 3rd Qu.:139.68
## Max. :0.9910 Max. :0.9830 Max. :208.28
1. Deskripsi Dataset
Sumber Data
Dataset yang digunakan adalah Spotify Tracks Dataset yang diperoleh dari Kaggle. Dataset ini berisi data lagu dari platform Spotify yang mencakup berbagai genre musik. Setiap baris pada dataset merepresentasikan satu lagu, sedangkan setiap kolom berisi informasi mengenai karakteristik lagu tersebut.
Dataset ini memiliki berbagai variabel numerik, seperti popularity, duration_ms, danceability, energy, loudness, speechiness, acousticness, instrumentalness, liveness, valence, dan tempo. Variabel-variabel tersebut digunakan untuk menggambarkan karakteristik audio dari setiap lagu. Selain itu, dataset ini memiliki jumlah observasi yang besar dan banyak variabel numerik yang saling berhubungan sehingga sesuai digunakan untuk analisis multivariat, khususnya Feature Engineering, Feature Selection, dan Principal Component Analysis (PCA).
Sumber dataset: Spotify Tracks Dataset
Jumlah Observasi
## [1] 1000
Berdasarkan hasil pengolahan data, dataset yang digunakan terdiri atas 1000 observasi. Observasi tersebut dipilih secara acak dari dataset asli yang berjumlah 114.000 observasi.
Jumlah Variabel
## [1] 22
Berdasarkan hasil pengolahan data menggunakan fungsi
ncol(), diperoleh bahwa dataset yang digunakan memiliki 22
variabel, yang terdiri atas informasi identitas lagu dan berbagai
karakteristik audio.
Tujuan Analisis
Analisis ini bertujuan untuk mengidentifikasi karakteristik audio lagu pada dataset Spotify berdasarkan berbagai variabel numerik yang digunakan, yaitu popularity, duration_ms, danceability, energy, loudness, speechiness, acousticness, instrumentalness, liveness, valence, dan tempo. Selain itu, dilakukan feature engineering untuk menghasilkan fitur baru, feature selection untuk memilih variabel yang relevan, serta Principal Component Analysis (PCA) untuk mereduksi dimensi data dan memperoleh informasi utama yang terkandung dalam dataset.
2. Exploratory Data Analysis (EDA)
Statistik Deskriptif
## popularity duration_ms danceability energy
## Min. : 0.00 Min. : 39775 Min. :0.0000 Min. :0.00189
## 1st Qu.:17.00 1st Qu.:173465 1st Qu.:0.4540 1st Qu.:0.46775
## Median :35.00 Median :214433 Median :0.5780 Median :0.68400
## Mean :33.72 Mean :228868 Mean :0.5647 Mean :0.64169
## 3rd Qu.:51.00 3rd Qu.:264231 3rd Qu.:0.6930 3rd Qu.:0.85800
## Max. :93.00 Max. :716079 Max. :0.9450 Max. :0.99900
## loudness speechiness acousticness instrumentalness
## Min. :-41.739 Min. :0.00000 Min. :0.00000 Min. :0.0000000
## 1st Qu.: -9.896 1st Qu.:0.03530 1st Qu.:0.02368 1st Qu.:0.0000000
## Median : -6.756 Median :0.04875 Median :0.17000 Median :0.0000174
## Mean : -8.093 Mean :0.08537 Mean :0.32469 Mean :0.1462549
## 3rd Qu.: -4.911 3rd Qu.:0.08123 3rd Qu.:0.61675 3rd Qu.:0.0269250
## Max. : -0.250 Max. :0.94800 Max. :0.99500 Max. :0.9990000
## liveness valence tempo
## Min. :0.0212 Min. :0.0000 Min. : 0.00
## 1st Qu.:0.0974 1st Qu.:0.2552 1st Qu.: 99.49
## Median :0.1345 Median :0.4585 Median :122.01
## Mean :0.2194 Mean :0.4743 Mean :121.26
## 3rd Qu.:0.2850 3rd Qu.:0.6870 3rd Qu.:139.68
## Max. :0.9910 Max. :0.9830 Max. :208.28
Berdasarkan statistik deskriptif di atas, dapat diperoleh gambaran awal mengenai distribusi setiap variabel numerik. Variabel popularity memiliki rentang nilai yang cukup lebar (0–93), sehingga menunjukkan bahwa terdapat lagu yang sangat tidak populer hingga sangat populer.
Variabel duration_ms menunjukkan variasi durasi lagu dalam milidetik dengan rata-rata sekitar 228.868 ms atau sekitar 3,8 menit. Variabel loudness bernilai negatif karena diukur dalam satuan desibel (dB) relatif terhadap 0 dB (nilai semakin mendekati 0 berarti semakin keras).
Variabel instrumentalness dan speechiness cenderung memiliki nilai rendah pada sebagian besar observasi, yang menunjukkan bahwa sebagian besar lagu mengandung vokal dan bukan sepenuhnya instrumental. Selain itu, rata-rata nilai danceability dan energy yang cukup tinggi menunjukkan bahwa mayoritas lagu pada dataset memiliki karakter yang cukup enerjik dan mudah untuk diikuti iramanya.Visualisasi Distribusi Variabel
par(mfrow = c(3, 4))
for (var in colnames(spotify_num)) {
hist(spotify_num[[var]],
main = paste("Histogram:", var),
xlab = var,
col = "#1DB954",
border = "white")
}
par(mfrow = c(1, 1))
Berdasarkan visualisasi histogram di atas, beberapa variabel menunjukkan distribusi yang tidak simetris (skewed). Variabel instrumentalness dan speechiness cenderung memiliki distribusi right-skewed, karena sebagian besar lagu memiliki nilai yang sangat rendah pada kedua variabel tersebut.
Variabel popularity dan liveness juga cenderung right-skewed, yang menunjukkan bahwa sebagian besar lagu memiliki nilai rendah hingga sedang. Sebaliknya, variabel energy menunjukkan distribusi left-skewed, karena sebagian besar lagu memiliki nilai energi yang tinggi.
Variabel danceability terlihat lebih mendekati distribusi normal dibanding variabel lainnya, sementara tempo menunjukkan distribusi yang cenderung unimodal dengan puncak di sekitar 120–130 BPM dan sedikit condong ke kanan.Deteksi Outlier Visual (Boxplot)
spotify_long <- melt(spotify_num)
ggplot(spotify_long, aes(x = variable, y = value, fill = variable)) +
geom_boxplot(outlier.colour = "red", outlier.size = 1.5, alpha = 0.7) +
facet_wrap(~ variable, scales = "free", ncol = 4) +
labs(title = "Boxplot Variabel Numerik Spotify",
x = "", y = "Nilai") +
theme_minimal(base_size = 11) +
theme(legend.position = "none",
plot.title = element_text(face = "bold", hjust = 0.5))
Boxplot di atas memperlihatkan sebaran nilai serta keberadaan outlier (titik merah) pada setiap variabel. Terlihat bahwa variabel duration_ms, instrumentalness, speechiness, dan liveness memiliki cukup banyak outlier pada nilai yang tinggi. Hal ini konsisten dengan histogram sebelumnya yang menunjukkan bahwa variabel-variabel tersebut cenderung memiliki distribusi right-skewed.
Variabel loudness juga memiliki cukup banyak outlier pada nilai yang rendah, yang menunjukkan adanya beberapa lagu dengan tingkat volume yang jauh lebih kecil dibanding mayoritas data. Sementara itu, variabel tempo memiliki outlier pada kedua sisi distribusi, baik pada nilai yang sangat rendah maupun sangat tinggi. Keberadaan outlier ini perlu diperhatikan karena dapat memengaruhi hasil analisis atau pemodelan selanjutnya.Missing Value
## popularity duration_ms danceability energy
## 0 0 0 0
## loudness speechiness acousticness instrumentalness
## 0 0 0 0
## liveness valence tempo
## 0 0 0
## popularity duration_ms danceability energy
## 0 0 0 0
## loudness speechiness acousticness instrumentalness
## 0 0 0 0
## liveness valence tempo
## 0 0 0
Berdasarkan hasil pengecekan missing value menggunakan fungsi
is.na(), diperoleh bahwa seluruh variabel numerik tidak
memiliki nilai yang hilang (missing value = 0 untuk semua variabel). Hal
ini menunjukkan bahwa data sudah bersih dan tidak memerlukan proses
imputasi sebelum analisis lebih lanjut dilakukan.
Deteksi Outlier (Metode IQR)
# Fungsi hitung outlier dengan metode IQR
hitung_outlier <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR_val <- Q3 - Q1
lower <- Q1 - 1.5 * IQR_val
upper <- Q3 + 1.5 * IQR_val
sum(x < lower | x > upper, na.rm = TRUE)
}
outlier_count <- sapply(spotify_num, hitung_outlier)
outlier_df <- data.frame(
Variabel = names(outlier_count),
Jumlah_Outlier = outlier_count
)
outlier_df## Variabel Jumlah_Outlier
## popularity popularity 0
## duration_ms duration_ms 50
## danceability danceability 4
## energy energy 0
## loudness loudness 49
## speechiness speechiness 115
## acousticness acousticness 0
## instrumentalness instrumentalness 232
## liveness liveness 78
## valence valence 0
## tempo tempo 5
Deteksi outlier dilakukan menggunakan metode Interquartile Range (IQR), di mana sebuah observasi dianggap outlier apabila nilainya berada di luar batas bawah (Q1 − 1.5 × IQR) atau batas atas (Q3 + 1.5 × IQR).Berdasarkan hasil di atas, variabel yang memiliki jumlah outlier terbanyak adalah instrumentalness (232), speechiness (115), liveness (78), loudness (49), dan duration_ms (50). Keberadaan outlier pada variabel-variabel tersebut perlu dipertimbangkan dalam tahap feature selection dan pemodelan, meskipun dalam konteks data audio Spotify, nilai-nilai ekstrem tersebut bisa jadi merupakan karakteristik lagu tertentu yang memang berbeda dari umumnya (misalnya lagu podcast atau lagu instrumental murni).
Analisis Korelasi
cor_matrix <- cor(spotify_num, use = "complete.obs")
corrplot(cor_matrix,
method = "color",
type = "upper",
tl.cex = 0.85,
addCoef.col = "black",
number.cex = 0.65,
col = colorRampPalette(c("#2166AC", "white", "#D6604D"))(200),
title = "Matriks Korelasi Variabel Numerik Spotify",
mar = c(0, 0, 2, 0))
Matriks korelasi di atas menunjukkan hubungan linier antarvariabel numerik. Korelasi positif yang cukup kuat terlihat antara variabel energy dan loudness (r = 0.76), yang berarti lagu dengan energi tinggi cenderung memiliki volume lebih keras. Sebaliknya, variabel energy dan acousticness memiliki korelasi negatif yang kuat (r = −0.73), sehingga lagu yang lebih akustik umumnya memiliki tingkat energi yang lebih rendah.
Selain itu, terdapat korelasi negatif sedang antara loudness dan acousticness (r = −0.59), serta korelasi positif sedang antara danceability dan valence (r = 0.47). Hubungan antarvariabel ini dapat menjadi pertimbangan dalam tahap feature selection karena variabel dengan korelasi tinggi berpotensi membawa informasi yang mirip atau redundan.Identifikasi Multikolinearitas (VIF)
# Regresi dummy untuk menghitung VIF
# Menggunakan popularity sebagai variabel dependen
model_vif <- lm(popularity ~ ., data = spotify_num)
vif_vals <- vif(model_vif)
vif_df <- data.frame(
Variabel = names(vif_vals),
VIF = round(vif_vals, 3)
)
vif_df## Variabel VIF
## duration_ms duration_ms 1.066
## danceability danceability 1.482
## energy energy 4.146
## loudness loudness 3.146
## speechiness speechiness 1.115
## acousticness acousticness 2.377
## instrumentalness instrumentalness 1.429
## liveness liveness 1.139
## valence valence 1.595
## tempo tempo 1.085
# Visualisasi VIF
ggplot(vif_df, aes(x = reorder(Variabel, VIF), y = VIF, fill = VIF > 5)) +
geom_col(width = 0.6) +
geom_hline(yintercept = 5, linetype = "dashed", color = "red", linewidth = 0.8) +
geom_hline(yintercept = 10, linetype = "dashed", color = "darkred", linewidth = 0.8) +
coord_flip() +
scale_fill_manual(values = c("#1DB954", "#E74C3C"),
labels = c("VIF ≤ 5 (Aman)", "VIF > 5 (Perlu Perhatian)")) +
labs(title = "Variance Inflation Factor (VIF) — Deteksi Multikolinearitas",
x = "Variabel", y = "Nilai VIF",
fill = "Status",
caption = "Garis merah putus-putus: VIF = 5 (moderate) dan VIF = 10 (severe)") +
theme_minimal(base_size = 11) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))Variance Inflation Factor (VIF) digunakan untuk mendeteksi multikolinearitas, yaitu kondisi di mana dua atau lebih variabel prediktor saling berkorelasi tinggi sehingga dapat mengganggu stabilitas model regresi. Secara umum, nilai VIF > 5 menunjukkan adanya multikolinearitas moderat, sedangkan VIF > 10 menunjukkan multikolinearitas yang lebih serius.
Berdasarkan hasil di atas, seluruh variabel memiliki nilai VIF di bawah 5, sehingga tidak terindikasi adanya multikolinearitas yang kuat. Namun, variabel energy (4.146), loudness (3.146), dan acousticness (2.377) menunjukkan nilai VIF yang relatif lebih tinggi dibandingkan variabel lainnya, konsisten dengan temuan pada matriks korelasi. Hal ini sejalan dengan matriks korelasi sebelumnya yang menunjukkan adanya hubungan cukup kuat antarvariabel tersebut. Oleh karena itu, variabel-variabel tersebut tetap dapat dipertimbangkan pada tahap feature selection untuk mengurangi kemungkinan adanya informasi yang saling tumpang tindih.
3. Feature Engineering
Feature Engineering merupakan tahap dalam proses analisis data yang bertujuan untuk membentuk fitur-fitur baru dari variabel yang sudah tersedia agar dapat merepresentasikan informasi dalam data secara lebih informatif dan bermakna. Pada tahap ini, dilakukan transformasi serta kombinasi variabel-variabel yang ada untuk menghasilkan fitur tambahan yang diharapkan mampu meningkatkan kualitas analisis dan performa model.
Fitur Baru
# 3. FEATURE ENGINEERING
# Fitur 1: Mood Score
mood_score <- (spotify_num$valence + spotify_num$energy) / 2
# Fitur 2: Acoustic Energy Ratio
acoustic_energy_ratio <- spotify_num$acousticness / (spotify_num$energy + 0.001)
# Fitur 3: Dance Popularity Score
dance_popularity <- spotify_num$danceability * spotify_num$popularity
# Fitur 4: Energy Intensity
energy_intensity <- spotify_num$energy * abs(spotify_num$loudness)
# Masukkan ke dataset
spotify_num$mood_score <- mood_score
spotify_num$acoustic_energy_ratio <- acoustic_energy_ratio
spotify_num$dance_popularity <- dance_popularity
spotify_num$energy_intensity <- energy_intensity
# Mengecek hasil feature baru
head(spotify_num)## # A tibble: 6 × 15
## popularity duration_ms danceability energy loudness speechiness acousticness
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 59 244831 0.746 0.988 -4.57 0.0637 0.29
## 2 42 250601 0.628 0.79 -7.16 0.0655 0.27
## 3 44 170866 0.65 0.915 -5.76 0.0368 0.446
## 4 39 178285 0.593 0.937 -6.70 0.0566 0.000397
## 5 34 299613 0.546 0.628 -10.3 0.0441 0.625
## 6 4 168828 0.676 0.338 -7.96 0.0284 0.372
## # ℹ 8 more variables: instrumentalness <dbl>, liveness <dbl>, valence <dbl>,
## # tempo <dbl>, mood_score <dbl>, acoustic_energy_ratio <dbl>,
## # dance_popularity <dbl>, energy_intensity <dbl>
summary(spotify_num[, c("mood_score",
"acoustic_energy_ratio",
"dance_popularity",
"energy_intensity")])## mood_score acoustic_energy_ratio dance_popularity energy_intensity
## Min. :0.00095 Min. : 0.0000 Min. : 0.000 Min. : 0.04763
## 1st Qu.:0.41550 1st Qu.: 0.0298 1st Qu.: 7.081 1st Qu.: 3.13219
## Median :0.57550 Median : 0.2522 Median :17.188 Median : 4.01230
## Mean :0.55801 Mean : 1.9689 Mean :19.162 Mean : 4.21422
## 3rd Qu.:0.71662 3rd Qu.: 1.1382 3rd Qu.:29.009 3rd Qu.: 5.10010
## Max. :0.96100 Max. :339.7924 Max. :81.052 Max. :12.69496
Alasan Pembuatan Fitur dan Interpretasi Fitur
Fitur 1: Mood Score
Alasan Pembuatan Fitur
Fitur mood_score dibuat untuk menggambarkan suasana atau karakter emosional suatu lagu dengan menggabungkan variabel energy dan valence. Variabel energy menunjukkan tingkat intensitas dan aktivitas lagu, sedangkan valence menggambarkan tingkat kepositifan atau keceriaan lagu. Penggabungan kedua variabel ini diharapkan dapat memberikan representasi yang lebih sederhana mengenai suasana keseluruhan lagu.Interpretasi Fitur
Nilai mood_score yang tinggi menunjukkan lagu cenderung memiliki energi dan suasana yang positif atau ceria. Sebaliknya, nilai yang rendah menunjukkan lagu cenderung memiliki energi rendah dan suasana yang lebih tenang atau melankolis. Berdasarkan hasil ringkasan statistik, fitur ini memiliki nilai rata-rata sebesar 0,558 dengan rentang nilai antara 0,00095 hingga 0,961, yang menunjukkan adanya variasi karakter suasana antar lagu dalam dataset.
Fitur 2: Acoustic Energy Ratio
Alasan Pembuatan Fitur
Fitur acoustic_energy_ratio dibuat untuk melihat hubungan antara tingkat keakustikan lagu (acousticness) dan tingkat energinya (energy). Fitur ini dapat membantu membedakan lagu yang dominan akustik namun memiliki energi rendah maupun lagu yang lebih energik dengan unsur akustik yang kecil.
Interpretasi Fitur
Nilai acoustic_energy_ratio yang tinggi menunjukkan bahwa karakter akustik lagu lebih dominan dibandingkan tingkat energinya. Sebaliknya, nilai yang rendah menunjukkan lagu memiliki energi yang relatif lebih tinggi dibandingkan unsur akustiknya. Berdasarkan hasil yang diperoleh, fitur ini memiliki rata-rata sebesar 1,969 dengan nilai maksimum mencapai 339,792, yang menunjukkan adanya beberapa lagu dengan tingkat akustik yang sangat tinggi dan energi yang sangat rendah.
Fitur 3: Dance Popularity Score
Alasan Pembuatan Fitur
Fitur dance_popularity dibuat dengan menggabungkan variabel danceability dan popularity. Tujuannya adalah untuk mengidentifikasi lagu yang tidak hanya mudah digunakan untuk menari, tetapi juga memiliki tingkat popularitas yang tinggi. Fitur ini dapat memberikan informasi tambahan mengenai potensi daya tarik suatu lagu di kalangan pendengar.
Interpretasi Fitur
Nilai dance_popularity yang tinggi menunjukkan lagu memiliki tingkat kemudahan untuk menari yang tinggi serta populer di kalangan pengguna Spotify. Sebaliknya, nilai yang rendah menunjukkan lagu kurang populer, kurang danceable, atau keduanya. Hasil ringkasan statistik menunjukkan nilai rata-rata sebesar 19,162 dengan nilai maksimum sebesar 81,052, yang mengindikasikan adanya beberapa lagu yang sangat populer dan memiliki karakteristik yang mendukung aktivitas menari.
Fitur 4: Energy Intensity
Alasan Pembuatan Fitur
Fitur energy_intensity dibuat untuk menggambarkan intensitas keseluruhan lagu melalui kombinasi antara variabel energy dan loudness. Variabel energy merepresentasikan tingkat aktivitas lagu, sedangkan loudness menunjukkan tingkat kekuatan suara. Penggabungan kedua variabel tersebut diharapkan dapat memberikan gambaran yang lebih jelas mengenai tingkat intensitas audio pada setiap lagu.
Interpretasi Fitur
Nilai energy_intensity yang tinggi menunjukkan lagu memiliki tingkat energi dan kekuatan suara yang tinggi, sehingga cenderung terdengar lebih dinamis dan kuat. Sebaliknya, nilai yang rendah menunjukkan lagu dengan energi dan intensitas suara yang lebih rendah. Berdasarkan hasil ringkasan statistik, fitur ini memiliki rata-rata sebesar 4,214 dengan rentang nilai antara 0,048 hingga 12,695, yang menunjukkan adanya variasi intensitas lagu dalam dataset.
4. Feature Selection
Feature selection adalah proses memilih sebagian variabel yang paling relevan dari keseluruhan variabel yang tersedia, tanpa membentuk variabel baru. Tujuannya untuk mengurangi kompleksitas model, menghindari overfitting, serta mengurangi potensi multikolinearitas. Pada tahap ini digunakan dua metode feature selection, yaitu Filter Method berbasis korelasi dan Wrapper Method menggunakan Stepwise Regression.
Metode 1: Filter Method (Korelasi)
Filter Method merupakan pendekatan feature selection yang memilih variabel berdasarkan ukuran statistik, tanpa melibatkan proses pembentukan model. Pada metode ini, variabel dipilih berdasarkan nilai korelasi absolut terhadap variabel target, yaitu popularity. Variabel dengan korelasi absolut ≥ 0.1 dianggap memiliki hubungan yang cukup relevan dengan popularity sehingga dipertahankan dalam analisis, sedangkan variabel dengan korelasi yang sangat rendah tidak digunakan lebih lanjut.
library(ggplot2)
library(dplyr)
# Menghitung korelasi semua variabel terhadap popularity
cor_with_popularity <- cor(spotify_num, use = "complete.obs")[, "popularity"]
cor_df <- data.frame(
Variabel = names(cor_with_popularity),
Korelasi = round(cor_with_popularity, 4)
) %>%
filter(Variabel != "popularity") %>%
arrange(desc(abs(Korelasi)))
cor_df## Variabel Korelasi
## dance_popularity dance_popularity 0.9015
## speechiness speechiness -0.0903
## energy_intensity energy_intensity -0.0770
## valence valence -0.0683
## instrumentalness instrumentalness -0.0657
## liveness liveness -0.0612
## mood_score mood_score -0.0565
## acoustic_energy_ratio acoustic_energy_ratio 0.0541
## danceability danceability 0.0306
## energy energy -0.0215
## loudness loudness 0.0148
## duration_ms duration_ms 0.0069
## tempo tempo -0.0006
## acousticness acousticness -0.0003
# Visualisasi korelasi terhadap popularity
ggplot(cor_df, aes(x = reorder(Variabel, abs(Korelasi)),
y = Korelasi,
fill = Korelasi > 0)) +
geom_col(width = 0.6) +
geom_hline(yintercept = 0.1, linetype = "dashed", color = "darkgreen", linewidth = 0.8) +
geom_hline(yintercept = -0.1, linetype = "dashed", color = "darkgreen", linewidth = 0.8) +
coord_flip() +
scale_fill_manual(values = c("#E74C3C", "#1DB954"),
labels = c("Korelasi Negatif", "Korelasi Positif")) +
labs(title = "Korelasi Variabel terhadap Popularity (Filter Method)",
x = "Variabel", y = "Nilai Korelasi",
fill = "Arah Korelasi",
caption = "Garis hijau putus-putus: batas |korelasi| = 0.1") +
theme_minimal(base_size = 11) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))# Variabel terpilih (|korelasi| >= 0.1)
selected_filter <- cor_df %>%
filter(abs(Korelasi) >= 0.1) %>%
pull(Variabel)
cat("Variabel terpilih (Filter Method):\n")## Variabel terpilih (Filter Method):
## [1] "dance_popularity"
# Variabel tereliminasi
eliminated_filter <- cor_df %>%
filter(abs(Korelasi) < 0.1) %>%
pull(Variabel)
cat("\nVariabel tereliminasi (Filter Method):\n")##
## Variabel tereliminasi (Filter Method):
## [1] "speechiness" "energy_intensity" "valence"
## [4] "instrumentalness" "liveness" "mood_score"
## [7] "acoustic_energy_ratio" "danceability" "energy"
## [10] "loudness" "duration_ms" "tempo"
## [13] "acousticness"
Berdasarkan hasil Filter Method, variabel yang terpilih adalah variabel dengan nilai korelasi absolut terhadap popularity lebih dari atau sama dengan 0.1. Variabel dance_popularity memiliki korelasi tertinggi terhadap popularity, yang wajar karena variabel ini memang dibentuk dari kombinasi danceability dan popularity.
Seluruh variabel selain dance_popularity memiliki nilai korelasi absolut di bawah 0,1, sehingga dieliminasi karena hubungannya terhadap popularity dianggap kurang signifikan.Metode 2: Wrapper Method (Stepwise Regression)
Wrapper Method merupakan pendekatan feature selection yang menggunakan performa model untuk menentukan variabel terbaik. Pada metode ini digunakan Stepwise Regression dengan tiga pendekatan: Forward Selection, Backward Elimination, dan Bidirectional. Evaluasi pemilihan variabel dilakukan berdasarkan kriteria AIC (Akaike Information Criterion), di mana model dengan nilai AIC lebih kecil dianggap lebih baik.
# Dataset dengan semua variabel (termasuk fitur baru dari feature engineering)
spotify_full <- spotify_num
# Model lengkap dan model null
full_model <- lm(popularity ~ ., data = spotify_full)
null_model <- lm(popularity ~ 1, data = spotify_full)
# Forward Selection
forward_model <- step(null_model,
scope = list(lower = null_model, upper = full_model),
direction = "forward",
trace = 0)
# Backward Elimination
backward_model <- step(full_model,
direction = "backward",
trace = 0)
# Stepwise Bidirectional
stepwise_model <- step(null_model,
scope = list(lower = null_model, upper = full_model),
direction = "both",
trace = 0)
# variabel terpilih tiap metode
cat("Forward Selection:\n"); print(formula(forward_model))## Forward Selection:
## popularity ~ dance_popularity + danceability + acoustic_energy_ratio +
## duration_ms + instrumentalness + speechiness + acousticness
##
## Backward Elimination:
## popularity ~ duration_ms + danceability + speechiness + acousticness +
## instrumentalness + acoustic_energy_ratio + dance_popularity
##
## Stepwise Bidirectional:
## popularity ~ dance_popularity + danceability + acoustic_energy_ratio +
## duration_ms + instrumentalness + speechiness + acousticness
# Perbandingan AIC
aic_comparison <- AIC(forward_model, backward_model, stepwise_model)
rownames(aic_comparison) <- c("Forward Selection", "Backward Elimination", "Stepwise Bidirectional")
aic_comparison## df AIC
## Forward Selection 9 6499.314
## Backward Elimination 9 6499.314
## Stepwise Bidirectional 9 6499.314
##
## Call:
## lm(formula = popularity ~ dance_popularity + danceability + acoustic_energy_ratio +
## duration_ms + instrumentalness + speechiness + acousticness,
## data = spotify_full)
##
## Residuals:
## Min 1Q Median 3Q Max
## -23.9512 -2.4046 -0.0698 2.9526 31.4630
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.961e+01 9.927e-01 29.830 < 2e-16 ***
## dance_popularity 1.560e+00 1.406e-02 111.005 < 2e-16 ***
## danceability -4.679e+01 1.297e+00 -36.069 < 2e-16 ***
## acoustic_energy_ratio 1.006e-01 1.612e-02 6.240 6.46e-10 ***
## duration_ms 5.600e-06 2.302e-06 2.432 0.0152 *
## instrumentalness -1.496e+00 6.800e-01 -2.200 0.0280 *
## speechiness -3.375e+00 1.758e+00 -1.920 0.0551 .
## acousticness -1.064e+00 6.225e-01 -1.710 0.0876 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 6.207 on 992 degrees of freedom
## Multiple R-squared: 0.9269, Adjusted R-squared: 0.9264
## F-statistic: 1797 on 7 and 992 DF, p-value: < 2.2e-16
# Visualisasi koefisien model stepwise terpilih
coef_df <- as.data.frame(summary(stepwise_model)$coefficients)
coef_df$Variabel <- rownames(coef_df)
coef_df <- coef_df %>%
filter(Variabel != "(Intercept)") %>%
rename(Estimate = Estimate, p_value = `Pr(>|t|)`) %>%
mutate(Signifikan = ifelse(p_value < 0.05, "Signifikan (p < 0.05)", "Tidak Signifikan"))
ggplot(coef_df, aes(x = reorder(Variabel, abs(Estimate)),
y = Estimate,
fill = Signifikan)) +
geom_col(width = 0.6) +
coord_flip() +
scale_fill_manual(values = c("#1DB954", "#B0B0B0")) +
labs(title = "Koefisien Variabel Terpilih — Stepwise Regression",
x = "Variabel", y = "Koefisien",
fill = "Status") +
theme_minimal(base_size = 11) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Berdasarkan hasil Stepwise Regression dengan pendekatan Forward Selection, Backward Elimination, dan Bidirectional, diperoleh model akhir dengan variabel-variabel yang dipilih berdasarkan kriteria AIC dalam menjelaskan variabel popularity. Ketiga metode menghasilkan variabel terpilih yang relatif sama, yaitu dance_popularity, danceability, acoustic_energy_ratio, duration_ms, instrumentalness, speechiness, dan acousticness.
Perbandingan nilai AIC menunjukkan bahwa ketiga pendekatan menghasilkan nilai AIC yang sama, yaitu 6499,314. Hal ini menunjukkan bahwa ketiga metode memiliki performa model yang setara dalam proses pemilihan variabel.
Berdasarkan hasil model stepwise, variabel dance_popularity memiliki pengaruh positif paling besar terhadap popularity. Sementara itu, variabel instrumentalness, speechiness, dan acousticness memiliki koefisien negatif terhadap popularity. Meskipun speechiness dan acousticness memiliki nilai p yang relatif lebih besar dibanding variabel lainnya, kedua variabel tersebut tetap dipertahankan dalam model karena masih memberikan kontribusi terhadap performa model berdasarkan kriteria AIC.Perbandingan dan Kesimpulan Feature Selection
# Variabel terpilih dari kedua metode
vars_forward <- all.vars(formula(forward_model))[-1]
vars_backward <- all.vars(formula(backward_model))[-1]
vars_stepwise <- all.vars(formula(stepwise_model))[-1]
# Variabel terpilih (Filter Method)
print(selected_filter)## [1] "dance_popularity"
## [1] "dance_popularity" "danceability" "acoustic_energy_ratio"
## [4] "duration_ms" "instrumentalness" "speechiness"
## [7] "acousticness"
## [1] "duration_ms" "danceability" "speechiness"
## [4] "acousticness" "instrumentalness" "acoustic_energy_ratio"
## [7] "dance_popularity"
## [1] "dance_popularity" "danceability" "acoustic_energy_ratio"
## [4] "duration_ms" "instrumentalness" "speechiness"
## [7] "acousticness"
# Variabel yang konsisten terpilih di semua metode wrapper
vars_konsisten <- Reduce(intersect, list(vars_forward, vars_backward, vars_stepwise))
cat("\nVariabel konsisten terpilih di semua metode Stepwise:\n")##
## Variabel konsisten terpilih di semua metode Stepwise:
## [1] "dance_popularity" "danceability" "acoustic_energy_ratio"
## [4] "duration_ms" "instrumentalness" "speechiness"
## [7] "acousticness"
# Dataset final untuk PCA (variabel dari filter + stepwise yang konsisten)
vars_final <- union(selected_filter, vars_konsisten)
# Hanya ambil variabel numerik asli (tanpa fitur baru jika ingin PCA murni)
vars_final_numerik <- vars_final[vars_final %in% c("popularity","duration_ms","danceability",
"energy","loudness","speechiness",
"acousticness","instrumentalness",
"liveness","valence","tempo",
"mood_score","acoustic_energy_ratio",
"dance_popularity","energy_intensity")]
cat("\nVariabel final untuk tahap selanjutnya (PCA):\n")##
## Variabel final untuk tahap selanjutnya (PCA):
## [1] "dance_popularity" "danceability" "acoustic_energy_ratio"
## [4] "duration_ms" "instrumentalness" "speechiness"
## [7] "acousticness"
Berdasarkan hasil kedua metode feature selection yang digunakan, dapat disimpulkan bahwa terdapat variabel-variabel yang secara konsisten terpilih, baik melalui Filter Method maupun Wrapper Method (Stepwise Regression). Variabel yang terpilih pada Filter Method menunjukkan adanya hubungan statistik yang relevan dengan popularity, sedangkan variabel yang terpilih pada Stepwise Regression merupakan variabel yang secara signifikan berkontribusi dalam model prediktif.
Variabel yang tereliminasi pada kedua metode dianggap tidak memberikan informasi yang cukup relevan terhadap popularity, sehingga tidak diikutkan pada tahap Principal Component Analysis (PCA).5. Feature Extraction
Ekstraksi fitur adalah teknik yang mengurangi dimensi atau kompleksitas data untuk meningkatkan kinerja dan efisiensi algoritma machine learning (ML). Proses ini memfasilitasi tugas ML dan meningkatkan analisis data dengan menyederhanakan kumpulan data untuk menyertakan hanya variabel atau atribut yang signifikan.
Analisis PCA
Principal Component Analysis (PCA) adalah teknik reduksi dimensi (feature extraction) yang menyederhanakan banyak variabel menjadi beberapa komponen utama.
Tujuan PCA antara lain:
• Mengurangi jumlah variabel
• Mengurangi multikolinearitas
• Mempermudah visualisasi
• Mempertahankan informasi utama data# 1. Load Library
library(ggplot2)
library(dplyr)
library(factoextra)
library(ggcorrplot)
library(tidyr)
# 2. Data Preprocessing
spotify_num <- spotify[, c("popularity", "duration_ms", "danceability",
"energy", "loudness", "speechiness",
"acousticness", "instrumentalness",
"liveness", "valence", "tempo")]
# Tambahkan kembali fitur hasil feature engineering
spotify_num$mood_score <- (spotify_num$valence + spotify_num$energy) / 2
spotify_num$acoustic_energy_ratio <- spotify_num$acousticness / (spotify_num$energy + 0.001)
spotify_num$dance_popularity <- spotify_num$danceability * spotify_num$popularity
spotify_num$energy_intensity <- spotify_num$energy * abs(spotify_num$loudness)
vars_final_numerik <- c("dance_popularity", "danceability", "acoustic_energy_ratio",
"duration_ms", "instrumentalness", "speechiness", "acousticness")
spotify_selected <- spotify_num[, vars_final_numerik]
pca_data <- spotify_selected %>%
select(-any_of("popularity"))
dim(pca_data)## [1] 1000 7
## dance_popularity danceability acoustic_energy_ratio
## 0 0 0
## duration_ms instrumentalness speechiness
## 0 0 0
## acousticness
## 0
# 3. PCA
pca_result <- prcomp(pca_data, center = TRUE, scale. = TRUE)
# Ringkasan PCA
cat("\n--- Ringkasan PCA ---\n")##
## --- Ringkasan PCA ---
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 1.3166 1.0526 1.0259 1.0069 0.9095 0.8398 0.74823
## Proportion of Variance 0.2476 0.1583 0.1504 0.1448 0.1182 0.1007 0.07998
## Cumulative Proportion 0.2476 0.4059 0.5563 0.7011 0.8193 0.9200 1.00000
Analisis Principal Component Analysis (PCA) dilakukan terhadap 7 variabel dari 1000 observasi hasil feature selection. Sebelum PCA dijalankan, seluruh variabel telah distandarisasi (scaling) untuk memastikan tidak ada variabel yang mendominasi. Hasil pengecekan missing value menunjukkan bahwa tidak terdapat nilai yang hilang pada seluruh variabel, sehingga PCA dapat dijalankan langsung. Secara keseluruhan, hasil PCA memperoleh 7 komponen utama yang menjelaskan 100% variansi data.
1. Variansi Tiap Komponen
Variansi tiap komponen dalam PCA ditunjukkan oleh nilai eigenvalue dan proporsi variansi masing-masing PC.
# Eigenvalue & proporsi variansi
eigenvalues <- pca_result$sdev^2
prop_var <- eigenvalues / sum(eigenvalues)
cumul_var <- cumsum(prop_var)
variance_df <- data.frame(
PC = paste0("PC", seq_along(eigenvalues)),
Eigenvalue = round(eigenvalues, 4),
Proporsi = round(prop_var * 100, 2),
Kumulatif = round(cumul_var * 100, 2)
)
print(variance_df)## PC Eigenvalue Proporsi Kumulatif
## 1 PC1 1.7333 24.76 24.76
## 2 PC2 1.1081 15.83 40.59
## 3 PC3 1.0525 15.04 55.63
## 4 PC4 1.0138 14.48 70.11
## 5 PC5 0.8272 11.82 81.93
## 6 PC6 0.7052 10.07 92.00
## 7 PC7 0.5598 8.00 100.00
Berdasarkan kriteria Kaiser, komponen yang memiliki nilai eigenvalue ≥ 1, dipertahankan. Hasil tersebut menunjukkan terdapat 4 komponen utama yang lebih besar dari 1, yaitu PC1 hingga PC4 dengan total kumulatif sebesar 70.11%. Hal ini menunjukkan bahwa keempat komponen tersebut mampu merepresentasikan sebagian besar informasi dari 7 variabel asli, sehingga dimensi data berhasi direduksi atau berkurang sebesar 42.86%.
Berdasarkan proporsi variansinya, PC1 merupakan komponen paling informatif dengan nilai proporsi 24.76%, kemudian nilai dibawahnya diikuti oleh PC2 - PC4. Proporsi variansi ini mengindikasikan bahwa setiap komponen menangkap dimensi informasi yang berbeda-beda, sehingga tidak tidak ada satu variabel yang mendominasi dalam data ini. Sementara itu, PC5 hingga PC7 memiliki eigenvalue dibawah 1 sehingga dianggap belum cukup informatif dan komponen ini tidak diikut sertakan untuk analisis selanjutnya.
Plot 1: Scree Plot
fviz_eig(pca_result, addlabels = TRUE, ylim = c(0, 100),
barfill = "#1DB954", barcolor = "#1DB954") +
labs(title = "Scree Plot — Variansi Tiap PC")Hasil Scree-plot tersebut merepresentasikan nilai proporsi variansi yang dihasilkan. Terlihat bahwa dimensi 1 (PC1) merupakan dimensi dengan persentase tertinggi sebesar 24.8%. Sementara itu, dimensi 7 (PC7) memiliki persentase terendah yang berarti komponen tersebut hanya menjelaskan sebagian kecil dari total variansi data dan dianggap tidak cukup informatif. Garis pada scree plot tersebut terlihat mulai melandai setelah PC4, ini menegaskan bahwa penambahan komponen setelah PC4 tidak memberikan kontribusi variansi yang signifikan.
2. Loading Factor
Loading factor menunjukkan besarnya kontribusi setiap variabel terhadap masing-masing PC. Semakin dekat dengan nilai ±1, maka kontribusi dianggap kuat, sedangkan semakin mendekati 0, kontribusi dianggap lemah.
# Loading Factor
loadings_df <- as.data.frame(round(pca_result$rotation, 4))
loadings_df$Variabel <- rownames(loadings_df)
print(loadings_df)## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## dance_popularity -0.4381 0.2793 0.1892 0.5652 -0.0862 -0.2267 0.5621
## danceability -0.5744 0.0706 0.2241 0.1839 -0.1832 0.0917 -0.7342
## acoustic_energy_ratio 0.3955 0.2782 0.4243 0.3453 0.1718 0.6608 -0.0270
## duration_ms 0.1563 -0.6490 0.3095 0.3985 0.4084 -0.3389 -0.1347
## instrumentalness 0.3831 -0.2085 -0.1262 0.3702 -0.8060 -0.0473 -0.0703
## speechiness -0.0287 -0.1473 0.7702 -0.4813 -0.3303 -0.0699 0.1966
## acousticness 0.3869 0.5944 0.1704 -0.0033 0.0632 -0.6176 -0.2873
## Variabel
## dance_popularity dance_popularity
## danceability danceability
## acoustic_energy_ratio acoustic_energy_ratio
## duration_ms duration_ms
## instrumentalness instrumentalness
## speechiness speechiness
## acousticness acousticness
A. PC1 (Dimensi Danceability vs Acoustic): Berdasarkan hasil PC1 tersebut, danceability (-0.5744) dan dance_popularity (0.4381) memiliki nilai loading negatif yang kuat, sementara itu acoustic_energy_ratio (0.3955), acousticness (0.3869), dan instrumentalness (0.3831) memiliki loading positif yang kuat. Hal ini menunjukkan bahwa PC1 dengan skor rendah merepresentasikan lagu yang bersifat danceable dan populer, sementara di sisi lain lagu dengan skor PC1 tinggi cenderung akustik dan intrumental.
B. PC2 (Dimensi Duration vs Acoustic): PC2 merepresentasikan antara duration_ms (-0.6490) dan acousticness (0.5944), keduanya hampir sama besar tapi berlawanan tanda, sehingga apabila salah satu nilai naik, yang lain cenderung turun. PC2 dengan skor rendah merepresentasikan lagu yang berdurasi panjang dengan karakteristik akustik yang lemah. Sebaliknya, skor PC2 tinggi cenderung memiliki karakteristik akustik yang kuat namun berdurasi pendek.
C. PC3 (Dimensi Speechiness): PC3 didominasi oleh speechiness (0.7702), dengan loading positif yang kuat. Komponen ini lebih dominan pada karakteristik lagu yang mengandung banyak elemen vokal atau lirik. Semakin tinggi skor PC3, maka semakin banyak elemen vokal pada lagu tersebut.
D. PC4 (Dimensi Dance Popularity vs Speechiness): PC4 merepresentasikan antara dance_popularity (0.5652) dan speechiness (-0.4813). Lagu dengan skor PC4 yang tinggi cenderung danceable dan populer namun elemen vokalnya sedikit. Sebaliknya, lagu dengan skor PC4 yang rendah memiliki elemen vokal yang tinggi namun tidak danceable dan populer.
E. PC5 (Dimensi Instrumentalness): PC5 didominasi oleh instrumentalness (-0.8060) dengan loading negatif yang kuat. Komponen ini hampir sepenuhnya menangkap karakteristik instrumental lagu. PC5 cenderung merupakan lagu instrumental murni tanpa vokal. Sementara itu, Variabel lainnya memiliki loading yang mendekati 0 sehingga kontribusinya dapat diabaikan.
F. PC6 (Dimensi Acoustic Energy Ratio vs Acousticness): PC6 didominasi oleh acoustic_energy_ratio (0.6608) dan acousticness (-0.6176). Kedua variabel ini berkaitan dengan akustik namun berlawanan arah. PC6 menunjukkan adanya perbedaan antara rasio energi akustik terhadap tingkat akustik murni suatu lagu.
G. PC7 (Dimensi Danceability): PC7 didominasi oleh danceability (-0.7342) dengan loading negatif kuat. Lagu dengan skor PC7 rendah cenderung memiliki tingkat danceability yang tinggi.
Plot 2: Heatmap
loadings_df %>%
pivot_longer(-Variabel, names_to = "PC", values_to = "Loading") %>%
ggplot(aes(x = PC, y = Variabel, fill = Loading)) +
geom_tile(color = "white") +
geom_text(aes(label = round(Loading, 2)), size = 3.5) +
scale_fill_gradient2(low = "#E74C3C", mid = "white", high = "#1DB954", midpoint = 0) +
labs(title = "Heatmap Loading Factor") +
theme_minimal()Heatmap loading factor menampilkan kontribusi setiap variabel terhadap masing-masing komponen utama (PCA). Warna hijau menunjukkan loading positif, warna merah menunjukkan loading negatif, dan warna putih menunjukkan loading mendekati 0 atau tidak berkontribusi secara signifikan terhadap komponen. Semakin pekat warnanya, maka semakin besar kontribusi variabel tersebut.
Secara keseluruhan, heatmap ini menunjukkan dimensi informasi yang berbeda-beda setiap komponennya, dengan tidak ada satu variabel yang mendominasi komponen secara bersamaan. Hal ini mengindikasikan bahwa variabel dalam dataset memiliki karakteristik yang beragam dan saling melengkapi.
3. PCA Keseluruhan
# Jumlah PC optimal (Kaiser: eigenvalue >= 1)
n_pc <- sum(pca_result$sdev^2 >= 1)
cat("Jumlah PC terpilih (Kaiser):", n_pc, "\n")## Jumlah PC terpilih (Kaiser): 4
## PC1 PC2 PC3 PC4
## 1 -1.5659467 0.444010452 0.44299401 1.0629889
## 2 -0.6756565 -0.008328797 0.09393802 0.2974240
## 3 -0.7424257 0.990516007 -0.23465933 0.1621183
## 4 -0.1108059 -0.454683810 -0.72378936 0.6156896
## 5 0.3612012 0.113413439 0.11599623 0.2612173
## 6 -0.1486593 0.431940475 -0.60620251 -0.7322983
Berdasarkan kriteria Kaiser, diperoleh 4 komponen utama yang dipertahankan (PC1 - PC4) dengan total variansi kumulatif sebesar 70.11%.
Skor PC merupakan hasil transformasi data asli ke dalam ruang komponen utama (PC), di mana setiap baris merepresentasikan posisi masing-masing lagu pada keempat komponen.
Observasi 1: Pada lagu pertama, skor tertinggi adalah pada PC4 (1.0630), yang menunjukkan lagu ini cenderung populer dengan elemen vokal yang sedikit.
Observasi 2: Pada lagu kedua, skor tertinggi adalah pada PC1 (-0.6757), yang menunjukkan lagu ini cenderung danceable dan populer.
Observasi 3: Pada lagu ketiga, skor tertinggi adalah pada PC2 (0.9905), yang menunjukkan lagu ini cenderung memiliki karakteristik akustik yang kuat dengan durasi yang pendek.
Observasi 4: Pada lagu keempat, skor tertinggi adalah pada PC3 (-0.7238), yang menunjukkan lagu ini memiliki elemen vokal yang sedikit.
Observasi 5: Pada lagu kelima, skor tertinggi adalah pada PC1 (0.3612), yang menunjukkan lagu ini cenderung bersifat akustik dan instrumental.
Observasi 6: Pada lagu keenam, skor tertinggi adalah pada PC4 (-0.7323), yang menunjukkan lagu ini cenderung memiliki elemen vokal yang banyak namun kurang populer.
Plot 3: Variable Plot
# Variable Plot
fviz_pca_var(pca_result, repel = TRUE, col.var = "contrib",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")) +
labs(title = "Variable Plot PCA")Variable plot menampilkan posisi setiap variabel dalam ruang dua dimensi yang dibentuk oleh PC1 (Dim1, 24.8%) dan PC2 (Dim2, 15.8%). Warna panah mencerminkan tingkat kontribusi variabel terhadap kedua komponen, di mana warna merah - oranye menunjukkan kontribusi tinggi dan warna biru-hijau menunjukkan kontribusi rendah.
Kuadran 1: Variabel acousticness memiliki panah terpanjang yang mengarah ke kuadran kanan atas, menunjukkan kontribusi positif yang kuat pada PC2 sekaligus kontribusi positif pada PC2. Acousticness dan acoustic_energy_ratio juga memiliki arah panah yang relatif berdekatan, mengindikasikan korelasi positif antara keduanya.
Kuadran 2: Variabel danceability dan dance_popularity memiliki panah yang mengarah ke kiri, menunjukkan kontribusi negatif pada PC1. Variabel dance_popularity dan danceability memiliki arah panah yang berdekatan, menunjukkan bahwa kedua variabel tersebut berkorelasi positif satu sama lain.
Kuadran 3: Speechiness memiliki panah yang sangat pendek dan hampir sejajar sumbu horizontal, mengindikasikan kontribusinya pada PC1 dan PC2 sangat kecil.
Kuadran 4: Variabel duration_ms memiliki panah yang mengarah ke kuadran kanan bawah, mencerminkan kontribusi positif pada PC1 namun negatif pada PC2.
Kesimpulan
Analisis eksplorasi dan reduksi data pada dataset Spotify telah dilakukan melalui tiga tahapan utama, yaitu Feature Engineering, Feature Selection, dan Feature Extraction menggunakan Principal Component Analysis (PCA). Berikut adalah kesimpulan dari keseluruhan analisis yang telah dilakukan.
Feature Engineering
Pada tahap Feature Engineering, berhasil dibentuk empat fitur baru dari variabel-variabel yang telah ada, yaitu mood_score, acoustic_energy_ratio, dance_popularity, dan energy_intensity. Keempat fitur tersebut dibuat untuk menangkap informasi yang lebih kaya mengenai karakteristik audio lagu, seperti suasana emosional, rasio akustik terhadap energi, potensi daya tarik lagu, serta intensitas audio secara keseluruhan.
Feature Selection
Pada tahap Feature Selection, digunakan dua metode yaitu Filter Method berbasis korelasi dan Wrapper Method menggunakan Stepwise Regression. Filter Method menghasilkan satu variabel terpilih, yaitu dance_popularity, karena memiliki korelasi absolut tertinggi terhadap popularity. Sementara itu, Wrapper Method dengan ketiga pendekatannya, yaitu Forward Selection, Backward Elimination, dan Stepwise Bidirectional, secara konsisten menghasilkan tujuh variabel terpilih yang sama dengan nilai AIC sebesar 6499,314. Variabel final yang digunakan untuk tahap PCA adalah dance_popularity, danceability, acoustic_energy_ratio, duration_ms, instrumentalness, speechiness, dan acousticness.
Berdasarkan hasil feature selection, variabel yang paling penting dalam menjelaskan popularity lagu adalah dance_popularity, yang memiliki korelasi absolut tertinggi terhadap popularity sebesar 0,9015. Hal ini menunjukkan bahwa lagu yang memiliki karakteristik danceable sekaligus populer cenderung mendominasi dataset. Selain itu, variabel danceability, acoustic_energy_ratio, duration_ms, instrumentalness, speechiness, dan acousticness juga terpilih secara konsisten oleh Wrapper Method sebagai variabel yang berkontribusi signifikan dalam model prediktif.
Feature Extraction
Pada tahap Feature Extraction menggunakan PCA, analisis dilakukan terhadap 7 variabel hasil feature selection dengan 1.000 observasi. Berdasarkan kriteria Kaiser, diperoleh 4 komponen utama yang dipertahankan, yaitu PC1 hingga PC4, dengan total variansi kumulatif sebesar 70,11%.
Keempat komponen tersebut masing-masing merepresentasikan dimensi yang berbeda:
PC1 menangkap kontras antara karakteristik Danceability dengan Acoustic, di mana lagu dengan skor rendah cenderung danceable dan populer, sementara lagu dengan skor tinggi cenderung akustik dan instrumental.
PC2 menangkap kontras antara Duration dengan Acoustic, yang menangkap kontras antara lagu berdurasi panjang dengan lagu berkarakter akustik kuat.
PC3 menangkap Speechiness, merepresentasikan dimensi speechiness, yang menangkap seberapa banyak kandungan vokal atau lirik dalam suatu lagu.
PC4 menangkap kontras antara Dance Popularity dengan Speechiness, merepresentasikan dimensi popularitas vs kandungan vokal, di mana lagu populer cenderung memiliki kandungan vokal yang rendah.
Beberapa insight penting yang diperoleh dari analisis ini adalah sebagai berikut:
Popularitas lagu di Spotify sangat erat kaitannya dengan karakteristik danceability, yang tercermin dari tingginya korelasi dance_popularity terhadap popularity.
Terdapat kontras yang jelas antara lagu berkarakter danceable dengan lagu berkarakter akustik, di mana keduanya membentuk dimensi utama dalam data.
Durasi lagu dan tingkat akustik merupakan dua dimensi yang saling berlawanan, artinya lagu akustik pada dataset ini cenderung berdurasi lebih pendek dibandingkan lagu non-akustik.
Elemen vokal (speechiness) membentuk dimensi tersendiri yang independen dari variabel lainnya, menunjukkan bahwa karakteristik ini unik dan tidak tumpang tindih dengan dimensi lain dalam data.