Este conjunto de datos contiene 114.000 canciones de Spotify que abarcan 114 géneros musicales únicos, recopiladas a través de la API Web de Spotify. Cada pista incluye un conjunto de características de audio calculadas por el motor interno de análisis de audio de Spotify.

##Fuente: https://www.kaggle.com/datasets/saichaitanyareddyai/spotify-tracks-dataset-audio-features ##Archivo: spotify-tracks-dataset-detailed.csv (19.43 MB)

##Importación de la base de datos

Base_spotify <- read_csv(
  "C:/Users/Juan_Cruz/Desktop/Carrera de especialización en estadística para las ciencias de salud/Multivariado/spotify-tracks-dataset-detailed.csv"
) %>%
  rename(
    id_cancion = track_id,
    artistas = artists,
    nombre_album = album_name,
    nombre_cancion = track_name,
    genero_musical = track_genre,
    popularidad = popularity,
    duracion_ms = duration_ms,
    explicito = explicit,
    bailabilidad = danceability,
    energia = energy,
    tonalidad = key,
    sonoridad = loudness,
    modo = mode,
    presencia_habla = speechiness,
    acusticidad = acousticness,
    instrumentalidad = instrumentalness,
    vivacidad = liveness,
    valencia = valence,
    tempo = tempo,
    compas = time_signature
  )
## Rows: 114000 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (5): track_id, artists, album_name, track_name, track_genre
## dbl (14): popularity, duration_ms, danceability, energy, key, loudness, mode...
## lgl  (1): explicit
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
glimpse(Base_spotify)
## Rows: 114,000
## Columns: 20
## $ id_cancion       <chr> "5SuOikwiRyPMVoIQDJUgSV", "4qPNDBW1i3p13qLCt0Ki3A", "…
## $ artistas         <chr> "Gen Hoshino", "Ben Woodward", "Ingrid Michaelson;ZAY…
## $ nombre_album     <chr> "Comedy", "Ghost (Acoustic)", "To Begin Again", "Craz…
## $ nombre_cancion   <chr> "Comedy", "Ghost - Acoustic", "To Begin Again", "Can'…
## $ popularidad      <dbl> 73, 55, 57, 71, 82, 58, 74, 80, 74, 56, 74, 69, 52, 6…
## $ duracion_ms      <dbl> 230666, 149610, 210826, 201933, 198853, 214240, 22940…
## $ explicito        <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS…
## $ bailabilidad     <dbl> 0.676, 0.420, 0.438, 0.266, 0.618, 0.688, 0.407, 0.70…
## $ energia          <dbl> 0.4610, 0.1660, 0.3590, 0.0596, 0.4430, 0.4810, 0.147…
## $ tonalidad        <dbl> 1, 1, 0, 0, 2, 6, 2, 11, 0, 1, 8, 4, 7, 3, 2, 4, 2, 1…
## $ sonoridad        <dbl> -6.746, -17.235, -9.734, -18.515, -9.681, -8.807, -8.…
## $ modo             <dbl> 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0,…
## $ presencia_habla  <dbl> 0.1430, 0.0763, 0.0557, 0.0363, 0.0526, 0.1050, 0.035…
## $ acusticidad      <dbl> 0.0322, 0.9240, 0.2100, 0.9050, 0.4690, 0.2890, 0.857…
## $ instrumentalidad <dbl> 1.01e-06, 5.56e-06, 0.00e+00, 7.07e-05, 0.00e+00, 0.0…
## $ vivacidad        <dbl> 0.3580, 0.1010, 0.1170, 0.1320, 0.0829, 0.1890, 0.091…
## $ valencia         <dbl> 0.7150, 0.2670, 0.1200, 0.1430, 0.1670, 0.6660, 0.076…
## $ tempo            <dbl> 87.917, 77.489, 76.332, 181.740, 119.949, 98.017, 141…
## $ compas           <dbl> 4, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4,…
## $ genero_musical   <chr> "acoustic", "acoustic", "acoustic", "acoustic", "acou…
Base_spotify <- Base_spotify %>%
  mutate(
    popularidad = as.numeric(popularidad),
    duracion_ms = as.numeric(duracion_ms),
    genero_musical = as.factor(genero_musical),
    explicito = factor(
      explicito,
      levels = c(FALSE, TRUE),
      labels = c("0", "1")
    ),
    tonalidad = as.factor(tonalidad),
    modo = as.factor(modo),
    compas = as.factor(compas)
  )

generos_seleccionados <- c(
   "heavy-metal",
   "tango", "reggaeton"
)

Base_spotify_reducida <- Base_spotify %>%
  filter(genero_musical %in% generos_seleccionados)

Base_spotify_reducida %>%
  count(genero_musical, sort = TRUE)
## # A tibble: 3 × 2
##   genero_musical     n
##   <fct>          <int>
## 1 heavy-metal     1000
## 2 reggaeton       1000
## 3 tango           1000

La base de datos contiene 104977 observaciones con 22 variables sin ningún dato faltante


1. Diccionario de variables (en español)

