如何删除闪亮的无功输入中的警告

时间:2016-04-06 13:25:34

标签: r shiny

当我在第一个selectInput小部件中更改数据集时,有人能告诉我为什么会出现错误吗?当我将数据集从diamonds更改为mtcars时,我在Could not find 'carat'和版本中得到错误input$bins只有一秒钟,之后一切正常。为什么会这样?

library(shiny)
library(ggplot2)

data(diamonds)
data(mtcars)


ui <- fluidPage(
      column(3,
             selectInput("data", "", choices = c('mtcars', 'diamonds')),
             uiOutput('server_cols'),
             uiOutput('server_bins')
             ),
      column(9,
             plotOutput("plot")
             )


)

server <- function(input, output) {

      data <- reactive({
            switch(input$data,
                   diamonds = diamonds,
                   mtcars = mtcars)
      })

      output$server_cols <- renderUI({
            data <- data()
            nam <- colnames(data)
            selectInput('cols', "Choose numeric columns:", choices = nam[sapply(data, function(x) is.numeric(x))])
      })

      output$server_bins <- renderUI({
            if (!is.null(input$cols)) {
                  df <- data()
                  x <- eval(input$cols)
                  max_value <- max(df[,x])

                  sliderInput('bins','Choose number of bins:', min = 0.1, 
                              max = max_value, 
                              value = max_value/2) 
            }
      })

      output$plot <- renderPlot({
            if (!is.null(input$cols) & !is.null(input$bins)) {
                  basicData <- data()
                  var <- eval(input$cols)

                  ggplot(basicData, aes_string(var)) +
                              geom_histogram(binwidth = input$bins, color = 'white', fill = 'red')
            }    

      })

}

shinyApp(ui, server)

1 个答案:

答案 0 :(得分:1)

Your respective output objects respond to any changes of your input variables. Thus, when you change your dataset via input$data, the plot rebuilds itself, although input$cols did not yet adjust. Actually, try inserting some print("a") inside the output$plot to see that it is called up to three times if you change input$data.

The fix is to rethink your reaction logic and let your elements respond only to specific changes, to get some kind of response "thread".

For example, input$data should only trigger output$server_cols. And output$server_bins should only be triggered by input$cols (because this already implies that input$data changed earlier). Ultimately, output$plot just has to listen to changes of input$bins (because changes in input$cols and input$data always result in changes of input$bins since it is at the end of the thread).

Here is my suggestion using isolate.

library(shiny)
library(ggplot2)

data(diamonds)
data(mtcars)


ui <- fluidPage(
  column(3,
    selectInput("data", "", choices = c('mtcars', 'diamonds')),
    uiOutput('server_cols'),
    uiOutput('server_bins')
   ),
   column(9,
     plotOutput("plot")
   )    
)

server <- function(input, output) {

  data <- reactive({
    switch(input$data, diamonds = diamonds, mtcars = mtcars)
  })

  output$server_cols <- renderUI({
    data <- data()
    nam <- colnames(data)
    selectInput('cols', "Choose numeric columns:", choices = nam[sapply(data, function(x) is.numeric(x))])
  })

  output$server_bins <- renderUI({
    if (!is.null(input$cols)) {
      df <- isolate(data())
      x <- eval(input$cols)
      max_value <- max(df[,x])

      sliderInput('bins','Choose number of bins:', min = 0.1, max = max_value, value = max_value/2) 
    }
  })

  output$plot <- renderPlot({
    if (!is.null(isolate(input$cols)) & !is.null(input$bins)) {
      basicData <- isolate(data())
      var <- eval(isolate(input$cols))

      ggplot(basicData, aes_string(var)) +
        geom_histogram(binwidth = input$bins, color = 'white', fill = 'red')
    }    
  })    
}

shinyApp(ui, server)

You might also want to look into updateSelectInput and updateSliderInput if you want to alter Input Elements depending on other input.