R Shiny中的反应式编码 - 导致这些分秒错误消息的原因是什么?

时间:2017-11-20 19:31:38

标签: r shiny

下面是我的闪亮应用程序中使用的代码的演示 - 它包含了我的完整应用程序的所有重要元素,最重要的是,我的问题被重现。

我闪亮的应用程序的一个重要部分是,只有当另一个窗口小部件设置为某个值时,才会显示某些窗口小部件。在这种情况下,shotchart.input是主窗口小部件,然后只有在shotchart.input设置为特定值时才会出现playerseason.input和teamgame.input窗口小部件。在我的UI中,我在uiOutput()函数中传递了这些第二和第三个小部件。

在我的服务器中,我也为这两个小部件中的每一个都有了renderUI函数。这些小部件的下拉选项取决于对我的主数据帧的某些过滤(不是在我的示例中,而是在我的主应用程序中),因此在服务器中创建这些小部件非常重要。

我的问题如下 - 当我启动应用程序时,暂时存在“非字符参数”错误。然后,当我将第一个小部件的值更改为Shot Marker Graph(团队游戏)时,我得到另一个分秒错误,这次“结果必须长度为20,而不是0”。

我认为这是因为,在我的renderPlotly()函数中,我有这样的代码行:

fname <- strsplit(input$player.id, split = ' ')[[1]][1]

和其他小部件

this.t2 <- input$team.id
all.pbp <- all.pbp %>% filter(team == this.t2) 

依赖于反应输入参数输入$ player.id并输入$ team.id。我的想法是这些输入参数需要大约1秒来获取值,因此在启动应用程序和切换主窗口小部件时会很快发生这些错误。

从用户体验的角度来看,这些错误看起来很糟糕,更重要的是,让我觉得我在这里没有正确使用renderUI和uiOutput。任何关于如何摆脱这些分裂错误消息/更好的编码实践的想法将不胜感激。谢谢!

以下应用程序:

# Pre-Processing 
all.pbp <- structure(list(team = c("BOS", "CLE", "BOS", "CLE", "BOS", "BOS", 
                                   "CLE", "CLE", "BOS", "CLE", "BOS", "CLE", "BOS", "CLE", "BOS", 
                                   "BOS", "CLE", "BOS", "BOS", "BOS"), lastname = c("Irving", "Rose", 
                                        "Hayward", "Love", "Tatum", "Horford", "Crowder", "Wade", "Brown", 
                                        "Rose", "Hayward", "Rose", "Irving", "Wade", "Irving", "Brown", 
                                        "Crowder", "Horford", "Brown", "Brown"), firstname = c("Kyrie", 
                                               "Derrick", "Gordon", "Kevin", "Jayson", "Al", "Jae", "Dwyane", 
                                               "Jaylen", "Derrick", "Gordon", "Derrick", "Kyrie", "Dwyane", 
                                               "Kyrie", "Jaylen", "Jae", "Al", "Jaylen", "Jaylen"), yloc = c(789L, 
                                                     55L, 751L, 134L, 866L, 699L, 107L, 86L, 883L, 62L, 798L, 296L, 
                                                     858L, 66L, 768L, 873L, 309L, 667L, 748L, 876L), xloc = c(251L, 
                                                          232L, 464L, 119L, 240L, 203L, 467L, 133L, 261L, 245L, 259L, 346L, 
                                                          257L, 398L, 141L, 248L, 197L, 133L, 468L, 255L)), .Names = c("team", 
                                                         "lastname", "firstname", "yloc", "xloc"), class = "data.frame", row.names = c(NA, 20L))

shotchart.types <- c('Shot Marker Graph (Player-Season)', 'Shot Marker Graph (Team-Game)')
names(shotchart.types) <- shotchart.types

# The UI
ui <- fluidPage(fluidRow(
                  column(width = 3, align = 'center',
                         h3('Chart Type'), hr(),

                         # create permanent input for shot chart type (should be 5 options)
                         selectInput(inputId = 'shotchart.input', label = 'Select Shot Chart Type:', multiple = FALSE,
                                     choices = shotchart.types, selected = 'Shot Marker Graph (Player-Season)'),

                         uiOutput('playerseason.input'),
                         uiOutput('teamgame.input')
                         ),

                  # 2.C Launch the Chart
                  # ===-===-===-===-===-===
                  column(width = 8, align = 'left',
                         plotlyOutput("shotplot")
                  )
                )
)