Diccionario de variables
Base de datos Spotify
Variable Tipo Descripción
Variables descriptivas
id_cancion carácter Identificador único de la canción en Spotify.
artistas carácter Artista o artistas que interpretan la canción.
nombre_album carácter Nombre del álbum en el que se incluye la canción.
nombre_cancion carácter Nombre de la canción.
genero_musical factor Género musical asignado a la canción.
popularidad numérico Popularidad de la canción en Spotify medida en una escala de 0 (baja) a 100 (alta).
duracion_ms numérico Duración de la canción en milisegundos.
explicito factor Indica si la canción contiene contenido explícito: 0 = no contiene, 1 = contiene.
Variables de audio
bailabilidad numérico Grado en que una canción es adecuada para bailar. Rango: 0.0 a 1.0.
energia numérico Medida de intensidad y actividad percibida de la canción. Rango: 0.0 a 1.0.
tonalidad factor Tonalidad musical estimada de la canción, codificada de 0 a 11.
sonoridad numérico Sonoridad promedio de la canción en decibeles (dB).
modo factor Modalidad musical de la canción: 0 = menor, 1 = mayor.
presencia_habla numérico Medida de presencia de palabras habladas en la canción. Rango: 0.0 al 1.0.
acusticidad numérico Medida de confianza de que la canción sea acústica. Rango: 0.0 a 1.0.
instrumentalidad numérico Probabilidad de que la canción no contenga voces. Valores cercanos a 1.0 indican que la canción es instrumental.
vivacidad numérico Probabilidad de que la canción haya sido interpretada en vivo. Valores mayores a 0.8 sugieren registros en vivo.
valencia numérico Positividad emocional de la canción. Rango: 0.0 (triste) a 1.00 (feliz).
tempo numérico Velocidad estimada de la canción, medida en beats por minuto (BPM).
compas factor Compás estimado de la canción, representado como número de pulsos por compás.
audio_vars <- Base_spotify_reducida %>%
  select(
    bailabilidad, energia, sonoridad, presencia_habla,
    acusticidad, instrumentalidad, vivacidad,
    valencia, tempo
  )

desc_vars <- Base_spotify_reducida %>%
  select(
    id_cancion, artistas, nombre_album, nombre_cancion,
    genero_musical, popularidad,
    duracion_ms, explicito
  )

skim(Base_spotify_reducida)
Data summary
Name Base_spotify_reducida
Number of rows 3000
Number of columns 20
_______________________
Column type frequency:
character 4
factor 5
numeric 11
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
id_cancion 0 1 22 22 0 2998 0
artistas 0 1 2 171 0 834 0
nombre_album 0 1 1 94 0 1127 0
nombre_cancion 0 1 1 107 0 2329 0

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
explicito 0 1 FALSE 2 0: 2705, 1: 295
tonalidad 0 1 FALSE 12 2: 363, 7: 342, 9: 338, 4: 308
modo 0 1 FALSE 2 1: 1575, 0: 1425
compas 0 1 FALSE 4 4: 2712, 3: 222, 5: 44, 1: 22
genero_musical 0 1 FALSE 3 hea: 1000, reg: 1000, tan: 1000, aco: 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
popularidad 0 1 23.32 19.15 0.00 16.00 21.00 27.00 98.00 ▇▇▁▁▁
duracion_ms 0 1 216054.29 67673.31 56600.00 174210.75 204654.50 243646.50 1534315.00 ▇▁▁▁▁
bailabilidad 0 1 0.57 0.17 0.09 0.45 0.56 0.72 0.96 ▁▅▇▆▃
energia 0 1 0.66 0.25 0.04 0.45 0.71 0.87 1.00 ▁▃▃▆▇
sonoridad 0 1 -6.94 3.47 -27.63 -8.87 -6.00 -4.32 -0.79 ▁▁▂▆▇
presencia_habla 0 1 0.09 0.08 0.02 0.04 0.06 0.11 0.57 ▇▁▁▁▁
acusticidad 0 1 0.34 0.38 0.00 0.00 0.13 0.79 1.00 ▇▁▁▁▃
instrumentalidad 0 1 0.08 0.21 0.00 0.00 0.00 0.01 0.97 ▇▁▁▁▁
vivacidad 0 1 0.23 0.20 0.01 0.10 0.15 0.30 0.99 ▇▃▁▁▁
valencia 0 1 0.54 0.22 0.04 0.37 0.55 0.71 0.97 ▂▆▇▇▅
tempo 0 1 120.01 29.12 50.96 97.00 116.71 135.04 214.02 ▁▇▆▂▁
# 1. Crear base analítica sin NA
datos_pca <- Base_spotify_reducida %>%
  select(
    genero_musical,
    bailabilidad, energia, sonoridad, presencia_habla,
    acusticidad, instrumentalidad, vivacidad,
    valencia, tempo
  ) %>%
  drop_na()

audio_vars <- datos_pca %>%
  select(-genero_musical)

# 2. Correlaciones
cor_matrix <- cor(audio_vars)
corrplot(cor_matrix, method = "color", type = "upper", tl.cex = 0.8)

