49882

Reactive SelectInput (Dataset Unknown until API call from Previous Filter)

Question:

I am creating a shiny app that will do the following using Spotify's API:

1) You manually type in the Artist Name

<strong>2) In the selectInput, the albums need to automatically populate for your selection.</strong>

3) After selecting the album, a table in the main panel will show the songs, artist, and album.

I have this working so far but I cannot figure out how to do the 2nd part which is to automatically populate the albums once the artist is selected. I asked a previous question here: <a href="https://stackoverflow.com/questions/46348193/shiny-automatic-selectinput-value-update-based-on-previous-filter" rel="nofollow">Shiny: Automatic SelectInput Value Update Based on Previous Filter</a> but I realized that after asking the question, the dataset will not be known in the beginning for you to reference in the ui.

So instead of doing this:

selectInput("selectinputid", "Album #1 to Select:", choices = c("Yeezus" = "Yeezus", "Graduation" = "Graduation", "Gears" = "gear"))

I want to do this:

selectInput("selectinputid", "Album #1 to Select:", choices = unique(with_album_name$`Album Name`)

Here is the code:

# ui.R library(shiny) shinyUI(fluidPage( titlePanel("Spotify: Interactive Song Selection"), sidebarLayout( sidebarPanel( helpText("The goal from this is for you to compare two artists' albums and see how similar the songs are based on the audio features."), helpText("Select your first artist you want to compare. For example: ", tags$b("Kanye West")), textInput("albumId", "Artist Name #1", value = "", width = NULL, placeholder = NULL), actionButton("goButton", "Submit Both Artists"), helpText("Based on the artist you selected, now select the albums that you want to compare songs for."), selectInput("selectinputid", "Album #1 to Select:", choices = c("Yeezus" = "Yeezus", "Graduation" = "Graduation", "Gears" = "gear")), actionButton("goButton1", "Submit Both Albums")), mainPanel( tableOutput("result") ) ) ))

Server Section:

# server.R spotifyKey <- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" spotifySecret <- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" library("httr") library("jsonlite") library(ggplot2) library(scales) library(dplyr) response = POST( 'https://accounts.spotify.com/api/token', accept_json(), authenticate(spotifyKey, spotifySecret), body = list(grant_type = 'client_credentials'), encode = 'form', verbose() ) token = content(response)$access_token HeaderValue = paste0('Bearer ', token) library(shiny) shinyServer(function(input, output) { output$result <- renderTable({ randomVals <- eventReactive(input$goButton, input$albumId) spotify <- c(randomVals()) ##Retrieve Artist ID get.artist <- function(spotify){ artistnameURL <- paste("https://api.spotify.com/v1/search?q=", spotify, "&type=artist", sep="") getArtist <- GET(artistnameURL, add_headers(Authorization = HeaderValue)) artistname <- jsonlite::fromJSON(toJSON(content(getArtist))) ids <- data.frame(matrix(unlist(artistname$artists$items$id), nrow=artistname$artists$total, byrow=T),stringsAsFactors=FALSE) names <- data.frame(matrix(unlist(artistname$artists$items$name), nrow=artistname$artists$total, byrow=T),stringsAsFactors=FALSE) colnames(ids)[1]<-"Artist ID" colnames(names)[1]<-"Artist Name" artist_search <- cbind(names, ids) artist_search <- artist_search[1,] return(artist_search) } df1 <- lapply(spotify, get.artist) result2 <- do.call(rbind, df1) result2_final<-result2 ids<-result2_final$`Artist ID` ##Retrieve Artist Albums get.albums <- function(ids){ artists_albumsURL <- paste("https://api.spotify.com/v1/artists/", ids, "/albums", sep="") getArtistAlbum <- GET(artists_albumsURL, add_headers(Authorization = HeaderValue)) artistalbumname <- jsonlite::fromJSON(toJSON(content(getArtistAlbum))) albumids <- data.frame(matrix(unlist(artistalbumname$items$id), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) albumnames <- data.frame(matrix(unlist(artistalbumname$items$name), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) artistid2 <- data.frame(matrix(unlist(artistalbumname$items$artists[[1]]$id), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) artistname2 <- data.frame(matrix(unlist(artistalbumname$items$artists[[1]]$name), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) colnames(albumids)[1]<-"Album IDs" colnames(albumnames)[1]<-"Album Name" colnames(artistid2)[1]<-"Artist ID" colnames(artistname2[1])<-"Artist Name" album_search <- cbind(artistid2, artistname2, albumnames, albumids) album_search <- unique(album_search) return(album_search) } df <- lapply(ids, get.albums) result <- do.call(rbind, df) result_final<-result colnames(result_final)[2]<-"Artist Name" spotify<-result_final$`Album IDs` get.tracks <- function(spotify){ albumTracksURL <- paste("https://api.spotify.com/v1/albums/", spotify, "/tracks?limit=50", sep="") getTracks <- GET(albumTracksURL, add_headers(Authorization = HeaderValue)) albumTracks <- jsonlite::fromJSON(toJSON(content(getTracks))) ids <- data.frame(matrix(unlist(albumTracks$items$id), nrow=albumTracks$total, byrow=T),stringsAsFactors=FALSE) names <- data.frame(matrix(unlist(albumTracks$items$name), nrow=albumTracks$total, byrow=T),stringsAsFactors=FALSE) artists<-albumTracks$items$artists artists1<-do.call(rbind, lapply(artists, function(x) do.call(cbind, lapply(x[c('id', 'name')], toString)))) result <- cbind(ids, names, artists1) colnames(result) <- c("ID", "NAME", "ARTIST ID", "ARTIST NAME") result$AlbumID <- spotify return(result) } df <- lapply(spotify, get.tracks) result <- do.call(rbind, df) result_final2<-result names(result_final2) <- c("ID", "NAME", "ARTIST ID", "ARTIST NAME") final<-result_final2 final1<-final[!duplicated(final), ] final2 <- final1[!duplicated(final1[2:5]),] colnames(final2)[5]<-"Album ID" with_album_name<-left_join(final2,result_final, by=c("Album ID" = "Album IDs")) with_album_name <- with_album_name[,-c(6:7)] ##target <- c(input$selectinputid) randomVals2 <- eventReactive(input$goButton1, input$selectinputid) target <- c(randomVals2()) result_final<-filter(with_album_name, `Album Name` %in% target) final2<-result_final final2 })})

Output:

<a href="https://i.stack.imgur.com/l51NV.jpg" rel="nofollow"><img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/l51NV.jpg" data-original="https://i.stack.imgur.com/l51NV.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

In the ui part, I need to find a way to reference the with_album_name table, but that table is created in the server section. Not sure how this can be done because right now all I have is to manually put in the album names for selection and that will not work when I want to reference a different artist in the spotify database.

Answer1:

I overwrote your server part:

<ul><li>

moved all functions out of it (I prefer to keep my server function in a separate file);

</li> <li>

Restructured server code: all code was returning single table. I now added observeEvent to update list

</li> </ul>

Minor changes in selectInput part:

selectInput("selectinputid", "Album #1 to Select:", "")

Server part:

server <- function(input, output, session) { ids <- reactive({ randomVals <- eventReactive(input$goButton, input$albumId) spotify <- c(randomVals()) df1 <- lapply(spotify, get.artist) result2 <- do.call(rbind, df1) result2_final<-result2 result2_final$`Artist ID` }) result_final <- reactive({ df <- lapply(ids(), get.albums) result <- do.call(rbind, df) colnames(result)[2]<-"Artist Name" result }) # Observes and updates album selection part observe({ albums <- unique(result_final()$`Album Name`) updateSelectInput(session, "selectinputid", label = "selectinputid", choices = albums, selected = albums[1]) }) output$result <- renderTable({ spotify<-result_final()$`Album IDs` df <- lapply(spotify, get.tracks) result <- do.call(rbind, df) result_final2<-result names(result_final2) <- c("ID", "NAME", "ARTIST ID", "ARTIST NAME") final<-result_final2 final1<-final[!duplicated(final), ] final2 <- final1[!duplicated(final1[2:5]),] colnames(final2)[5]<-"Album ID" with_album_name<-left_join(final2,result_final(), by=c("Album ID" = "Album IDs")) with_album_name <- with_album_name[,-c(6:7)] randomVals2 <- eventReactive(input$goButton1, input$selectinputid) target <- c(randomVals2()) result_final<-filter(with_album_name, `Album Name` %in% target) final2<-result_final final2 }) }

All code (messy):

library(shiny) ui <- fluidPage( titlePanel("Spotify: Interactive Song Selection"), sidebarLayout( sidebarPanel( helpText("The goal from this is for you to compare two artists' albums and see how similar the songs are based on the audio features."), helpText("Select your first artist you want to compare. For example: ", tags$b("Kanye West")), textInput("albumId", "Artist Name #1", value = "", width = NULL, placeholder = NULL), actionButton("goButton", "Submit Both Artists"), helpText("Based on the artist you selected, now select the albums that you want to compare songs for."), selectInput("selectinputid", "Album #1 to Select:", ""), actionButton("goButton1", "Submit Both Albums")), mainPanel( tableOutput("result") ) ) ) spotifyKey <- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" spotifySecret <- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" library("httr") library("jsonlite") library(ggplot2) library(scales) library(dplyr) response = POST( 'https://accounts.spotify.com/api/token', accept_json(), authenticate(spotifyKey, spotifySecret), body = list(grant_type = 'client_credentials'), encode = 'form', verbose() ) token = content(response)$access_token HeaderValue = paste0('Bearer ', token) get.artist <- function(spotify){ artistnameURL <- paste("https://api.spotify.com/v1/search?q=", spotify, "&type=artist", sep="") getArtist <- GET(artistnameURL, add_headers(Authorization = HeaderValue)) artistname <- jsonlite::fromJSON(toJSON(content(getArtist))) ids <- data.frame(matrix(unlist(artistname$artists$items$id), nrow=artistname$artists$total, byrow=T),stringsAsFactors=FALSE) names <- data.frame(matrix(unlist(artistname$artists$items$name), nrow=artistname$artists$total, byrow=T),stringsAsFactors=FALSE) colnames(ids)[1]<-"Artist ID" colnames(names)[1]<-"Artist Name" artist_search <- cbind(names, ids) artist_search <- artist_search[1,] return(artist_search) } get.albums <- function(ids){ artists_albumsURL <- paste("https://api.spotify.com/v1/artists/", ids, "/albums", sep="") getArtistAlbum <- GET(artists_albumsURL, add_headers(Authorization = HeaderValue)) artistalbumname <- jsonlite::fromJSON(toJSON(content(getArtistAlbum))) albumids <- data.frame(matrix(unlist(artistalbumname$items$id), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) albumnames <- data.frame(matrix(unlist(artistalbumname$items$name), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) artistid2 <- data.frame(matrix(unlist(artistalbumname$items$artists[[1]]$id), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) artistname2 <- data.frame(matrix(unlist(artistalbumname$items$artists[[1]]$name), nrow=artistalbumname$total, byrow=T),stringsAsFactors=FALSE) colnames(albumids)[1]<-"Album IDs" colnames(albumnames)[1]<-"Album Name" colnames(artistid2)[1]<-"Artist ID" colnames(artistname2[1])<-"Artist Name" album_search <- cbind(artistid2, artistname2, albumnames, albumids) album_search <- unique(album_search) return(album_search) } get.tracks <- function(spotify){ albumTracksURL <- paste("https://api.spotify.com/v1/albums/", spotify, "/tracks?limit=50", sep="") getTracks <- GET(albumTracksURL, add_headers(Authorization = HeaderValue)) albumTracks <- jsonlite::fromJSON(toJSON(content(getTracks))) ids <- data.frame(matrix(unlist(albumTracks$items$id), nrow=albumTracks$total, byrow=T),stringsAsFactors=FALSE) names <- data.frame(matrix(unlist(albumTracks$items$name), nrow=albumTracks$total, byrow=T),stringsAsFactors=FALSE) artists<-albumTracks$items$artists artists1<-do.call(rbind, lapply(artists, function(x) do.call(cbind, lapply(x[c('id', 'name')], toString)))) result <- cbind(ids, names, artists1) colnames(result) <- c("ID", "NAME", "ARTIST ID", "ARTIST NAME") result$AlbumID <- spotify return(result) } server <- function(input, output, session) { ids <- reactive({ randomVals <- eventReactive(input$goButton, input$albumId) spotify <- c(randomVals()) df1 <- lapply(spotify, get.artist) result2 <- do.call(rbind, df1) result2_final<-result2 result2_final$`Artist ID` }) result_final <- reactive({ df <- lapply(ids(), get.albums) result <- do.call(rbind, df) colnames(result)[2]<-"Artist Name" result }) # Observes and updates album selection part observe({ albums <- unique(result_final()$`Album Name`) updateSelectInput(session, "selectinputid", label = "selectinputid", choices = albums, selected = albums[1]) }) output$result <- renderTable({ spotify<-result_final()$`Album IDs` df <- lapply(spotify, get.tracks) result <- do.call(rbind, df) result_final2<-result names(result_final2) <- c("ID", "NAME", "ARTIST ID", "ARTIST NAME") final<-result_final2 final1<-final[!duplicated(final), ] final2 <- final1[!duplicated(final1[2:5]),] colnames(final2)[5]<-"Album ID" with_album_name<-left_join(final2,result_final(), by=c("Album ID" = "Album IDs")) with_album_name <- with_album_name[,-c(6:7)] randomVals2 <- eventReactive(input$goButton1, input$selectinputid) target <- c(randomVals2()) result_final<-filter(with_album_name, `Album Name` %in% target) final2<-result_final final2 }) } shinyApp(ui, server)

Recommend

  • After creating an executable ShinyApp when Rendering Rmarkdown Stops in R
  • sql and linq query
  • R Shiny: object 'input' not found
  • R Shiny: Creating New Columns Within a Reactive Data Frame
  • User must have accepted TOS - Facebook Graph API error when posting photos to group page
  • Plupload set album name before upload
  • no such table: tablename in sqlite even after initialization
  • Using Shiny actionButton() function in onRender() function of htmlWidgets
  • Direction of target annotation when outside of visible area
  • mapping joda timezone to windows timezone (for example in C#)
  • Bootstrap navbar transparent
  • how to add horizontal scroll bar to a panel In ExtJs?
  • Binding a custom handler twice in knockoutjs
  • Alert prompt to function not working in react native
  • Get photos from a Google+ album, in JSON format
  • Textfield Mandatory On basis of radio button selection- Yii2
  • Facebook Graph API: Permissions to Friends Photos
  • Yii2: Using Kartik Depdrop Widget?
  • Kivy, TypeError: 'NoneType' object has no attribute '__getitem__'
  • How to Add Polymorphic Comments to Feed?
  • Xaml, wpf image position and crop issue
  • Getting different value with placeholder over CPU/GPU
  • Yii2: Config params vs. const/define
  • $wpdb not working in file of WordPress plugin
  • why overloaded new operator is calling constructor even I am using malloc inside overloading functio
  • how to adjust image in a panel in Java swing?
  • Why value captured by reference in lambda is broken? [duplicate]
  • Possible to stop flickering java tooltip in heavyweight mode?
  • output of program is not same as passed argument
  • How to show dropdown in excel using jrxml (jasper api)?
  • Akka Routing: Reply's send to router ends up as dead letters
  • Linker errors when using intrinsic function via function pointer
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • NSLayoutConstraint that would pin a view to the bottom edge of a superview
  • How get height of the a view with gone visibility and height defined as wrap_content in xml?
  • LevelDB C iterator
  • python draw pie shapes with colour filled
  • unknown Exception android
  • Checking variable from a different class in C#
  • How can i traverse a binary tree from right to left in java?