问题
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