spotify = read.csv("dataset.csv")

# Data selection and cleaning
genreAvg = spotify %>%
  group_by(track_genre) %>%
  summarise(popularity = mean(popularity),
            energy = mean(energy),
            loudness = mean(loudness),
            tempo = mean(tempo),
            .groups = 'drop')

# Do some PCA
genreScaled = genreAvg %>%
  column_to_rownames("track_genre") %>%
  scale()

pca_result = prcomp(genreScaled)
scores = data.frame(pca_result$x) %>%
  rownames_to_column("track_genre")

scores$cluster = factor(kmeans(scores[,2:3], centers = 10)$cluster)

fullData = left_join(scores, genreAvg, by = "track_genre")

# Set up Shiny UI
ui = fluidPage(
  titlePanel("Spotify Genre PCA Visualization"),
  mainPanel(
    plotlyOutput("pcaPlot"),
    h3("Genre Features"),
    DTOutput("genreTable")
  )
)

# Set up shinny Server
server = function(input, output, session) {
  
  output$pcaPlot = renderPlotly({
    gg = ggplot(fullData, aes(x = PC1, y = PC2, color = cluster)) +
      geom_point(aes(text = track_genre), size = 2) +   
      theme_minimal(base_size = 14) +
      scale_color_brewer(palette = "Set3") +
      theme(legend.position = "none") +
      labs(title = "PCA of Spotify Track Genres",
           x = "PC1", y = "PC2")
    
    ggplotly(gg, tooltip = "text") %>%
      layout(dragmode = "select")
  })
  
  selected_genres = reactive({
    eventdata <- event_data("plotly_selected")
    if (is.null(eventdata)) {
      return(NULL)
    } else {
      fullData$track_genre[eventdata$pointNumber + 1]  
      # +1 because R is 1-indexed and plotly is 0-indexed!
    }
  })
  
  output$genreTable = renderDT({
    req(selected_genres())
    fullData %>%
      filter(track_genre %in% selected_genres()) %>%
      select(track_genre, popularity, energy, loudness, tempo)
  })
}

shinyApp(ui, server)
Shiny applications not supported in static R Markdown documents