2017-04-02 84 views
2

我在Shiny中構建了我的第一個應用程序,我一直想要更好地瞭解有關反應性的知識。我已經閱讀了關於http://shiny.rstudio.com/tutorial/的教程。我正在研究一個與網球相關的數據集,並希望使用「雷達圖」軟件包創建雷達圖。我能夠呈現單選按鈕並使用反應式表達式成功選擇輸入框。無法使用Shiny中的eventReactive()函數篩選每個用戶的輸入數據

但是,點擊'Go!'後,按鈕,控制檯顯示以下錯誤:「filter_impl中的錯誤:不正確的長度(0),期望:27」。雖然沒有錯誤出現在應用程序本身,但點擊「Go!」時沒有渲染。按鈕。

在調試時,我看到當我嘗試使用用戶選擇的輸入值(server.R中的第60-63行)篩選數據時發生此錯誤。我主要關心的是根據用戶的選擇過濾數據,我無法以任何方式做到這一點。我試圖使用eventReactive(),observe()以及reactiveValues()函數也沒有取得任何成功。我在eventReactive函數中包裝了renderChartJSRadar函數,但我不太確定這是否正確。

我很困惑這種情況下的反應性應該如何工作,以及我錯過了什麼使其工作。代碼如下所示。我非常感謝任何幫助。

ui.R

library(xlsx) 
library(shiny) 
library(dplyr) 
source("chart.R") 
library(radarchart) 

shinyUI(fluidPage(

      titlePanel("Match Radar Chart"), 

      sidebarLayout(
      sidebarPanel(
       selectInput("var", 
         label = "Choose a tournament", 
         choices = tour, 
         selected = "Auckland"), 

       uiOutput("radioButtons"), 
       uiOutput("selectControls"), 
       actionButton("update", "Go!") 
      ), 

       mainPanel(
       chartJSRadarOutput("radarChart", width = "450", height = "300") 
      ) 
     ) 
)) 

server.R

library(xlsx) 
library(dplyr) 
library(radarchart) 
library(data.table) 
source("chart.R") 
library(shiny) 
library(grDevices) 


shinyServer(function(input, output, session) { 

    output$radioButtons <- renderUI({ 
       dataInput <- reactive({input$var}) 
       z <- dataInput() 
       buttons <- numrounds(z) 
       radioButtons("button", "Select a round: ", choices = buttons, inline = FALSE) 
     }) 

    output$selectControls <- renderUI({ 
       dataInput <- reactive({input$var}) 
       z <- dataInput() 
       dataInput1 <- reactive({input$button}) 
       y <- dataInput1() 
       winner <- mydata %>% 
         filter(tourney_name == z) %>% 
         filter(round == y) %>% 
         select(winner_name) %>% 
         sapply(as.character) %>% 
         as.vector() 

       loser <- mydata %>% 
         filter(tourney_name == z) %>% 
         filter(round == y) %>% 
         select(loser_name) %>% 
         sapply(as.character) %>% 
         as.vector() 

       players <- c(winner, loser) 

       selectInput("select", "Select a match: ", choices = players, selected = 1, multiple = FALSE) 

    })  

      output$radarChart <- eventReactive(input$update, { 
      renderChartJSRadar({ 
      dataInput1 <- reactive({input$var}) 
      z <- dataInput1() 
      dataInput2 <- reactive({input$button}) 
      y <- dataInput2() 
      dataInput3 <- reactive({input$select}) 
      x <- dataInput3() 
      match <- mydata %>% 
       filter(tourney_name == z) %>% 
       filter(round == y) %>% 
       filter(winner_name == x) 

      scoresw <- vector() 
      scoresl <- vector() 
      for(j in 25:33) { 
        scoresw <- c(scoresw, match()[j]) 
      } 
      for(j in 34:42) { 
        scoresl <- c(scoresl, match()[j]) 
      } 

      scores <- list(winner = scoresw, loser = scoresl) 
      labs <- c("Aces", "Double Faults", "Service points", "1st Service In", "1st Service won", "2nd Service won", "Service games", "Break points saved", "Break points faced") 
      c <- grDevices::col2rgb(c("green", "red")) 

      chartJSRadar(scores = scores, labs = labs, labelSize = 15, colMatrix = c) 
    }) 
    }) 

}) 

