R Shiny: how to prevent duplicate plot update with nested selectors?

送分小仙女□ 提交于 2020-01-15 08:37:08

问题


I have a dataset in which every row contains data about single person and every column contains different information about him/her. Let's say it looks like this (but more columns and rows in real data):

data <- data.frame(
  height=runif(1000, 150, 200),
  sex=sample(c("f","m"), 1000, replace=T),
  heir=sample(c("blond", "black", "red", "brown"), 1000, replace=T),
  eye=sample(c("blue", "green", "brown"to show histograms ), 1000, replace=T)
)

I want to make a Shiny app in which I could select a category (column) and a value and draw a histogram of height among people who share this value. For example for category = 'sex' and value = 'f' I would like to have a histogram of height among woman. Because each category have different set of values, after changing category I have to (automatically) update the value selector too. The problem is that it means two updates and each of them generates new histogram, while only the second one makes any sense. Here is my code:

server.R

shinyServer(function(input, output, session) {

  data <- data.frame(
    height=runif(1000, 150, 200),
    sex=sample(c("f","m"), 1000, replace=T),
    heir=sample(c("blond", "black", "red", "brown"), 1000, replace=T),
    eye=sample(c("blue", "green", "brown"), 1000, replace=T)
    )

  # update value after category change
  observe({
    updateSelectInput(session, "value", "Value",
                      choices=as.list(levels(data[,input$category])))
    cat(paste("category update:",input$category, "\n"), file = stderr())
  })

  output$histogram <- renderPlot({
    cat(paste("hist:", "category =", input$category,
              "value =",input$value, "\n"), file = stderr())
    hist(data[data[, input$category] == input$value, "height"])
  })
})

ui.R

shinyUI(fluidPage(
  sidebarPanel(    
    selectInput("category", "Category", choices=c("sex", "heir", "eye"), selected="sex"),
    selectInput("value", "Value", c("f", "m"), selected="f")
  ),

  mainPanel(
    plotOutput("histogram")
  )
))

The cat expressions makes it easier to see what is going on. When I run the app the default category ('sex') and value ('f') is selected, so the console output is:

category update: sex 
hist: category = sex value = f 

Then, when I choose the different category using the selector, for example heir, I got an information:

category update: heir 
hist: category = heir value = f 
Error in hist.default(data[data[, input$category] == input$value, "height"]): 
  invalid number of 'breaks'
hist: category = heir value = black 

So at first, the app changes the category and tries to plot a histogram for the new category = heir and old value = f, which of course have to fail. Only then it changes the value and then draws correct histogram. Is there any way to automatically update the value selector before any plot is drawn?


回答1:


You can use isolateto avoid dependency of your histogram on input$category:

  output$histogram <- renderPlot({
    cat(paste("hist:", "category =", isolate(input$category),
              "value =",input$value, "\n"), file = stderr())
    hist(data[data[, isolate(input$category)] == input$value, "height"])
  })

Your histogram will no longer be updated when the category changes. Changing the category also changes the value in your app, and the histogram will update when that value is changed.

More info on isolate here.



来源:https://stackoverflow.com/questions/31594052/r-shiny-how-to-prevent-duplicate-plot-update-with-nested-selectors

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!