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