chart.R

mydata <- read.csv("Match Radar/Data/atp_matches_2014_edited.csv", header = TRUE) 
tour <- unique(data$tourney_name) 


numrounds <- function(z) { 
    for(i in 1:64) { 
    rounds <- mydata %>% 
     filter(tourney_name == z) %>% 
     summarise(number = n_distinct(round)) 

    if(rounds == 3){ 
     buttons <- c("RR", "SF", "F") 
    } 
    else if(rounds == 5){ 
     buttons <- c("R32", "R16", "QF", "SF", "F") 
    } 
    else if(rounds == 6){ 
     buttons <- c("R64", "R32", "R16", "QF", "SF", "F") 
    } 
    else { 
     buttons <- c("R128", "R64", "R32", "R16", "QF", "SF", "F") 
    } 
    } 
    buttons 
} 

回答

1

我把你的應用程序在一個單獨的文件爲了簡單調試。

菜單正確顯示:有光澤的部分應該工作。基本思想是輸入變量已經是反應性的,所以構建一個反應函數是多餘的(至少在這種情況下)。

renderChartJSRadar z,y和x被正確初始化(一旦最初的NULL情況被丟棄)。另外renderChartJSRadar已經是反應性的,但由於它是「急切反應性」,所以它在其他值未被設置時開始,因此過濾爲NULL。

renderChartJSRadar在R邏輯中有一些計算得分的調試。目前有一個錯誤:很遺憾,我不能幫助,我不能告訴你想達到什麼 - 我不打網球:)

library(xlsx) 
library(dplyr) 
library(radarchart) 
# library(data.table) 
# source("chart.R") 
library(shiny) 
library(grDevices) 

#------------------------------------------------------------------------------ 

mydata <- read.csv("./data/atp_matches_2014.csv", header = TRUE) 
tour <- unique(mydata$tourney_name) 

numrounds <- function(z) { 
    for(i in 1:64) { 
    rounds <- mydata %>% 
     filter(tourney_name == z) %>% 
     summarise(number = n_distinct(round)) 

    if(rounds == 3){ 
     buttons <- c("RR", "SF", "F") 
    } 
    else if(rounds == 5){ 
     buttons <- c("R32", "R16", "QF", "SF", "F") 
    } 
    else if(rounds == 6){ 
     buttons <- c("R64", "R32", "R16", "QF", "SF", "F") 
    } 
    else { 
     buttons <- c("R128", "R64", "R32", "R16", "QF", "SF", "F") 
    } 
    } 
    return(buttons) 
} 

#------------------------------------------------------------------------------ 

ui <- fluidPage(

    titlePanel("Match Radar Chart"), 

    sidebarLayout(
    sidebarPanel(
     selectInput("var", 
        label = "Choose a tournament", 
        choices = tour, 
        selected = "Auckland"), 

     uiOutput("radioButtons"), 
     uiOutput("selectControls"), 
     actionButton("update", "Go!") 
    ), 

    mainPanel(
     chartJSRadarOutput("radarChart", width = "450", height = "300") 
    ) 
) 
) 

#------------------------------------------------------------------------------ 

