2

我正在 Shiny 中构建我的第一个应用程序,我一直想更好地了解反应性。我已经浏览了http://shiny.rstudio.com/tutorial/上的教程。我正在研究一个与网球相关的数据集,并希望使用“radarchart”包创建一个雷达图。我能够使用反应式表达式成功呈现单选按钮并选择输入框。

然而,点击“开始!” 按钮,控制台显示以下错误:“filter_impl 中的错误:长度不正确 (0),预期:27”。不过,应用程序本身没有显示错误,点击“开始!”时没有渲染 按钮。

调试时,我看到当我尝试使用用户选择的输入值(server.R 中的第 60-63 行)过滤数据时发生此错误。我主要关心的是根据用户的选择过滤数据,我无法以任何方式做到这一点。我也尝试过使用 eventReactive()、observe() 以及 reactiveValues() 函数,但没有成功。我已将 renderChartJSRadar 函数包装在 eventReactive 函数中,但我不太确定这是否是正确的方法。

我对这种情况下的反应性应该如何工作以及我缺少什么使其工作感到困惑。代码如下所示。我真的很感激任何帮助。

用户界面

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

服务器.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)
     })
  })

 })

图表.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
}
4

1 回答 1

1

为了简化调试,我将您的应用程序放在一个文件中。

菜单显示正确:闪亮的部分应该可以工作。基本思想是输入变量已经是反应性的,因此用它们构建反应性函数是多余的(至少在这种情况下)。

renderChartJSRadarz,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. 在上面的代码中,只有对 input$button 的更改才会触发renderChartJSRadar.

于 2017-04-02T14:33:24.200 回答