# 3. Adecuación para PCA
cortest.bartlett(cor_matrix, n = nrow(audio_vars))
## $chisq
## [1] 9388.559
## 
## $p.value
## [1] 0
## 
## $df
## [1] 36
# 4. PCA
pca_model <- prcomp(audio_vars, center = TRUE, scale. = TRUE)
summary(pca_model)
## Importance of components:
##                           PC1    PC2    PC3    PC4     PC5     PC6     PC7
## Standard deviation     1.6248 1.3347 1.0478 1.0053 0.91908 0.88823 0.64524
## Proportion of Variance 0.2933 0.1979 0.1220 0.1123 0.09386 0.08766 0.04626
## Cumulative Proportion  0.2933 0.4913 0.6133 0.7256 0.81943 0.90709 0.95335
##                            PC8     PC9
## Standard deviation     0.57300 0.30255
## Proportion of Variance 0.03648 0.01017
## Cumulative Proportion  0.98983 1.00000
fviz_eig(pca_model, addlabels = TRUE)

# 5. Loadings
loadings <- as.data.frame(pca_model$rotation)

loadings %>%
  rownames_to_column("variable") %>%
  select(variable, PC1, PC2)
##           variable         PC1         PC2
## 1     bailabilidad -0.02211139  0.65051734
## 2          energia -0.57618984 -0.07758220
## 3        sonoridad -0.52528240  0.16118951
## 4  presencia_habla -0.08723601  0.24556986
## 5      acusticidad  0.54583553  0.08936697
## 6 instrumentalidad  0.23465093 -0.20370207
## 7        vivacidad -0.05885484 -0.31903619
## 8         valencia  0.08063737  0.57332486
## 9            tempo -0.14498575 -0.06749146
# 6. Scores
pca_scores <- as.data.frame(pca_model$x) %>%
  mutate(genero_musical = datos_pca$genero_musical)

# 7. Visualización PCA por género
ggplot(pca_scores, aes(PC1, PC2, color = genero_musical)) +
  geom_point(alpha = 0.5, size = 1.8) +
  theme_minimal()

# 8. Clustering
vars_scaled <- scale(audio_vars)

fviz_nbclust(vars_scaled, kmeans, method = "wss")

fviz_nbclust(vars_scaled, kmeans, method = "silhouette")

# 8. Clustering con K = 3

set.seed(123)

kmeans_model <- kmeans(
  vars_scaled,
  centers = 3,
  nstart = 25
)


# 10. Agregar clusters a las bases

pca_scores$cluster <- factor(kmeans_model$cluster)
datos_pca$cluster <- factor(kmeans_model$cluster)

# 11. Tamaño de cada cluster

datos_pca %>%
  count(cluster) %>%
  mutate(prop_porcentaje = round(n / sum(n) * 100, 1))
## # A tibble: 3 × 3
##   cluster     n prop_porcentaje
##   <fct>   <int>           <dbl>
## 1 1        1020            34  
## 2 2        1000            33.3
## 3 3         980            32.7
# 12. Visualizar clusters sobre PC1 y PC2

ggplot(pca_scores, aes(x = PC1, y = PC2, color = cluster)) +
  geom_point(alpha = 0.5, size = 1.8) +
  theme_minimal() +
  labs(
    title = "Clusters acústicos proyectados sobre PC1 y PC2",
    x = "PC1: energía acústica",
    y = "PC2: bailabilidad / valencia",
    color = "Cluster"
  )

# 13. Relación entre cluster y género

cluster_genero <- datos_pca %>%
  count(cluster, genero_musical) %>%
  group_by(cluster) %>%
  mutate(
    prop = n / sum(n),
    prop_porcentaje = round(prop * 100, 1)
  ) %>%
  arrange(cluster, desc(prop))

cluster_genero
## # A tibble: 9 × 5
## # Groups:   cluster [3]
##   cluster genero_musical     n    prop prop_porcentaje
##   <fct>   <fct>          <int>   <dbl>           <dbl>
## 1 1       reggaeton        947 0.928              92.8
## 2 1       heavy-metal       37 0.0363              3.6
## 3 1       tango             36 0.0353              3.5
## 4 2       heavy-metal      940 0.94               94  
## 5 2       reggaeton         45 0.045               4.5
## 6 2       tango             15 0.015               1.5
## 7 3       tango            949 0.968              96.8
## 8 3       heavy-metal       23 0.0235              2.3
## 9 3       reggaeton          8 0.00816             0.8

## # A tibble: 3 × 10
##   cluster bailabilidad energia sonoridad presencia_habla acusticidad
##   <fct>          <dbl>   <dbl>     <dbl>           <dbl>       <dbl>
## 1 1              1.03    0.325     0.576           0.381      -0.425
## 2 2             -0.821   0.843     0.382          -0.220      -0.836
## 3 3             -0.233  -1.20     -0.989          -0.172       1.30 
## # ℹ 4 more variables: instrumentalidad <dbl>, vivacidad <dbl>, valencia <dbl>,
## #   tempo <dbl>

fviz_pca_biplot(
  pca_model,
  geom.ind = "point",
  habillage = pca_scores$cluster,
  addEllipses = TRUE,
  label = "var",
  repel = TRUE
)