server <- function(input, output, session){ 
    session$onSessionEnded({ stopApp }) 

    output$radioButtons <- renderUI({ 
    # dataInput <- reactive({input$var}) 

    z <- input$var 
    buttons <- numrounds(z) 
    radioButtons("button", "Select a round: ", choices = buttons, inline = FALSE) 
    }) 

    output$selectControls <- renderUI({ 

    # dataInput <- reactive({input$var}) 
    z <- input$var 
    # dataInput1 <- reactive({input$button}) 
    y <- input$button #dataInput1() 
    winner <- mydata %>% 
     filter(tourney_name == z) %>% 
     filter(round == y) %>% 
     select(winner_name) %>% 
     sapply(as.character) %>% 
     as.vector() 

    loser <- mydata %>% 
     filter(tourney_name == z) %>% 
     filter(round == y) %>% 
     select(loser_name) %>% 
     sapply(as.character) %>% 
     as.vector() 

    players <- c(winner, loser) 

    selectInput("select", "Select a match: ", choices = players, selected = 1, multiple = FALSE) 

    })  

    output$radarChart <- renderChartJSRadar({ 
    # browser() 
     if(is.null(input$button)) return() 
     if(is.null(input$select)) return() 
     # dataInput1 <- reactive({input$var}) 
     z <- input$var # dataInput1() 
     # dataInput2 <- reactive({input$button}) 
     y <- input$button # dataInput2() 
     # dataInput3 <- reactive({input$select}) 
     x <- input$select # dataInput3() 
     match <- mydata %>% 
     filter(tourney_name == z) %>% 
     filter(round == y) %>% 
     filter(winner_name == x) 

     scoresw <- vector() 
     scoresl <- vector() 
     for(j in 25:33) { 
     scoresw <- c(scoresw, match()[j]) 
     } 
     for(j in 34:42) { 
     scoresl <- c(scoresl, match()[j]) 
     } 

     scores <- list(winner = scoresw, loser = scoresl) 
     labs <- c("Aces", "Double Faults", "Service points", "1st Service In", "1st Service won", "2nd Service won", "Service games", "Break points saved", "Break points faced") 
     c <- grDevices::col2rgb(c("green", "red")) 

     chartJSRadar(scores = scores, labs = labs, labelSize = 15, colMatrix = c) 

    }) 

} 
#------------------------------------------------------------------------------ 

shinyApp(ui, server) 

至於防止雷達圖來繪製每次玩的用戶改變三個輸入中的一個,這可以使用isolate

例如(代碼沒有測試,但它應該工作:))

output$radarChart <- renderChartJSRadar({ 
     if(is.null(input$button)) return() 
     isolate({ 
      if(is.null(input$select)) return() 
      z <- input$var # dataInput1() 
      y <- input$button # dataInput2() 
      x <- input$select # dataInput3() 
     }) 

或者非常類似的東西。以input$var爲例。由於它在isolate之內,用戶的任何更改都不會觸發執行renderChartJSRadar。在上面的代碼中,只有輸入$按鈕的更改觸發執行renderChartJSRadar

+0

我相信問題依然存在,因爲'分數'變量取決於'scoresw'和'scoresl',而這依次取決於被動變量'match()'。我嘗試轉換成'scoresw()','scoresl()'和'scores()',但沒有成功。初始化向量'scoresw'和'scoresl'可能會有問題。我試圖將'scoresw'和'scoresl'初始化爲空向量。每次用戶更改輸入時,「匹配」變量都會更改。你有什麼想法如何結合這個功能,使我的'分數'變量工作?謝謝。 –

+0

此外,謝謝你刪除代碼中的冗餘元素,並在renderchartJSRadar的情況下爲NULL添加過濾,我完全錯過了這一點。我試着運行它,我發現不知何故「分數」變量沒有被正確計算。 –

+0

我真的很感激你的輸入Enzo,我可以通過調整變量'match'來使它工作一點點。事實證明,它不是被動的,所以我不需要使用'match()',也不需要擔心所有後續的反應。我還有最後一個問題(儘管它不是太緊迫) - 我怎麼才能調整我的代碼,只需點擊「Go!」即可更新圖表。按鈕。在我的工作代碼中,事實證明,每次更改三個輸入中的任何一個時,圖表都會更新。如果我只想在用戶點擊「Go!」時更新它,我該怎麼做?按鈕?再次感謝! –

相關問題