Reactive SelectInput(数据集未知,直到来自上一过滤器的API调用)

时间:2017-09-21 20:17:08

标签: r shiny shiny-server

我正在使用Spotify的API创建一个闪亮的应用程序:

1)您手动输入艺术家姓名

2)在selectInput中,相册需要自动填充以供选择。

3)选择相册后,主面板中的表格将显示歌曲,艺术家和专辑。

到目前为止,我有这个工作,但我无法弄清楚如何选择艺术家后第二部分自动填充相册。我在这里问了一个上一个问题:Shiny: Automatic SelectInput Value Update Based on Previous Filter但我意识到在提问之后,数据集在开头就不会被你知道了。

所以不要这样做:

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

我想这样做:

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

以下是代码:

# 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.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
   })})

输出:

enter image description here

在ui部分,我需要找到一种引用with_album_name表的方法,但该表是在服务器部分创建的。不知道如何做到这一点,因为现在我只需要手动输入相册名称进行选择,当我想在spotify数据库中引用不同的艺术家时,这将无效。

1 个答案:

答案 0 :(得分:1)

我覆盖了你的服务器部分:

  • 将所有功能移出它(我更喜欢将我的服务器功能保存在一个单独的文件中);

  • 重组服务器代码:所有代码都返回单个表。我现在已将observeEvent添加到更新列表

selectInput部分的细微变化:

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

服务器部分:

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
    })
}

所有代码(凌乱):

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)