# The Server
server <- shinyServer(function(input, output) {

  # 3.A widgets whose appearance is conditional on another widget value
  # ===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===
  # select player for player-season graph
  output$playerseason.input <- renderUI({
    if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {

      all.players <- unique(paste(all.pbp$firstname, all.pbp$lastname))
      names(all.players) <- all.players

      selectInput(inputId = 'player.id', label = 'Select Player:', multiple = FALSE,
                  choices = all.players, selected = 'Kyrie Irving')
    } else{
      return(NULL)
    }
  })

  # select team for team-game graph
  output$teamgame.input <- renderUI({
    if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {

      all.teams <- unique(all.pbp$team)
      names(all.teams) <- all.teams

      selectInput(inputId = 'team.id', label = 'Select Team:', multiple = FALSE,
                  choices = all.teams, selected = 'BOS')

    } else{
      return(NULL)
    }
  })

  # 3.B The Plot
  # ===-===-===-===
  output$shotplot <- renderPlotly({

    # first plot, based on chart type widget
    if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {

      fname <- strsplit(input$player.id, split = ' ')[[1]][1]
      lname <- strsplit(input$player.id, split = ' ')[[1]][2]
      all.pbp <- all.pbp %>% filter(firstname == fname, lastname == lname)
      print(fname);
      print(lname);
      print(all.pbp);

      plot_ly(all.pbp) %>%
        add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
    }

    # second plot, also based on chart type widget
    else if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {

      this.t2 <- input$team.id
      all.pbp <- all.pbp %>% filter(team == this.t2)      

      plot_ly(all.pbp) %>%
        add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
    }

  })
})

shinyApp(ui, server)

1 个答案:

答案 0 :(得分:1)

嗨,这些问题来自输入字段的动态呈现。它们不是在第一次计算图表时启动的。但是一旦启动,情节就会重新计算,一切正常。

Shiny具有函数req只是为了这个目的,你可以测试一个变量是否真实,即有一个值。如果不是,则使用静音警告取消计算。以下是它如何适用于您的情况。我刚刚在两个地方添加了req(),它运行正常。

server <- shinyServer(function(input, output) {

  # 3.A widgets whose appearance is conditional on another widget value
  # ===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===
  # select player for player-season graph
  output$playerseason.input <- renderUI({
    if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {

      all.players <- unique(paste(all.pbp$firstname, all.pbp$lastname))
      names(all.players) <- all.players

      selectInput(inputId = 'player.id', label = 'Select Player:', multiple = FALSE,
                  choices = all.players, selected = 'Kyrie Irving')
    } else{
      return(NULL)
    }
  })

  # select team for team-game graph
  output$teamgame.input <- renderUI({
    if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {

      all.teams <- unique(all.pbp$team)
      names(all.teams) <- all.teams

      selectInput(inputId = 'team.id', label = 'Select Team:', multiple = FALSE,
                  choices = all.teams, selected = 'BOS')

    } else{
      return(NULL)
    }
  })

  # 3.B The Plot
  # ===-===-===-===
  output$shotplot <- renderPlotly({

    # first plot, based on chart type widget
    if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {
      req(input$player.id)
      fname <- strsplit(input$player.id, split = ' ')[[1]][1]
      lname <- strsplit(input$player.id, split = ' ')[[1]][2]
      all.pbp <- all.pbp %>% filter(firstname == fname, lastname == lname)
      print(fname);
      print(lname);
      print(all.pbp);

      plot_ly(all.pbp) %>%
        add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
    }

    # second plot, also based on chart type widget
    else if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {
      req(input$team.id)

      this.t2 <- input$team.id
      all.pbp <- all.pbp %>% filter(team == this.t2)      

      plot_ly(all.pbp) %>%
        add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
    }

  })
})